Oracle® Solaris 11.2 链接程序和库指南

退出打印视图

更新时间: 2014 年 7 月
 
 

使用 elfdump 分析文件

可以使用各种工具分析 ELF 文件的内容,包括标准的 Unix 实用程序 dump(1)nm(1)size(1)。在 Oracle Solaris 中,这些工具大都已被 elfdump(1) 取代。

使用 eldump 诊断 ELF 目标文件的内容对于调查以下几节中介绍的各种性能问题很有用。

ELF 格式可以将数据组织到多个中。各节会被依次指定给称为的单元。段描述如何将文件的各部分映射到内存。请参见 mmapobj(2)。可以通过使用 elfdump(1) 命令并检查 PT_LOAD 项来显示这些可装入段。

$ 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:     0x53c       p_memsz:    0x53c
    p_offset:     0           p_align:    0x10000

Program Header[1]:
    p_vaddr:      0x1053c     p_flags:    [ PF_X PF_W PF_R ]
    p_paddr:      0           p_type:     [ PT_LOAD ]
    p_filesz:     0x114       p_memsz:    0x13c
    p_offset:     0x53c       p_align:    0x10000

libfoo.so.1 共享目标文件中存在两种可装入段,通常称为文本段和数据段。对文本段进行了映射以允许读取和执行其内容(PF_XPF_R)。数据段映射的目的是允许同时修改其内容 PF_W。数据段的内存大小 p_memsz 不同于文件大小 p_filesz。该差异说明存在 .bss 节,此节属于数据段并在装入数据段时动态创建。

程序员通常根据定义其代码中的函数和数据元素的符号来考虑文件。通过在 elfdump 命令中使用 –s 选项可显示这些符号。

$ elfdump -sN.symtab libfoo.so.1

Symbol Table Section:  .symtab
   index    value     size  type bind oth ver shndx          name
    ....
    [36]  0x10628     0x28  OBJT GLOB  D    0 .data          data
    ....
    [38]  0x10650     0x28  OBJT GLOB  D    0 .bss           bss
    ....
    [40]    0x520      0xc  FUNC GLOB  D    0 .init          _init
    ....
    [44]    0x508     0x14  FUNC GLOB  D    0 .text          foo
    .... 
    [46]    0x52c      0xc  FUNC GLOB  D    0 .fini          _fini

elfdump 显示的符号表信息包括与符号关联的节。elfdump –c 选项可用于显示与这些节有关的信息。

$ elfdump -c libfoo.so.1
....
Section Header[6]:  sh_name: .text
    sh_addr:      0x4f8           sh_flags:   [ SHF_ALLOC SHF_EXECINSTR ]
    sh_size:      0x28            sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x4f8           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x8

Section Header[7]:  sh_name: .init
    sh_addr:      0x520           sh_flags:   [ SHF_ALLOC SHF_EXECINSTR ]
    sh_size:      0xc             sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x520           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4

Section Header[8]:  sh_name: .fini
    sh_addr:      0x52c           sh_flags:   [ SHF_ALLOC SHF_EXECINSTR ]
    sh_size:      0xc             sh_type:    [ SHT_PROGBITS ]
    sh_offset:    0x52c           sh_entsize: 0
    sh_link:      0               sh_info:    0
    sh_addralign: 0x4
....
Section Header[12]:  sh_name: .data
   sh_addr:      0x10628         sh_flags:   [ SHF_WRITE SHF_ALLOC ]
   sh_size:      0x28            sh_type:    [ SHT_PROGBITS ]
   sh_offset:    0x628           sh_entsize: 0
   sh_link:      0               sh_info:    0
   sh_addralign: 0x4
....
Section Header[14]:  sh_name: .bss
   sh_addr:      0x10650         sh_flags:   [ SHF_WRITE SHF_ALLOC ]
   sh_size:      0x28            sh_type:    [ SHT_NOBITS ]
   sh_offset:    0x650           sh_entsize: 0
   sh_link:      0               sh_info:    0
   sh_addralign: 0x4
....

以上示例中 elfdump(1) 的输出显示了 _initfoo_fini 函数与 .init.text.fini 节的关联关系。这些节由于具有只读性质,因此属于文本段。

同样,数据数组 databss 分别与节 .data.bss 关联。这些节由于具有可写性质,因此属于数据段。