The idea behind the elfparts library is to simplify the process of assembling the various components of an ELF file. The "parts" of an ELF file that the library deals with are largely equivalent to sections, excepting a few of the part types (namely, the ELF header, the program header table, and the section header table itself). The basic process entails filling in a blueprint with the description of what the file will look like, and then proceeding through several stages stages of building up the actual contents, after which the image may be saved to an actual file. A blueprint consists of two pieces of data. The first is the filetype field, which specifies what kind of file to create -- it should be set to ET_REL for an object file, ET_EXEC for an executable, or ET_DYN for a shared library. The second is an array of elfpart structures. This is the parts list. The library exports a number of elfpart structures, covering all the different kinds of structures that appear in ELF files. A user of the elfparts library should begin by creating a blueprint, allocating an array of elfpart structures, and then filling in the array with the desired parts, in the order that they will appear in the ELF image. Each element should be a copy of one of the elfpart structures provided by the library. The first element in the array must be a copy of part_ehdr, providing the ELF header. The array can include multiple entries of a given type, in cases where it makes sense to do so. By copying these elfpart structures into the elements of the parts list, the type of each element is determined. The exported elfpart structures are initialized to default empty values except for the first four fields, which are function pointers. They correspond directly to four of the stages of building up the file image, and are called implicitly by other library functions. The purpose of breaking the process up into multiple stages is to give the caller many opportunities for adding or inserting their content into the various parts. Each stage finalizes one or more aspects of blueprint. Many ELF sections depend on information provided in other sections, and it can be inconvenient to manage the data dependencies between them. The library attempts to relieve the caller of the task of dependency management, while still leaving room for building many different kinds of ELF files. Once a blueprint has been assembled, the caller should call newparts() before doing anything else with it. This function will put each part into an initial state consistent with its type. After calling newparts(), the caller can "connect" parts that need to know about each other. A number of functions are provided for this purpose: * sethashsyms() links a hash section to its dynamic symbol table. * setsymstrings() links a symbol table to the string table containing the symbol's names. * setshdrstrs() sets the string table associated with the section header table. * setrelsyms() links a relocation section to its symbol table. * setrelsection() sets the section that a relocation section's fixups are applied to. (See the commented function declarations in elfparts.h for details.) In addition to the above, the caller may choose to remove parts from the blueprint at this stage by using removepart(). initparts() is called after this is finished, and completes the initialization of the component parts. After this function has returned, the blueprint is initialized and the caller may begin to fill in the actual contents of each part. Several parts are relatively free-form in nature. These are the progbits parts: part_text, part_data, and part_rodata. These types differ only in their permission settings (and their default names). No requirements or expectations are imposed on the contents of these parts, other than that they occupy memory. (Though there is also a part_progbits type that doesn't even do that; its only default purpose is to be present in the image.) The elfpart struct has a field named part, which is a void pointer. When adding data to one of the progbits parts, the caller should set the part field to a buffer containing the contents of that part. In addition, there is a field named size which should be set to the size of the buffer. The other elfpart types are generally not filled in directly by the caller, but are instead built up via library functions: * addtostrtab() adds a string to a string table. * addtosymtab() adds a symbol to a symbol table. * addsymbolrel() adds a relocation to a relocation section. (See the commented functions in elfparts.h for more details.) Some elfpart types, such as part_phdrtab and part_shdrtab, generate their contents automatically by examining the blueprint, and do not require any input from the caller after being added. fillparts() brings the file image to the next stage, and should generally be called after the caller has finished defining the content. This function causes the various parts to add any content that remains to be generated. After this function returns, the size of most parts will be fixed. The caller may continue to change the size of parts of type progbits, but not to anything else. When the caller is ready, the measureparts() function is called next. This function determines the actual positions in the file image for each part, and, if applicable, the addresses for the parts that will be loaded into memory. This information is stored in the offset and addr fields of the elfpart structure. These values cannot be changed after this point. Once measureparts() return, the caller may still modify the data within the contents of various parts (and in fact various bits of information cannot be set until the file offsets and memory addresses are determined). But the caller must not change the size of any part of the blueprint. completeparts() brings the image to the final stage. This function causes the contents of the various parts to take on their final form. After this function returns, the caller may continue to alter data within the parts of type progbits, but only if nothing else in the file is dependent on the changes. Having reached this point, the caller may then use the outputelf() function to output the ELF image to a file.