LibElfArchiveCreation

Joseph Koshy

ar(1) archive creation using libelf

We would like applications to be able to create ar(1) archive using libelf.

The new functions and symbols use an ELF_/elf_ prefix to avoid polluting the namespace any more than is being done already by <libelf.h>.

The proposed API changes are as follows:

New Flags

Two new flags, namely ELF_F_ARCHIVE and ELF_F_ARCHIVE_SYSV will be defined in libelf.h for use with elf_flagelf(). These flag an Elf descriptor as being for a new ar(1) archive. These flags are only valid for use with Elf descriptors that were created using ELF_C_WRITE.

The default format for an archive would be the BSD format, using the ELF_F_ARCHIVE_SYSV flag changes that to SYSV style.

New Functions

Three new functions are defined:

  • elf_add_member
  • elf_add_symtab
  • elf_flagarhdr

elf_add_member

off_t
elf_add_member(Elf *ar, ElfArhdr *arhdr, void *data);

This function adds object data to the current archive at the end. The header metadata for the object, in particular the size of data would be in arhdr. The return value is a "tentative" offset that may be used to construct an Elf_Arsym table for the symbols in this object.

The offset is "tentative" because the actual sizes of the string and symbol table members, which must come before the data members themselves, aren't known at this point.

elf_add_symtab

int
elf_add_symtab(Elf *ar, Elf_Arsym *ars, size_t nentries);

This API would add the symbol table ars to the archive. The as_off members for entries will be adjusted at the time the archive is written out to compensate for the size of the symbol table itself and for the archive string table.

elf_flagarhdr

unsigned int
elf_flagarhdr(Elf_Arhdr *a, Elf_Cmd c, unsigned int flags);

Marks an Elf_Arhdr structure as "dirty" for subsequent updation using elf_update().

Other changes

In addition to the above, elf_update() would be augmented to deal with ar(1) archives.

Using the extension

With this API extension, the program flow to create an AR archive would be:

   fd = open("/path/to/archive", O_WRONLY);
   ar = elf_begin(fd, ELF_C_WRITE, NULL);
   elf_flagelf(ar, ELF_C_SET, ELF_F_ARCHIVE); /* creating an archive */

   while (...there are more members to add...) {
         e = ... get a pointer to raw data ...;
         arhdr  = ... fill up the archive header ...;
         off = elf_add_member(ar, &arhdr, e);
         ... fill up members of the arsym array with this tentative
             offset value ..
   }

   elf_add_arsym(ar, arsym, nentries); /* add symbol table */
   elf_update(ar, ELF_C_WRITE); /* and write it out */

Related

Wiki: libelf