ELF_BEGIN(3ELF) ELF Library Functions ELF_BEGIN(3ELF)

NAME


elf_begin, elf_end, elf_memory, elf_next, elf_rand - process ELF
object files

SYNOPSIS


cc [ flag... ] file ... -lelf [ library ... ]
#include <libelf.h>

Elf *elf_begin(int fildes, Elf_Cmd cmd, Elf *ref);


int elf_end(Elf *elf);


Elf *elf_memory(char *image, size_t sz);


Elf_Cmd elf_next(Elf *elf);


size_t elf_rand(Elf *elf, size_t offset);


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.

o 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.

o 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.

o 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.


if (elf_version(EV_CURRENT) == EV_NONE)
{
/* library out of date */
/* recover from error */
}
cmd = ELF_C_READ;
arf = elf_begin(fildes, cmd, (Elf *)0);
while ((elf = elf_begin(fildes, cmd, arf)) != 0)
{
if ((ehdr = elf32_getehdr(elf)) != 0)
{
/* process the file ... */
}
cmd = elf_next(elf);
elf_end(elf);
}
elf_end(arf);


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.


elf_version(EV_CURRENT);
arf = elf_begin(fildes, ELF_C_READ, (Elf *)0);
if (elf_kind(arf) != ELF_K_AR)
{
/* not an archive */
}
/* initial processing */
/* set offset = ... for desired member header */
while (elf_rand(arf, offset) == offset)
{
if ((elf = elf_begin(fildes, ELF_C_READ, arf)) == 0)
break;
if ((ehdr = elf32_getehdr(elf)) != 0)
{
/* process archive member ... */
}
/* set offset = ... for desired member header */
}


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).


#include <ar.h>
#include <libelf.h>
int
rewindelf(Elf *elf)
{
if (elf_rand(elf, (size_t)SARMAG) == SARMAG)
return 0;
return -1;
}


The following outline shows how one might create a new ELF file. This
example is simplified to show the overall flow.


elf_version(EV_CURRENT);
fildes = open("path/name", O_RDWR|O_TRUNC|O_CREAT, 0666);
if ((elf = elf_begin(fildes, ELF_C_WRITE, (Elf *)0)) == 0)
return;
ehdr = elf32_newehdr(elf);
phdr = elf32_newphdr(elf, count);
scn = elf_newscn(elf);
shdr = elf32_getshdr(scn);
data = elf_newdata(scn);
elf_update(elf, ELF_C_WRITE);
elf_end(elf);


Finally, the following outline shows how one might update an existing
ELF file. Again, this example is simplified to show the overall flow.


elf_version(EV_CURRENT);
fildes = open("path/name", O_RDWR);
elf = elf_begin(fildes, ELF_C_RDWR, (Elf *)0);
/* add new or delete old information */
...
/* ensure that the memory image of the file is complete */
elf_update(elf, ELF_C_NULL);
elf_update(elf, ELF_C_WRITE); /* update file */
elf_end(elf);


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).


ATTRIBUTES


See attributes(7) for descriptions of the following attributes:


+--------------------+-----------------+
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
+--------------------+-----------------+
|Interface Stability | Stable |
+--------------------+-----------------+
|MT-Level | MT-Safe |
+--------------------+-----------------+

SEE ALSO


creat(2), lseek(2), mmap(2), open(2), elf(3ELF), elf32_getehdr(3ELF),
elf_cntl(3ELF), elf_getarhdr(3ELF), elf_getarsym(3ELF),
elf_getbase(3ELF), elf_getdata(3ELF), elf_getscn(3ELF),
elf_kind(3ELF), elf_rawfile(3ELF), elf_update(3ELF),
elf_version(3ELF), ar.h(3HEAD), libelf(3LIB), attributes(7)

July 11, 2001 ELF_BEGIN(3ELF)

tribblix@gmail.com :: GitHub :: Privacy