Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ elf_begin(3E) — IRIX 6.5.3f

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

creat(2)

lseek(2)

mmap(2)

open(2)

truncate(2)

elf(3E)

ar(4)



ELFBEGIN(3E)                                                    ELFBEGIN(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
Page 1


ELFBEGIN(3E)                                                    ELFBEGIN(3E)



                     descriptor for ref, the program must call elfend once
                     for each activation.  See elfnext(3E) and the examples
                     below for more information.

     ELFCREADMMAP This command duplicates the actions of ELFCREAD but
                     uses the mmap() system call to access the file data in a
                     more memory efficient manner.  If, after libelf has
                     opened the file, another process truncates the file
                     libelf could get a Segmentation Violation attempting to
                     read data it believes is in the file (but which is no
                     longer there due to the truncation).  Applications
                     calling libelf with ELFCREADMMAP may therefore wish to
                     install a signal handler for SIGSEGV (Segmentation
                     Violation) and issue a message when it happens.

     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.

     ELFCWRITEFAST
                     is the same as ELFCWRITE except that instead of
                     malloc()ing memory for the output file (and then doing a
                     write(2) and free()) ELFCWRITEFAST writes the output
                     directly to the file system (by doing writes as needed).
                     Avoiding the malloc() can help limit time-consuming
                     paging activity.

     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



                                                                        Page 2





ELFBEGIN(3E)                                                    ELFBEGIN(3E)



     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.











                                                                        Page 3





ELFBEGIN(3E)                                                    ELFBEGIN(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 ftruncate, and the



                                                                        Page 4





ELFBEGIN(3E)                                                    ELFBEGIN(3E)



     call to creat protects against this.

     Notice that both file creation examples open the file with write and read
     permissions.  The library is not compiled to use mmap so there is no need
     for write permission. But for maximum portability with implementations
     that do use mmap for file creation you may wish to provide both write and
     read permissions.

SEE ALSO
     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 .  COFF object files
     cannot be used with this library.

     ELFCREADMMAP and ELFCWRITEFAST are options specific to this
     implementation, not options which are generally available.


































                                                                        Page 5



Typewritten Software • bear@typewritten.org • Edmonds, WA 98026