elf_begin(3E)

elf_begin - Make a file descriptor

Showing IRIX 6.5.30 (default release). Last changed in IRIX 6.5.19.

NAME
     elf_begin - Make a file descriptor

SYNOPSIS
     cc [flag ...] file ...  -lelf [library ...]

     #include <libelf.h>

     Elf *elf_begin(int fildes, Elf_Cmd cmd, Elf *ref);

DESCRIPTION
     elf_begin, elf_next, elf_rand, and elf_end work together to process
     ELF object files, either individually or as members of archives.
     After obtaining an ELF descriptor from elf_begin, the program may read
     an existing file, update an existing file, or create a new file.
     fildes is an open file descriptor that elf_begin uses for reading or
     writing.  The initial file offset is unconstrained, and the resulting
     file offset is undefined.

     cmd may have the following values:

     ELF_C_NULL     elf_begin returns a null pointer, without opening a new
                    descriptor.  ref is ignored for this command.  See
                    elf_next(3E) and the EXAMPLES section for more
                    information.

     ELF_C_READ     Specifies that the program examine the contents of an
                    existing file.  Depending on the value of ref, this
                    command examines archive members or entire files.  The
                    following three cases may occur:

                    * First, if ref is a null pointer, elf_begin allocates
                      a new ELF descriptor and prepares to process the
                      entire file.  If the file being read is an archive,
                      elf_begin also prepares the resulting descriptor to
                      examine the initial archive member on the next call
                      to elf_begin, as if the program had used elf_next or
                      elf_rand to ``move'' to the initial member.

                    * Second, if ref is a non-null descriptor associated
                      with an archive file, elf_begin lets a program obtain
                      a separate ELF descriptor associated with an
                      individual member.  The program should have used
                      elf_next or elf_rand to position ref appropriately
                      (except for the initial member, which elf_begin
                      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, elf_begin 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 elf_end once for each activation.  See
                      elf_next(3E) and the EXAMPLES section for more
                      information.

     ELF_C_READ_MMAP
                    This command duplicates the actions of ELF_C_READ 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 ELF_C_READ_MMAP may therefore wish
                    to install a signal handler for SIGSEGV (Segmentation
                    Violation) and issue a message when it happens.

     ELF_C_RDWR     This command duplicates the actions of ELF_C_READ and
                    additionally allows the program to update the file
                    image; see elf_update(3E).  That is, using ELF_C_READ
                    gives a read-only view of the file, while ELF_C_RDWR
                    lets the program read and write the file.  ELF_C_RDWR
                    is not valid for archive members.  If ref is non-null,
                    it must have been created with the ELF_C_RDWR command.

     ELF_C_WRITE    The program ignores previous file contents, presumably
                    to create a new file.  ref is ignored for this command.

     ELF_C_WRITE_FAST
                    This command is the same as ELF_C_WRITE except that
                    instead of performing malloc() on memory for the output
                    file and then doing a write(2) and free(),
                    ELF_C_WRITE_FAST writes the output directly to the file
                    system (by doing a write as needed).  Avoiding running
                    malloc() can help limit time-consuming paging activity.

     elf_begin 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 elf_kind or elf_getehdr 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, elf_begin returns
     a null pointer.  Otherwise, the return value is a non-null ELF
     descriptor.

     Before the first call to elf_begin, a program must call elf_version 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.  Usually, 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 elf_cntl to let it reuse file
     descriptors.  After calling elf_cntl 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
     elf_end 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:

     The following is a prototype for reading a file.  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 elf_end 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);

     Example 2:

     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 elf_end 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 */
          }

     Example 3:

     The following outline shows how you 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);

     Example 4:

     The following outline shows how you might update an existing ELF file.
     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 previous example, 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.

     Note 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 want to
     provide both write and read permissions.

NOTES
     COFF is an object file format that preceded ELF.  COFF object files
     cannot be used with this library.

     ELF_C_READ_MMAP and ELF_C_WRITE_FAST are options specific to this
     implementation, not options that are generally available.

SEE ALSO
     creat(2), lseek(2), mmap(2), open(2), truncate(2)
     elf(3E), elf_cntl(3E), elf_end(3E), elf_getarhdr(3E), elf_getbase(3E),
     elf_getdata(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)