[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]

Technical Reference: Base Operating System and Extensions, Volume 1

elf_begin Subroutine


Makes a file descriptor


cc [flag...] file... -lelf [library] ...
#include <libelf.h>


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


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 the lseek subroutine] is unconstrained, and the resulting file offset is undefined.

COFF is an object file format that preceded ELF on some computer architectures (Intel, for example). For these architectures, 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 the elf_getehdr, elf_getphdr, and elf_getshdr subroutines]. 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, and so on). 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.


cmd Specifies the action to take and can be set to any of the following values.

Causes elf_begin to return a null pointer, without opening a new descriptor. ref is ignored for this command. See the elf_next subroutine and the examples below for more information.

Enables a program to read the contents of an existing file.

Depending on the value of ref, this command examines archive members or entire files. Three cases can occur.

  1. 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.
  2. 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.
  3. 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 the elf_next subroutine and the examples below for more information.

Duplicates the actions of ELF_C_READ and additionally enables the program to update the file image [see the elf_update subroutine]. 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.

Ignores the previous file's content, presumably to create a new file. 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 program that deals with multiple input (or output) files must keep the ELF descriptors active until it finishes with them.


  1. A prototype for reading a file is shown 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);
  2. A prototype for random archive processing is shown below. 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.

       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)
            if ((ehdr = elf32_getehdr(elf)) != 0)
                    /* process archive member...*/
            /* set offset =...for desired member header */
  3. A prototype that illustrates how to create a new ELF file is shown below. This example is simplified to show the overall flow.

       fildes = open("path/name", O_RDWR|O_TRUNC|O_CREAT, 0666);
       if ((elf = elf_begin(fildes, ELF_C_WRITE, (Elf *)0)) == 0)
       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);
  4. A prototype that illustrates how to update an existing ELF file is shown below. This example is simplified to show the overall flow.

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

    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 the truncate subroutine). 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.

Related Information

The creat (open, openx, open64, creat, or creat64 Subroutine) subroutine, elf_cntl (elf_cntl Subroutine) subroutine, elf_end (elf_end Subroutine) subroutine, elf_getarhdr (elf_getarhdr Subroutine) subroutine, elf_getbase (elf_getbase Subroutine) subroutine, elf_getdata (elf_getdata, elf_newdata, elf_rawdata Subroutine) subroutine, elf32_getehdr (elf32_getehdr, elf32_newehdr, elf64_getehdr, elf64_newehdr Subroutine) subroutine, elf64_getehdr (elf32_getehdr, elf32_newehdr, elf64_getehdr, elf64_newehdr Subroutine) subroutine, elf32_getphdr (elf32_getphdr, elf32_newphdr, elf64_getphdr, elf64_newphdr Subroutine) subroutine, elf32_getphdr (elf32_getphdr, elf32_newphdr, elf64_getphdr, elf64_newphdr Subroutine) subroutine, elf_getscn (elf_getscn, elf_ndxscn, elf_newscn, elf_nextscn Subroutine) subroutine, elf_kind (elf_kind Subroutine) subroutine, elf_next (elf_next Subroutine) subroutine, elf_rand (elf_rand Subroutine) subroutine, elf_rawfile (elf_rawfile Subroutine) subroutine, elf_update (elf_update Subroutine) subroutine, elf_version (elf_version Subroutine) subroutine, lseek (lseek, llseek or lseek64 Subroutine) subroutine, mmap (mmap or mmap64 Subroutine) subroutine, open (open, openx, open64, creat, or creat64 Subroutine) subroutine, truncate subroutine.

Introduction to ELF Subroutines,

[ Previous | Next | Table of Contents | Index | Library Home | Legal | Search ]