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.
