Description

The elf_begin(), elf_end(), elf_memory(), elf_next(), and elf_rand() functions work together to process
Executable and Linking Format (ELF) object files, either individually or as members
of archives. After obtaining an ELF descriptor from elf_begin() or elf_memory(), the program
can read an existing file, update an existing file, or create a
new file. The fildes argument is an open file descriptor that elf_begin()
uses for reading or writing. The elf argument is an ELF descriptor
previously returned from elf_begin(). The initial file offset (see lseek(2)) is unconstrained,
and the resulting file offset is undefined.

The cmd argument can take the following values:

ELF_C_NULL

When a program sets cmd to this value, elf_begin() returns a null pointer, without opening a new descriptor. ref is ignored for this command. See the examples below for more information.

ELF_C_READ

When a program wants to examine the contents of an existing file, it should set cmd to this value. Depending on the value of ref, this command examines archive members or entire files. Three cases can occur.

If ref is a null pointer, elf_begin() allocates a new ELF descriptor and prepares to process the entire file. If the file being read is an archive, elf_begin() also prepares the resulting descriptor to examine the initial archive member on the next call to elf_begin(), as if the program had used elf_next() or elf_rand() to ``move'' to the initial member.

If ref is a non-null descriptor associated with an archive file, elf_begin() lets a program obtain a separate ELF descriptor associated with an individual member. The program should have used elf_next() or elf_rand() to position ref appropriately (except for the initial member, which elf_begin() prepares; see the example below). In this case, fildes should be the same file descriptor used for the parent archive.

If ref is a non-null ELF descriptor that is not an archive, elf_begin() increments the number of activations for the descriptor and returns ref, without allocating a new descriptor and without changing the descriptor's read/write permissions. To terminate the descriptor for ref, the program must call elf_end() once for each activation. See the examples below for more information.

ELF_C_RDWR

This command duplicates the actions of ELF_C_READ and additionally allows the program to update the file image (see elf_update(3ELF)). Using ELF_C_READ gives a read-only view of the file, while ELF_C_RDWR lets the program read and write the file. ELF_C_RDWR is not valid for archive members. If ref is non-null, it must have been created with the ELF_C_RDWR command.

ELF_C_WRITE

If the program wants to ignore previous file contents, presumably to create a new file, it should set cmd to this value. ref is ignored for this command.

The elf_begin() function operates on all files (including files with zero bytes),
providing it can allocate memory for its internal structures and read any
necessary information from the file. Programs reading object files can call elf_kind(3ELF)
or elf32_getehdr(3ELF) to determine the file type (only object files have an ELF
header). If the file is an archive with no more members to
process, or an error occurs, elf_begin() returns a null pointer. Otherwise, the
return value is a non-null ELF descriptor.

Before the first call to elf_begin(), a program must call elf_version() to
coordinate versions.

The elf_end() function is used to terminate an ELF descriptor, elf, and
to deallocate data associated with the descriptor. Until the program terminates a
descriptor, the data remain allocated. A null pointer is allowed as an argument,
to simplify error handling. If the program wants to write data associated
with the ELF descriptor to the file, it must use elf_update() before
calling elf_end().

Calling elf_end() removes one activation and returns the remaining activation count. The
library does not terminate the descriptor until the activation count reaches 0.
Consequently, a 0 return value indicates the ELF descriptor is no longer valid.

The elf_memory() function returns a pointer to an ELF descriptor. The ELF
image has read operations enabled ( ELF_C_READ). The image argument is a
pointer to an image of the Elf file mapped into memory. The sz
argument is the size of the ELF image. An ELF image that
is mapped in with elf_memory() can be read and modified, but the
ELF image size cannot be changed.

The elf_next() function provides sequential access to the next archive member. Having
an ELF descriptor, elf, associated with an archive member, elf_next() prepares the
containing archive to access the following member when the program calls elf_begin(). After
successfully positioning an archive for the next member, elf_next() returns the value
ELF_C_READ. Otherwise, the open file was not an archive, elf was NULL,
or an error occurred, and the return value is ELF_C_NULL. In either
case, the return value can be passed as an argument to elf_begin(),
specifying the appropriate action.

The elf_rand() function provides random archive processing, preparing elf to access an
arbitrary archive member. The elf argument must be a descriptor for the
archive itself, not a member within the archive. The offset argument specifies
the byte offset from the beginning of the archive to the archive
header of the desired member. See elf_getarsym(3ELF) for more information about archive member
offsets. When elf_rand() works, it returns offset. Otherwise, it returns 0, because
an error occurred, elf was NULL, or the file was not an archive
(no archive member can have a zero offset). A program can mix
random and sequential archive processing.

System Services

When processing a file, the library decides when to read or write
the file, depending on the program's requests. Normally, the library assumes the
file descriptor remains usable for the life of the ELF descriptor. If,
however, a program must process many files simultaneously and the underlying operating system
limits the number of open files, the program can use elf_cntl() to
let it reuse file descriptors. After calling elf_cntl() with appropriate arguments, the
program can close the file descriptor without interfering with the library.

All data associated with an ELF descriptor remain allocated until elf_end() terminates
the descriptor's last activation. After the descriptors have been terminated, the storage
is released; attempting to reference such data gives undefined behavior. Consequently, a program
that deals with multiple input (or output) files must keep the ELF
descriptors active until it finishes with them.

Examples

Example 1 A sample program of calling the elf_begin() function.

A prototype for reading a file appears on the next page. If
the file is a simple object file, the program executes the loop
one time, receiving a null descriptor in the second iteration. In this
case, both elf and arf will have the same value, the activation count
will be 2, and the program calls elf_end() twice to terminate the
descriptor. If the file is an archive, the loop processes each archive
member in turn, ignoring those that are not object files.

Alternatively, the next example illustrates random archive processing. After identifying the file
as an archive, the program repeatedly processes archive members of interest. For
clarity, this example omits error checking and ignores simple object files. Additionally,
this fragment preserves the ELF descriptors for all archive members, because it does
not call elf_end() to terminate them.

An archive starts with a ``magic string'' that has SARMAG bytes; the
initial archive member follows immediately. An application could thus provide the following
function to rewind an archive (the function returns -1 for errors and
0 otherwise).

Notice that both file creation examples open the file with write and
read permissions. On systems that support mmap(2), the library uses it to enhance
performance, and mmap(2) requires a readable file descriptor. Although the library can
use a write-only file descriptor, the application will not obtain the performance advantages
of mmap(2).