Various tools are available to analyze the contents of an ELF file. To display the size of a file use the size(1) command.
$ 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 used in 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 segments describe how portions of a file are mapped into memory. See mmap(2). These loadable segments can be displayed by using the dump(1) command and examining the LOAD entries.
$ elfdump -p -NPT_LOAD libfoo.so.1 Program Header[0]: p_vaddr: 0 p_flags: [ PF_X PF_R ] p_paddr: 0 p_type: [ PT_LOAD ] p_filesz: 0x59c p_memsz: 0x59c p_offset: 0 p_align: 0x10000 Program Header[1]: p_vaddr: 0x10630 p_flags: [ PF_X PF_W PF_R ] p_paddr: 0 p_type: [ PT_LOAD ] p_filesz: 0x10c p_memsz: 0x12c p_offset: 0x630 p_align: 0x10000 |
There are two loadable 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, PF_X PF_R. The data segment is mapped to also allow its contents to be modified, PF_W. The memory size, p_memsz, of the data segment differs from the file size, p_filesz. This difference accounts for the .bss section, which is part of the data segment, and is dynamically created when the segment is loaded.
Programmers 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 ......... |
The output from both the previous nm(1) and dump(1) examples shows the association of the functions _init, foo, and _fini to the sections .init, .text and .fini. These sections, because of their read-only nature, are part of the text segment.
Similarly, 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.