United States-English |
|
|
HP-UX Reference > Eelf_begin(3E)HP-UX 11i Version 3: February 2007 |
|
NAMEelf_begin() — make file descriptor for ELF file SYNOPSISCommand: cc [flag]... file... -lelf [library]... #include <libelf.h> Elf *elf_begin( int fildes, Elf_Cmd cmd, Elf *ref ); DESCRIPTIONelf_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_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 nonnull ELF descriptor. Before the first call to elf_begin(), a program must call elf_version() to coordinate versions. System ServicesWhen 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. EXAMPLESA 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. 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 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. |
Printable version | ||
|