elf_begin(3E) DG/UX R4.11MU05 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 following 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 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, 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.
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 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 program must
call elfend once for each activation. See
elfnext(3E) and the examples below for more
information.
ELFCRDWR This command duplicates the actions of ELFCREAD and
additionally allows the program 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. Otherwise, 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. 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 elfcntl to let it reuse file
descriptors. After calling elfcntl 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
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.
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 ftruncate, 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 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), truncate(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, 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. 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 consistent, 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.
Licensed material--property of copyright holder(s)