Before discussing performance, it is useful to be aware of some available tools and their use in analyzing the contents of an ELF file.
Frequently reference is made to the size of either the sections or the segments that are defined within an ELF file (for a complete description of the ELF format see Chapter 7, Object Files). The size of a file can be displayed using the size(1) command. For example:
$ size -x libfoo.so.1 59c + 10c + 20 = 0x6c8 $ size -xf libfoo.so.1 ..... + 1c(.init) + ac(.text) + c(.fini) + 4(.rodata) + \ ..... + 18(.data) + 20(.bss) ..... |
The first example indicates the size of the shared objects text, data, and bss, a categorization that has traditionally been used throughout previous releases of the SunOS operating system. The ELF format provides a finer granularity for expressing data within a file by organizing the data into sections. The second example displays the size of each of the file's loadable sections.
Sections are allocated to units known as segments, some of which describe how portions of a file will be mapped into memory. These loadable segments can be displayed by using the dump(1) command and examining the LOAD entries. For example:
$ dump -ov libfoo.so.1 libfoo.so.1: ***** PROGRAM EXECUTION HEADER ***** Type Offset Vaddr Paddr Filesz Memsz Flags Align LOAD 0x94 0x94 0x0 0x59c 0x59c r-x 0x10000 LOAD 0x630 0x10630 0x0 0x10c 0x12c rwx 0x10000 |
Here, there are two segments in the shared object libfoo.so.1, commonly referred to as the text and data segments. The text segment is mapped to allow reading and execution of its contents (r-x), whereas the data segment is mapped to allow its contents to be modified (rwx). Notice that the memory size (Memsz) of the data segment differs from the file size (Filesz). This difference accounts for the .bss section, which is actually part of the data segment.
Programmers, however, usually think of a file in terms of the symbols that define the functions and data elements within their code. These symbols can be displayed using nm(1). For example:
$ nm -x libfoo.so.1 [Index] Value Size Type Bind Other Shndx Name ......... [39] |0x00000538|0x00000000|FUNC |GLOB |0x0 |7 |_init [40] |0x00000588|0x00000034|FUNC |GLOB |0x0 |8 |foo [41] |0x00000600|0x00000000|FUNC |GLOB |0x0 |9 |_fini [42] |0x00010688|0x00000010|OBJT |GLOB |0x0 |13 |data [43] |0x0001073c|0x00000020|OBJT |GLOB |0x0 |16 |bss ......... |
The section that contains a symbol can be determined by referencing the section index (Shndx) field from the symbol table and by using dump(1) to display the sections within the file. For example:
$ dump -hv libfoo.so.1 libfoo.so.1: **** SECTION HEADER TABLE **** [No] Type Flags Addr Offset Size Name ......... [7] PBIT -AI 0x538 0x538 0x1c .init [8] PBIT -AI 0x554 0x554 0xac .text [9] PBIT -AI 0x600 0x600 0xc .fini ......... [13] PBIT WA- 0x10688 0x688 0x18 .data [16] NOBI WA- 0x1073c 0x73c 0x20 .bss ......... |
Using the output from both the previous nm(1) and dump(1) examples, the association of the functions _init, foo, and _fini to the sections .init, .text and .fini can be seen. These sections, because of their read-only nature, are part of the text segment.
Similarly, it can be seen that the data arrays data, and bss are associated with the sections .data and .bss respectively. These sections, because of their writable nature, are part of the data segment.
The previous dump(1) display has been simplified for this example.
Armed with this tool information, you can analyze the location of code and data within any ELF file you generate. This knowledge will be useful when following the discussions in later sections.