ELF节头表分析

本文深入解析了ELF文件中节头表和节的基本概念、结构及特性,包括节头表索引、节类型、节属性、节内容等关键信息,以及如何通过节头表定位文件中的所有节,特别强调了预留值SHN_UNDEF及其在不同上下文中的意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Sections 节

An object file's section header table lets one locate all the file's sections. The section header table is an array of Elf32_Shdr or Elf64_Shdr structures as described below. A section header table index is a subscript into this array. The ELF header's e_shoff member gives the byte offset from the beginning of the file to the section header table. e_shnum normally tells how many entries the section header table contains. e_shentsize gives the size in bytes of each entry.

通过目标文件中的节头表,我们就可以轻松地定位文件中所有的节。节头表是若干结构Elf32_Shdr或者结构Elf64_Shdr组成的数组。节头表索引(section header table index)是用来定位节头表的表项的。ELF文件头中的e_shoff代表的是节头表在文件中的偏移值;e_shnum代表的是节头表的表项总数;e_shentsize代表的是节头表的表项大小。

If the number of sections is greater than or equal to SHN_LORESERVE (0xff00), e_shnum has the value SHN_UNDEF (0) and the actual number of section header table entries is contained in the sh_size field of the section header at index 0 (otherwise, the sh_size member of the initial entry contains 0).

如果节头表的表项个数大于或者等于SHN_LORESERVE(0xff00)的话,成员e_shnum的值为SHN_UNDEF(0),那么真正的节头表表项个数存储在节头表中第一表项(节头表索引值为0)中的成员sh_size里(否则,一般情况下,第一表项的成员sh_size的值为0)。


Some section header table indexes are reserved in contexts where index size is restricted, for example, the st_shndx member of a symbol table entry and the e_shnum and e_shstrndx members of the ELF header. In such contexts, the reserved values do not represent actual sections in the object file. Also in such contexts, an escape value indicates that the actual section index is to be found elsewhere, in a larger field.

需要注意的是,有一些特殊的节头表索引值是预留的,这些预留值可能会被符号表表项成员st_shndx和ELF文件头成员e_shnum和e_shstrndx使用到。

这些特殊的节头表索引值总结下主要有以下两方面作用:

(1)当针对符号表表项成员st_shndx时,下表所列的SHN_UNDEF/SHN_ABS/SHN_COMMON并不代表在目标文件中真是存在对应的节,而是说明该符号具有特殊的含义。

st_shndx值为SHN_ABS,符号类型不一定就是STT_FILE,例如使用objcopy将bianry文件转为.o文件时的符号) 

(2)当针对ELF文件头成员e_shnum和e_shstrndx时,下表所列的SHN_UNDEF/SHN_XINDEX有时也被称为逸出值(escape value),表明真实的节头表索引值存储在别处(一个大小足够容纳真实节头表索引值的地方)。

SHN_UNDEF

This value marks an undefined, missing, irrelevant, or otherwise meaningless section reference. For example, a symbol ``defined'' relative to section number SHN_UNDEF is an undefined symbol.

索引值SHN_UNDEF在不同的上下文代表不同的含义。 例如:

(1)当一个符号表表项的成员st_shndx值为SHN_UNDEF时,代表该符号是个未定义符号;

(2)当e_shnum的值是SHN_UNDEF是,表明真实的节头表表项个数(也就是目标文件中节的总个数)存储在第一个(即节头表索引值为0)节头表表项的成员sh_size中;

NOTE:Although index 0 is reserved as the undefined value, the section header table contains an entry for index 0. If the e_shnum member of the ELF header says a file has 6 entries in the section header table, they have the indexes 0 through 5. The contents of the initial entry are specified later in this section.

注意:尽管索引值SHN_UNDEF(0)是个预留值,但是节头表的索引值依然是从0开始的。如果ELF文件头成员e_shnum的值为6,说明该目标文件中的节头表有6个表项(即目标文件中有6个节),它们的索引值为0 ~ 5。

* SHN_LORESERVE

This value specifies the lower bound of the range of reserved indexes.

SHN_LOPROC through SHN_HIPROC

Values in this inclusive range are reserved for processor-specific semantics.

SHN_LOOS through SHN_HIOS

Values in this inclusive range are reserved for operating system-specific semantics.

SHN_ABS

This value specifies absolute values for the corresponding reference. For example, symbols defined relative to section number SHN_ABS have absolute values and are not affected by relocation.

当节头表索引值为SHN_ABS时,表明该符号是个绝对值,并且该值不会因为重定位而改变。

例如,一般情况下当一个符号的类型是STT_FILE时,则st_shndx的值为SHN_ABS。

SHN_COMMON

Symbols defined relative to this section are common symbols, such as FORTRAN COMMON or unallocated C external variables.

当符号表表项成员st_shndx的值为SHN_COMMON时,表明该符号对应的实体是个公用块数据。

SHN_XINDEX

This value is an escape value. It indicates that the actual section header index is too large to fit in the containing field and is to be found in another location (specific to the structure where it appears).

节头表索引值SHN_XINDEX代表的是个 逸出值。它代表的意思是真实的 节头表索引值 太大,所以存储在别处。当e_shstrndx的值是SHN_XINDEX时,表明真实的节名表存储在第一个(即节头表索引值为0)节头表表项的成员sh_link中。

SHN_HIRESERVE

This value specifies the upper bound of the range of reserved indexes. The system reserves indexes between SHN_LORESERVE and SHN_HIRESERVE, inclusive; the values do not reference the section header table. The section header table does not contain entries for the reserved indexes.

系统保留SHN_LORESERVE ~ SHN_HIRESERVE的值为预留值。节头表中并不真实的存在这些表项。


Sections contain all information in an object file except the ELF header, the program header table, and the section header table. Moreover, object files' sections satisfy several conditions.

目标文件中除了ELF文件头、程序头表和节头表,剩下的就全都是节了。此外,目标文件中的节符合下列条件:

  • Every section in an object file has exactly one section header describing it. Section headers may exist that do not have a section.

目标文件中真实存在的节都对应一个节头表表项,但是存在节头表表项,并不能说明目标文件中真实存在该节,例如可重定位文件中的.bss节就是存在节头表表项,但是在文件中该节的大小为0,即不存在真实的bss节。又比如节头表表项0,也并不存在对应的节。

  • Each section occupies one contiguous (possibly empty) sequence of bytes within a file.
目标文件中的一个节所占用的空间是连续的(当然了,有的节大小可能为0,例如.bss节)。
  • Sections in a file may not overlap. No byte in a file resides in more than one section.
目标文件中的所有节互相之间不覆盖或者重叠的。
  • An object file may have inactive space. The various headers and the sections might not ``cover'' every byte in an object file. The contents of the inactive data are unspecified.
目标文件中也许存在冗余的字符。由于字节对齐的需要,目标文件中的内容并不是连续的,而是随机有填充的冗余数据,这样的数据是未定义的。

A section header has the following structure.

节头表结构如下。

/* Section header.  */

typedef struct
{
  Elf32_Word    sh_name;                /* Section name (string tbl index) */
  Elf32_Word    sh_type;                /* Section type */
  Elf32_Word    sh_flags;               /* Section flags */
  Elf32_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf32_Off     sh_offset;              /* Section file offset */
  Elf32_Word    sh_size;                /* Section size in bytes */
  Elf32_Word    sh_link;                /* Link to another section */
  Elf32_Word    sh_info;                /* Additional section information */
  Elf32_Word    sh_addralign;           /* Section alignment */
  Elf32_Word    sh_entsize;             /* Entry size if section holds table */
} Elf32_Shdr;

typedef struct
{
  Elf64_Word    sh_name;                /* Section name (string tbl index) */
  Elf64_Word    sh_type;                /* Section type */
  Elf64_Xword   sh_flags;               /* Section flags */
  Elf64_Addr    sh_addr;                /* Section virtual addr at execution */
  Elf64_Off     sh_offset;              /* Section file offset */
  Elf64_Xword   sh_size;                /* Section size in bytes */
  Elf64_Word    sh_link;                /* Link to another section */
  Elf64_Word    sh_info;                /* Additional section information */
  Elf64_Xword   sh_addralign;           /* Section alignment */
  Elf64_Xword   sh_entsize;             /* Entry size if section holds table */
} Elf64_Shdr;

* sh_name

This member specifies the name of the section. Its value is an index into the section header string table section [see ``String Table'' below], giving the location of a null-terminated string.

成员sh_name是用来指定该节的名称的。它本身其实并不是字符串,而是一个数值,代表的是目标文件中 字符串表 中的一个索引值, 那里才真正存储着该节的名称对应的字符串。

* sh_type

This member categorizes the section's contents and semantics. Section types and their descriptions appear below.

成员sh_type指定该节的类型。

* sh_flags

Sections support 1-bit flags that describe miscellaneous attributes. Flag definitions appear below.

成员sh_flags用来描述该节的诸多属性。它由一系列标志比特位组成,每一位对应一个属性,当具备某一属性时,相应的标志位设置为1,反之设置为0。

* sh_addr

If the section will appear in the memory image of a process, this member gives the address at which the section's first byte should reside. Otherwise, the member contains 0.

如果该节的数据内容最后存在于程序的内存映像中,成员sh_addr指定的是该节数据在内存中的起始地址。否则,即该节数据不需要映射到内存中时,该成员数值为0。

* sh_offset

This member's value gives the byte offset from the beginning of the file to the first byte in the section. One section type, SHT_NOBITS described below, occupies no space in the file, and its sh_offset member locates the conceptual placement in the file.

成员sh_offset的数值代表的意思是该节数据在目标文件中的偏移量。需要注意的是,当节的类型为SHT_NOBITS时(例如.bss节),说明该节在目标文件中并不占用空间大小,所以此时成员sh_offset的数值代表的是概念上的偏移值。

* sh_size

This member gives the section's size in bytes. Unless the section type is SHT_NOBITS, the section occupies sh_size bytes in the file. A section of type SHT_NOBITS may have a non-zero size, but it occupies no space in the file.

成员sh_size说明的是该节的大小。当节的类型不是SHT_NOBITS时,成员sh_size的数值就是该节在目标文件中的实际大小;当节的类型是SHT_NOBITS时,尽管sh_size的数值有可能不是0,但是其实该节在目标文件中不占用实际大小。

* sh_link

This member holds a section header table index link, whose interpretation depends on the section type. A table below describes the values.

成员sh_link的数值代表的是一个节头表索引值,具体是哪个节会因节的类型不同而不同。

* sh_info

This member holds extra information, whose interpretation depends on the section type. A table below describes the values. If the sh_flags field for this section header includes the attribute SHF_INFO_LINK, then this member represents a section header table index.

成员sh_info的意义会因节的类型的不同而不同。

特别的,类型为SHT_REL或者SHT_RELA的节,其sh_flags会包含属性标志SHF_INFO_LINK,此时sh_info代表的是一个节头表索引值,指代需要做重定位操作的节。

* sh_addralign

Some sections have address alignment constraints. For example, if a section holds a doubleword, the system must ensure doubleword alignment for the entire section. The value of sh_addr must be congruent to 0, modulo the value of sh_addralign. Currently, only 0 and positive integral powers of two are allowed. Values 0 and 1 mean the section has no alignment constraints.

有一些节有字节对齐的限制。例如,如果一个节中有双字节类型的数据,那么系统必须保证该节的字节对齐数是双字节类型大小的。也就是说,成员sh_addr的数值必须是双字节类型大小的整数倍。目前,成员sh_addralign的数值只能是0或者其他2的整数幂数值。数值0和1代表的是该节没有字节对齐要求。

* sh_entsize

Some sections hold a table of fixed-size entries, such as a symbol table. For such a section, this member gives the size in bytes of each entry. The member contains 0 if the section does not hold a table of fixed-size entries.

有一些节的数据内容是固定大小的表,例如符号表。对于这样的节,成员sh_entsize给出的是每个表项的大小。如果该成员数值为0,则说明该节的数据内容并不是一张表。


Section Type

A section header's sh_type member specifies the section's semantics.

节头表表项成员sh_type直接该节的类型。

* SHT_NULL

This value marks the section header as inactive; it does not have an associated section. Other members of the section header have undefined values.

当节头表表项成员sh_type类型为SHT_NULL时,表明该节头表表项是无效的(非活动的),目标文件中没有它对应的节,其他成员的值是未定义的(当e_shnum的值为0(SHN_UNDEF)时,真正的节个数不是存储在该表项的sh_size中吗?还有e_shstrndx,怎么不提下?)。

* SHT_PROGBITS

The section holds information defined by the program, whose format and meaning are determined solely by the program.

当节的类型是SHT_PROGBITS时表明该节中有程序定义的信息,这些信息的格式和意义完全是由程序定义的。

* SHT_SYMTAB and SHT_DYNSYM

These sections hold a symbol table. Currently, an object file may have only one section of each type, but this restriction may be relaxed in the future. Typically, SHT_SYMTAB provides symbols for link editing, though it may also be used for dynamic linking. As a complete symbol table, it may contain many symbols unnecessary for dynamic linking. Consequently, an object file may also contain a SHT_DYNSYM section, which holds a minimal set of dynamic linking symbols, to save space. See ``Symbol Table'' below for details.

当节的类型是SHT_SYMTAB或者SHT_DYNSYM时,表明该节的数据内容是符号表。

目前的目标文件中,每种类型的节只存在一个,在将来会考虑增加节的个数。

一般情况下,类型为SHT_SYMTAB的节是为静态链接器提供符号信息,尽管有的符号在程序运行时也会被动态链接器用到 -- 也就是说,SHT_SYMTAB类型的节中包含的是所有的符号信息,因此也就包含了很多动态链接器不需要的符号信息,为了动态链接的方便和高效,一般可执行文件中还包含一个类型为SHT_DYNSYM的节,该节包含的完全是动态链接器要用到的符号信息。

* SHT_STRTAB

The section holds a string table. An object file may have multiple string table sections. See ``String Table'' below for details.

当节的类型是SHT_STRTAB时,表明该节是个字符串表。

一个目标文件中,一般会包含多个类型为SHT_STRTAB的节。(.dynstr -- 动态符号 .shstrtab -- 节名 .strtab -- 所有符号)

* SHT_RELA

The section holds relocation entries with explicit addends, such as type Elf32_Rela for the 32-bit class of object files or type Elf64_Rela for the 64-bit class of object files. An object file may have multiple relocation sections. ``Relocation'' below for details.

当节的类型是SHT_RELA时,表明该节内容是一个 重定位表,表项都是带Addend的。

例如32-bit的Elf32_Rela,64-bit的Elf64_Rela。

一个目标文件,一般会包含多个类型为SHT_RELA类型的节。

* SHT_HASH

The section holds a symbol hash table. Currently, an object file may have only one hash table, but this restriction may be relaxed in the future. See ``Hash Table'' in the Chapter 5 for details.

类型为SHT_HASH的节中包含的是一个符号哈希表。

目前,一个目标文件只包含一个符号哈希表,在将来可能会增加数目。

* SHT_DYNAMIC

The section holds information for dynamic linking. Currently, an object file may have only one dynamic section, but this restriction may be relaxed in the future. See ``Dynamic Section'' in Chapter 5 for details.

类型为SHT_DYNAMIC的节的内容是用来提供给动态链接器使用的。

目前,一个目标文件中只包含一个类型为SHT_DYNAMIC的节,在将来可能会增加数目。

* SHT_NOTE

The section holds information that marks the file in some way. See ``Note Section'' in Chapter 5 for details.

有时,供应商或系统构建人员需要用特殊信息标记目标文件,这样其它程序就可以根据这些信息检查程序一致性、兼容性等。

这些信息一般就存在类型为SHT_NOTE的节中。

* SHT_NOBITS

A section of this type occupies no space in the file but otherwise resembles SHT_PROGBITS. Although this section contains no bytes, the sh_offset member contains the conceptual file offset.

一个类型为SHT_NOBITS的节除了在文件中不占空间之外,其他的属性跟类型为SHT_PROGBITS的节很类似。

尽管这种类型的节在文件中不占空间,但是它有一个概念上的文件偏移的(典型的例子当属.bss节)。

* SHT_REL

The section holds relocation entries without explicit addends, such as type Elf32_Rel for the 32-bit class of object files or type Elf64_Rel for the 64-bit class of object files. An object file may have multiple relocation sections. See ``Relocation'' below for details.

当节的类型是SHT_REL时,表明该节内容是一个 重定位表,不过与类型为SHT_RELA的节不同的是 表项都不带Addend。

例如32-bit的Elf32_Rel,64-bit的Elf64_Rel。

一个目标文件,一般会包含多个类型为SHT_REL类型的节。

* SHT_SHLIB

This section type is reserved but has unspecified semantics.

该类型作为保留值。

* SHT_INIT_ARRAY

This section contains an array of pointers to initialization functions, as described in ``Initialization and Termination Functions'' in Chapter 5. Each pointer in the array is taken as a parameterless procedure with a void return.

类型为SHT_INIT_ARRAY的节中存储的是一个函数指针数组,函数的原型是void func(void),这些函数是初始化函数(initialization functions),即在main函数之前就运行的函数。

* SHT_FINI_ARRAY

This section contains an array of pointers to termination functions, as described in ``Initialization and Termination Functions'' in Chapter 5. Each pointer in the array is taken as a parameterless procedure with a void return.

类型为SHT_FINI_ARRAY的节中存储的是一个函数指针数组,函数的原型是void func(void),这些函数是终止函数(termination functions),即在main函数之后运行的函数。

* SHT_PREINIT_ARRAY

This section contains an array of pointers to functions that are invoked before all other initialization functions, as described in ``Initialization and Termination Functions'' in Chapter 5. Each pointer in the array is taken as a parameterless procedure with a void return.

类型为SHT_PREINIT_ARRAY的节中存储的是一个函数指针数组,函数原型是void func(void),这些函数同样是初始化函数,不过运行时间比类型为SHT_INIT_ARRAY节中的初始化函数还要早。

* SHT_GROUP

This section defines a section group. A section group is a set of sections that are related and that must be treated specially by the linker (see below for further details). Sections of type SHT_GROUP may appear only in relocatable objects (objects with the ELF header e_type member set to ET_REL). The section header table entry for a group section must appear in the section header table before the entries for any of the sections that are members of the group.

* SHT_SYMTAB_SHNDX

This section is associated with a symbol table section and is required if any of the section header indexes referenced by that symbol table contain the escape value SHN_XINDEX. The section is an array of Elf32_Word values. Each value corresponds one to one with a symbol table entry and appear in the same order as those entries. The values represent the section header indexes against which the symbol table entries are defined. Only if the corresponding symbol table entry's st_shndx field contains the escape value SHN_XINDEX will the matching Elf32_Word hold the actual section header index; otherwise, the entry must be SHN_UNDEF (0).

* SHT_LOOS through SHT_HIOS

Values in this inclusive range are reserved for operating system-specific semantics.

* SHT_LOPROC through SHT_HIPROC

Values in this inclusive range are reserved for processor-specific semantics.

* SHT_LOUSER

This value specifies the lower bound of the range of indexes reserved for application programs.

* SHT_HIUSER

This value specifies the upper bound of the range of indexes reserved for application programs. Section types between SHT_LOUSER and SHT_HIUSER may be used by the application, without conflicting with current or future system-defined section types.

Other section type values are reserved. As mentioned before, the section header for index 0 (SHN_UNDEF) exists, even though the index marks undefined section references. This entry holds the following.

其它的节类型值是保留不使用的。

前面提到过,索引值为SHN_UNDEF(0)的节头表表项是真实存在的,尽管文件中没有与之对应的真实节存在。但是它也是有作用的:当ELF文件头中的成员e_phnum/e_shnum/e_shstrndx不足以表示真实大小时,就需要参考该特殊节中的相应成员,具体如下表:

缺画


Section Attribute Flag

A section header's sh_flags member holds 1-bit flags that describe the section's attributes. Defined values appear in the following table; other values are reserved.

节头表表项中成员sh_flags用来描述该节的各种属性。
节头表表项成员sh_flags中一个bit对应该节的一个属性,当某种属性设置时,相应位设置为1,反之设置为0。

缺画

If a flag bit is set in sh_flags, the attribute is ``on'' for the section. Otherwise, the attribute is ``off'' or does not apply. Undefined attributes are set to zero.

当成员sh_flags的某个位设置为1时,说明该节具备相应的属性。反之,则说明该节不具备相应的属性,或者说该属性根本就不适用该类型的文件。sh_flags中还有很多很多bit并未定义对应什么属性,这些bit设置为0。

* SHF_WRITE

The section contains data that should be writable during process execution.
属性标志SHF_WRITE说明当该程序在运行时,该节的数据是可写的。


* SHF_ALLOC

The section occupies memory during process execution. Some control sections do not reside in the memory image of an object file; this attribute is off for those sections.

* SHF_EXECINSTR

The section contains executable machine instructions.


* SHF_MERGE

The data in the section may be merged to eliminate duplication. Unless the SHF_STRINGS flag is also set, the data elements in the section are of a uniform size. The size of each element is specified in the section header's sh_entsize field. If the SHF_STRINGS flag is also set, the data elements consist of null-terminated character strings. The size of each character is specified in the section header's sh_entsize field.
Each element in the section is compared against other elements in sections with the same name, type and flags. Elements that would have identical values at program run-time may be merged. Relocations referencing elements of such sections must be resolved to the merged locations of the referenced values. Note that any relocatable values, including values that would result in run-time relocations, must be analyzed to determine whether the run-time values would actually be identical. An ABI-conforming object file may not depend on specific elements being merged, and an ABI-conforming link editor may choose not to merge specific elements.

* SHF_STRINGS

The data elements in the section consist of null-terminated character strings. The size of each character is specified in the section header's sh_entsize field.

* SHF_INFO_LINK

The sh_info field of this section header holds a section header table index.

* SHF_LINK_ORDER

This flag adds special ordering requirements for link editors. The requirements apply if the sh_link field of this section's header references another section (the linked-to section). If this section is combined with other sections in the output file, it must appear in the same relative order with respect to those sections, as the linked-to section appears with respect to sections the linked-to section is combined with.

参考链接:

Sections》《Sections

重定位类型分析

What are the GOT and PLT?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值