The basic 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 pretty much 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 should look like, and then proceeding through four stages of gradually building up the actual contents, after which the image may be saved to an actual file. The first piece of data in the blueprint is the filetype field, which specifies the type of file to create. This field should be set to ET_REL for an object file, ET_EXEC for an executable, or ET_DYN for a shared library. The other piece of information in a blueprint structure is an array of elfpart structures. This is the parts list. The caller should allocate the elfpart array, and fill it in with the desired types of parts, in the order that they are to appear in the file. (For example, the first element in the parts list will always be an ELF header.) There can be more than one instance of a given type, presuming that the ELF standard permits it. The library exports a number of elfpart structures. By copying these structures into the elements of the parts list, the type of each element is determined. These structures are empty except for the first four fields, which are function pointers. They correspond directly to the previously mentioned four stages of building up the file image. The caller does not call them directly, however; the library exports four functions, each of which move all the parts in the parts list through the various stages. newparts() is the first function, and is usually called immediately after setting up the blueprint. At this stage, each part sets up its initial state. After calling newparts(), the caller should "attach" parts that need to know about each other. Generally, this means supplying a pointer to one part in the link field of another. The following linkages need to be made: * A hash needs to be linked to the dynamic symbol table (dynsym). * Symbol tables (dynsym or symtab) need to be linked to a string table (dynstr or strtab). * A section header string table (shstrtab) needs to be linked to the section header table (shdrtab). * Relocation section (rel or rela) need to also be linked to a symbol table (symtab). In addition, relocation sections should have their info field set to the index of the part (usually one of the progbits types) that they apply to. Finally, note that if a program header table and/or a section header table is included, then the first part in the parts list must be an ELF header (which should be the case anyway, but these two parts require it). If the caller wishes, they may remove parts from the parts list at this stage by setting the shtype field in the elfpart structure to zero. initparts() is called after this, and completes the initialization of the component parts. This is the second stage. After initparts() has returned, the caller may begin to fill in the actual contents of each part. The parts of type progbits (namely, the types text, data, bss, and progbits) are not filled in by the library; the caller should do that directly. The elfpart field named part is a void pointer, and the caller should use this field to hold a pointer to memory containing the desired contents. Likewise, the size field should contain the content's total size. Alternately, if the contents are an array, the caller can fill in the entsize and count fields instead, which specify the size of each array element and the number of elements respectively. The progbits type itself sets the flags field to PF_R (i.e., read-only). If the caller wants such a part to include the PF_X switch, they should either OR this value in directly, or use the more specific text type. Likewise for the data type and the PF_W (writeable) flag. Currently, the elfparts library does not actually support a proper bss type (i.e., one whose contents are not added to the file). The other part types are not filled in directly, but via functions supplied by the library. See elfparts.h for documentation on these functions. fillparts() brings the file image to the third stage, and should generally be called after the caller has finished adding content. This function causes the various parts to "fill up"; after this function returns, each part will be at the size it will have in the completed file. At this point, the caller may continue to build up the parts of type progbits, but the other parts should already contain everything they need. When the caller is finished, the computeoffsets() function should be called. 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. The computeoffsets() function must be called during this stage. Once this function has been called, the caller may still fill in the actual contents of various parts (and in fact various bits of information cannot be set until the file offsets and memory addresses are known). However, the caller must not add or remove anything from the contents: the size of each part should remain unchanged. completeparts() brings the file image to the fourth and 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 make changes within the parts of type progbits, but only if nothing else in the file is dependent on the changes. At any time after this point, the user may call the outputelf() function. The completed image will be written to the given filename, and the job is done.