elf_begin(3E) MISC. REFERENCE MANUAL PAGES elf_begin(3E)
NAME
elfbegin - make a file descriptor
SYNOPSIS
cc [flag ...] file ... -lelf [library ...]
#include <libelf.h>
Elf *elfbegin(int fildes, ElfCmd cmd, Elf *ref);
DESCRIPTION
elfbegin, elfnext, elfrand, and elfend work together to
process ELF object files, either individually or as members
of archives. After obtaining an ELF descriptor from
elfbegin, the program may read an existing file, update an
existing file, or create a new file. fildes is an open file
descriptor that elfbegin uses for reading or writing. The
initial file offset [see lseek(2)] is unconstrained, and the
resulting file offset is undefined. cmd may have the fol-
lowing values.
ELFCNULL 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 elfnext(3E) and the
examples below for more information.
ELFCREAD When a program wishes to examine the con-
tents 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.
First, 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 ini-
tial member.
Second, 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 program should have used
elfnext or elfrand to position ref
appropriately (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
Last change: ELF Library 1
elf_begin(3E) MISC. REFERENCE MANUAL PAGES elf_begin(3E)
parent archive.
Finally, 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 pro-
gram must call elfend once for each activa-
tion. See elfnext(3E) and the examples
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(3E)]. That is, 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 wishes to ignore previous
file contents, presumably to create a new
file, it should set cmd to this value. ref
is ignored for this command. elfbegin
``works'' 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 thus may call
elfkind or elfgetehdr 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. Other-
wise, the return value is a non-null ELF
descriptor. Before the first call to
elfbegin, a program must call elfversion
to coordinate versions.
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,
Last change: ELF Library 2
elf_begin(3E) MISC. REFERENCE MANUAL PAGES elf_begin(3E)
the program may 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
A prototype for reading a file appears below. 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 two, 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.
if (elfversion(EVCURRENT) == 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.
Last change: ELF Library 3
elf_begin(3E) MISC. REFERENCE MANUAL PAGES elf_begin(3E)
elfversion(EVCURRENT);
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 */
}
The following outline shows how one might create a new ELF
file. This example is simplified to show the overall flow.
elfversion(EVCURRENT);
fildes = open("path/name", ORDWR|OTRUNC|OCREAT, 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(EVCURRENT);
fildes = open("path/name", ORDWR);
elf = elfbegin(fildes, ELFCRDWR, (Elf *)0);
/* add new or delete old information ... */
close(creat("path/name", 0666));
elfupdate(elf, ELFCWRITE);
elfend(elf);
In the example above, the call to creat truncates the file,
thus ensuring the resulting file will have the ``right''
size. Without truncation, the updated file might be as big
as the original, even if information were deleted. The
library truncates the file, if it can, with ftruncate [see
truncate(2)]. Some systems, however, do not support ftrun-
cate, and the call to creat protects against this. Notice
that both file creation examples open the file with write
and read permissions. On systems that support mmap, the
Last change: ELF Library 4
elf_begin(3E) MISC. REFERENCE MANUAL PAGES elf_begin(3E)
library uses it to enhance performance, and mmap 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.
SEE ALSO
cof2elf(1), creat(2), lseek(2), mmap(2), open(2), trun-
cate(2), elf(3E), elfcntl(3E), elfend(3E),
elfgetarhdr(3E), elfgetbase(3E), elfgetdata(3E),
elfgetehdr(3E), elfgetphdr(3E), elfgetscn(3E),
elfkind(3E), elfnext(3E), elfrand(3E), elfrawfile(3E),
elfupdate(3E), elfversion(3E), ar(4).
NOTES
COFF is an object file format that preceded ELF . When a
program calls elfbegin on a COFF file, the library
translates COFF structures to their ELF equivalents, allow-
ing programs to read (but not to write) a COFF file as if it
were ELF . This conversion happens only to the memory image
and not to the file itself. After the initial elfbegin,
file offsets and addresses in the ELF header, the program
headers, and the section headers retain the original COFF
values [see elfgetehdr, elfgetphdr, and elfgetshdr]. A
program may call elfupdate to adjust these values (without
writing the file), and the library will then present a con-
sistent, ELF view of the file. Data obtained through
elfgetdata are translated (the COFF symbol table is
presented as ELF , etc.). Data viewed through elfrawdata
undergo no conversion, allowing the program to view the
bytes from the file itself. Some COFF debugging information
is not translated, though this does not affect the semantics
of a running program. Although the ELF library supports
COFF , programmers are strongly encouraged to recompile
their programs, obtaining ELF object files.
Last change: ELF Library 5