Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ elf_begin(3E) — DG/UX R4.11MU05

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

cof2elf(1)

creat(2)

lseek(2)

mmap(2)

open(2)

truncate(2)

elf(3E)

ar(4)



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)

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