ELF Library Functions elfbegin(3ELF)
NAME
elfbegin, elfend, elfmemory, elfnext, elfrand - process
ELF object files
SYNOPSIS
cc [ flag... ] file ... -lelf [ library ... ]
#include
Elf *elfbegin(int fildes, ElfCmd cmd, Elf *ref);
int elfend(Elf *elf);
Elf *elfmemory(char *image, sizet sz);
ElfCmd elfnext(Elf *elf);
sizet elfrand(Elf *elf, sizet offset);
DESCRIPTION
The elfbegin(), elfend(), elfmemory(), elfnext(), and
elfrand() 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
elfbegin() or elfmemory(), the program can read an exist-
ing file, update an existing file, or create a new file. The
fildes argument is an open file descriptor that elfbegin()
uses for reading or writing. The elf argument is an ELF
descriptor previously returned from elfbegin(). The initial
file offset (see lseek(2)) is unconstrained, and the result-
ing file offset is undefined.
The cmd argument can take the following values:
ELFCNUL When a program sets cmd to this value,
elfbegin() returns a null pointer, without
opening a new descriptor. ref is ignored for
this command. See the examples below for more
information.
ELFCREAD 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.
SunOS 5.11 Last change: 11 Jul 2001 1
ELF Library Functions elfbegin(3ELF)
o If ref is a null pointer,
elfbegin() allocates a new ELF
descriptor and prepares to process
the entire file. If the file being
read is an archive, elfbegin() also
prepares the resulting descriptor to
examine the initial archive member
on the next call to elfbegin(), as
if the program had used elfnext()
or elfrand() to ``move'' to the
initial member.
o If ref is a non-null descriptor
associated with an archive file,
elfbegin() lets a program obtain a
separate ELF descriptor associated
with an individual member. The pro-
gram should have used elfnext() or
elfrand() to position ref appropri-
ately (except for the initial
member, which elfbegin() 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, elfbegin()
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 elfend() once
for each activation. See the exam-
ples below for more information.
ELFCRDWR This command duplicates the actions of
ELFCREAD and additionally allows the pro-
gram to update the file image (see
elfupdate(3ELF)). Using ELFCREAD gives a
read-only view of the file, while ELFCRDWR
lets the program read and write the file.
ELFCRDWR is not valid for archive members.
If ref is non-null, it must have been
created with the ELFCRDWR command.
ELFCWRITE If the program wants to ignore previous file
contents, presumably to create a new file, it
SunOS 5.11 Last change: 11 Jul 2001 2
ELF Library Functions elfbegin(3ELF)
should set cmd to this value. ref is ignored
for this command.
The elfbegin() 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
elfkind(3ELF) or elf32getehdr(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, elfbegin() returns a null pointer. Otherwise, the
return value is a non-null ELF descriptor.
Before the first call to elfbegin(), a program must call
elfversion() to coordinate versions.
The elfend() function is used to terminate an ELF descrip-
tor, 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 argu-
ment, to simplify error handling. If the program wants to
write data associated with the ELF descriptor to the file,
it must use elfupdate() before calling elfend().
Calling elfend() removes one activation and returns the
remaining activation count. The library does not terminate
the descriptor until the activation count reaches 0. Conse-
quently, a 0 return value indicates the ELF descriptor is no
longer valid.
The elfmemory() function returns a pointer to an ELF
descriptor. The ELF image has read operations enabled (
ELFCREAD). 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
elfmemory() can be read and modified, but the ELF image
size cannot be changed.
The elfnext() function provides sequential access to the
next archive member. Having an ELF descriptor, elf, associ-
ated with an archive member, elfnext() prepares the con-
taining archive to access the following member when the pro-
gram calls elfbegin(). After successfully positioning an
archive for the next member, elfnext() returns the value
ELFCREAD. Otherwise, the open file was not an archive, elf
SunOS 5.11 Last change: 11 Jul 2001 3
ELF Library Functions elfbegin(3ELF)
was NUL, or an error occurred, and the return value is
ELFCNUL. In either case, the return value can be passed
as an argument to elfbegin(), specifying the appropriate
action.
The elfrand() 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 elfgetarsym(3ELF) for
more information about archive member offsets. When
elfrand() works, it returns offset. Otherwise, it returns
0, because an error occurred, elf was NUL, 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. Nor-
mally, 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 elfcntl() to let it reuse file descrip-
tors. After calling elfcntl() with appropriate arguments,
the program can close the file descriptor without interfer-
ing with the library.
All data associated with an ELF descriptor remain allocated
until elfend() 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 elfbegin() func-
tion.
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
elfend() 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.
SunOS 5.11 Last change: 11 Jul 2001 4
ELF Library Functions elfbegin(3ELF)
if (elfversion(EVCURENT) == EVNONE)
{
/* library out of date */
/* recover from error */
}
cmd = ELFCREAD;
arf = elfbegin(fildes, cmd, (Elf *)0);
while ((elf = elfbegin(fildes, cmd, arf)) != 0)
{
if ((ehdr = elf32getehdr(elf)) != 0)
{
/* process the file ... */
}
cmd = elfnext(elf);
elfend(elf);
}
elfend(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 elfend() to terminate them.
elfversion(EVCURENT);
arf = elfbegin(fildes, ELFCREAD, (Elf *)0);
if (elfkind(arf) != ELFKAR)
{
/* not an archive */
}
/* initial processing */
/* set offset = ... for desired member header */
while (elfrand(arf, offset) == offset)
{
if ((elf = elfbegin(fildes, ELFCREAD, arf)) == 0)
break;
if ((ehdr = elf32getehdr(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
SunOS 5.11 Last change: 11 Jul 2001 5
ELF Library Functions elfbegin(3ELF)
application could thus provide the following function to
rewind an archive (the function returns -1 for errors and 0
otherwise).
#include
#include
int
rewindelf(Elf *elf)
{
if (elfrand(elf, (sizet)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.
elfversion(EVCURENT);
fildes = open("path/name", ORDWROTRUNCOCREAT, 0666);
if ((elf = elfbegin(fildes, ELFCWRITE, (Elf *)0)) == 0)
return;
ehdr = elf32newehdr(elf);
phdr = elf32newphdr(elf, count);
scn = elfnewscn(elf);
shdr = elf32getshdr(scn);
data = elfnewdata(scn);
elfupdate(elf, ELFCWRITE);
elfend(elf);
Finally, the following outline shows how one might update an
existing ELF file. Again, this example is simplified to show
the overall flow.
elfversion(EVCURENT);
fildes = open("path/name", ORDWR);
elf = elfbegin(fildes, ELFCRDWR, (Elf *)0);
/* add new or delete old information */
/* ensure that the memory image of the file is complete */
elfupdate(elf, ELFCNUL);
elfupdate(elf, ELFCWRITE); /* update file */
elfend(elf);
SunOS 5.11 Last change: 11 Jul 2001 6
ELF Library Functions elfbegin(3ELF)
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).
ATRIBUTES
See attributes(5) for descriptions of the following attri-
butes:
ATRIBUTE TYPE ATRIBUTE VALUE
Interface Stability Stable
MT-Level MT-Safe
SEE ALSO
creat(2), lseek(2), mmap(2), open(2), ar.h(3HEAD),
elf(3ELF), elf32getehdr(3ELF), elfcntl(3ELF),
elfgetarhdr(3ELF), elfgetarsym(3ELF), elfgetbase(3ELF),
elfgetdata(3ELF), elfgetscn(3ELF), elfkind(3ELF),
elfrawfile(3ELF), elfupdate(3ELF), elfversion(3ELF),
libelf(3LIB), attributes(5)
SunOS 5.11 Last change: 11 Jul 2001 7
|