elf_begin(3E)elf_begin(3E)NAMEelf_begin() - make file descriptor for ELF file
SYNOPSIS
Command: [flag]... file... [library]...
DESCRIPTION
and work together to process ELF object files, either individually or
as members of archives. After obtaining an ELF descriptor from the
program may read an existing file, update an existing file, or create a
new file. fildes is an open file descriptor that 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 following
values.
When a program sets cmd to this value, returns a null pointer, without
opening a new descriptor. ref is ignored for this
command. See elf_next(3E) and the examples below
for more information.
When a program wishes 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.
First, if ref is a null pointer, allocates a new
ELF descriptor and prepares to process the entire
file. If the file being read is an archive, also
prepares the resulting descriptor to examine the
initial archive member on the next call to as if
the program had used or to "move" to the initial
member.
Second, if ref is a nonnull descriptor associated
with an archive file, lets a program obtain a sepa‐
rate ELF descriptor associated with an individual
member. The program should have used or to posi‐
tion ref appropriately (except for the initial mem‐
ber, which prepares; see the example below). In
this case, fildes should be the same file descrip‐
tor used for the parent archive.
Finally, if ref is a nonnull ELF descriptor that is
not an archive, increments the number of activa‐
tions for the descriptor and returns ref, without
allocating a new descriptor and without changing
the descriptor's read/write permissions. To termi‐
nate the descriptor for ref, the program must call
once for each activation. See elf_next(3E) and the
examples below for more information.
This command duplicates the actions of
and additionally allows the program to update the
file image (see elf_update(3E)). That is, using
gives a read-only view of the file, while lets the
program read and write the file. is not valid for
archive members. If ref is nonnull, it must have
been created with the command.
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.
"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
or 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, returns a null pointer. Otherwise, the return value is a non‐
null ELF descriptor. Before the first call to a program must call 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. Normally, the library
assumes the file descriptor remains usable for the life of the ELF
descriptor. If, however, a program must process many files simultane‐
ously and the underlying operating system limits the number of open
files, the program can use to let it reuse file descriptors. After
calling with appropriate arguments, the program may close the file
descriptor without interfering with the library.
All data associated with an ELF descriptor remain allocated until ter‐
minates 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.
Note
When a program calls on a COFF file, the library translates COFF struc‐
tures to their ELF equivalents, allowing 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.
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 and will have
the same value, the activation count will be two, and the program calls
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 pro‐
cesses 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 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 */
}
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 . . . */
close(creat("path/name", 0666));
elf_update(elf, ELF_C_WRITE);
elf_end(elf);
In the example above, the call to 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 (see trun‐
cate(2)). Some systems, however, do not support and the call to pro‐
tects against this. Notice that both file creation examples open the
file with write and read permissions. On systems that support the
library uses it to enhance performance, and requires a readable file
descriptor. Although the library can use a write-only file descriptor,
the application will not obtain the performance advantages of
SEE ALSOcreat(2), lseek(2), mmap(2), open(2), truncate(2), elf(3E),
elf_cntl(3E), elf_end(3E), elf_getarhdr(3E), elf_getbase(3E), elf_get‐
data(3E), elf_getehdr(3E), elf_getphdr(3E), elf_getscn(3E),
elf_kind(3E), elf_next(3E), elf_rand(3E), elf_rawfile(3E),
elf_update(3E), elf_version(3E), ar(4).
elf_begin(3E)