| 跳过导航链接 | |
| 退出打印视图 | |
 
			 | 
			Oracle Solaris 11.1 链接程序和库指南 Oracle Solaris 11.1 Information Library (简体中文) | 
可以使用各种工具分析 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_X 和 PF_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]  0x00010628 0x00000028  OBJT GLOB  D    0 .data          data
      ....
      [38]  0x00010650 0x00000028  OBJT GLOB  D    0 .bss           bss
      ....
      [40]  0x00000520 0x0000000c  FUNC GLOB  D    0 .init          _init
      ....
      [44]  0x00000508 0x00000014  FUNC GLOB  D    0 .text          foo
      ....
      [46]  0x0000052c 0x0000000c  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) 输出显示 _init、foo 和 _fini 函数与 .init、.text 和 .fini 节的关联关系。这些节由于具有只读性质,因此属于文本段。
同样,数据数组 data 和 bss 分别与节 .data 和 .bss 关联。这些节由于具有可写性质,因此属于数据段。