Museum

Home

Lab Overview

Retrotechnology Articles

⇒ Online Manual

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

cof2elf(1)

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)





   elf_begin(3E)                  (ELF Library)                  elf_begin(3E)


   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 [see lseek(2)] is unconstrained,
         and the resulting file offset is undefined.

         cmd may have the following values.

         ELF_C_NULL      When a program sets cmd to this value, elf_begin
                         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.

         ELF_C_READ      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, 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.




   7/91                                                                 Page 1









   elf_begin(3E)                  (ELF Library)                  elf_begin(3E)


                         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 below for more
                         information.

         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     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.

         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.  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 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


   Page 2                                                                 7/91









   elf_begin(3E)                  (ELF Library)                  elf_begin(3E)


         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 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);

         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.

















   7/91                                                                 Page 3









   elf_begin(3E)                  (ELF Library)                  elf_begin(3E)


              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 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


   Page 4                                                                 7/91









   elf_begin(3E)                  (ELF Library)                  elf_begin(3E)


         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), 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).

   NOTES
         COFF is an object file format that preceded ELF . When a program
         calls elf_begin 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 elf_begin, file offsets and addresses in the ELF header, the
         program headers, and the section headers retain the original COFF
         values [see elf_getehdr, elf_getphdr, and elf_getshdr].  A program
         may call elf_update to adjust these values (without writing the
         file), and the library will then present a consistent, ELF view of
         the file.  Data obtained through elf_getdata are translated (the COFF
         symbol table is presented as ELF , etc.).  Data viewed through
         elf_rawdata 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.















   7/91                                                                 Page 5





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