Linker and Libraries Guide

Analyzing Files

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
59c + 10c + 20 = 0x6c8

$ size -xf
..... + 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

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, 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

[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
           **** 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.

Note –

The previous dump(1) display has been simplified for this example.