An object file’s symbol table holds information needed to locate and relocate a program’s symbolic definitions and references. A symbol table index is a subscript into this array. Index 0 both designates the first entry in the table and serves as the undefined symbol index. The contents of the initial entry are specified later in this section.

ELF文件中的“符号表(symbol table)”包含的是程序中的符号信息 -- 这些符号代表的或许是定义(例如定义全局变量时使用的变量名,或者定义函数时使用的函数名),或许代表的是引用(例如使用关键字extern声明的变量或函数时使用的符号名称)。当代表的是定义时,在链接阶段链接器需要为它们重定位;当代表的是引用时,在链接阶段链接器需要在其他编译模块定位到该符号的定义。

符号表其实是所有符号信息的集合统称,即符号表是所有符号信息一起组成的一个数组,所以一个符号表索引(symbol table index) 对应该数组中的一个(符号表)表项。

其中,索引值0有双重含义:一般情况下代表的意思是指代符号表的第一个表项,然而一个未定义符号却也使用STN_UNDEF(数值为0)来指定其节头表索引值。

关于符号表第一表项的内容,下文会提到。

A symbol table entry has the following format.

一个符号表表项的数据结构定义如下:

/* Symbol table entry.  */typedef struct
{Elf32_Word    st_name;                /* Symbol name (string tbl index) */Elf32_Addr    st_value;               /* Symbol value */Elf32_Word    st_size;                /* Symbol size */unsigned char st_info;                /* Symbol type and binding */unsigned char st_other;               /* Symbol visibility */Elf32_Section st_shndx;               /* Section index */
} Elf32_Sym;typedef struct
{Elf64_Word    st_name;                /* Symbol name (string tbl index) */unsigned char st_info;                /* Symbol type and binding */unsigned char st_other;               /* Symbol visibility */Elf64_Section st_shndx;               /* Section index */Elf64_Addr    st_value;               /* Symbol value */Elf64_Xword   st_size;                /* Symbol size */
} Elf64_Sym;

st_name 符号名称

This member holds an index into the object file's symbol string table, which holds the character representations of the symbol names. If the value is non-zero, it represents a string table index that gives the symbol name. Otherwise, the symbol table entry has no name.

st_name成员其实不是一个字符串,而是一个数值,代表的是目标文件中 字符串表 中的一个索引值, 那里才真正存储着该符号的名称对应的字符串。如果st_name成员数值不为0,则代表该符号有符号名称。否则,说明该符号没有名称。

NOTE:External C symbols have the same names in C and object files' symbol tables.

注意:在C程序中的 具有外部链接属性的符号 的名称 和 最后生成的目标文件中的符号表中的符号名称 是相同的,这点与C++不同。

st_value 符号数值

This member gives the value of the associated symbol. Depending on the context, this may be an absolute value, an address, and so on; details appear below.

st_value成员给出了相应的符号值。这个符号值具体是什么意思,是要依据上下文的(主要依据不同的符号属性和不同的目标文件),也许是个绝对值,也许是个地址值,等等。

st_size 符号大小

Many symbols have associated sizes. For example, a data object's size is the number of bytes contained in the object. This member holds 0 if the symbol has no size or an unknown size.

很多类型的符号都是有大小属性的。例如,一个数据对象的大小指的是它实际在目标文件中占的字节数。st_size成员如果是0的话,说明这个符号在目标文件中不占用任何字节数(例如common symbols)或者当前是未知大小的(例如undefined symbols)。

st_info 符号的类型 和 绑定属性

This member specifies the symbol's type and binding attributes. A list of the values and meanings appears below. The following code shows how to manipulate the values for both 32 and 64-bit objects.

成员st_info指定了符号的类型(低四位)和绑定属性(高四位)。不同的符号类型/符号绑定属性以及意义将在下文列出。下面的宏分别展现了如何操作成员st_info。通过st_info得到类型和绑定属性,以及如何通过类型和绑定属性而得到st_info。

st_other 符号的可见性

This member currently specifies a symbol's visibility. A list of the values and meanings appears below. The following code shows how to manipulate the values for both 32 and 64-bit objects. Other bits contain 0 and have no defined meaning.

st_other成员目前指定符号的可见性属性。不同的可见性属性值以及意义将在文章后续给出。下面的宏分别展示了在32位和64位机器上如何操作st_other。除了低两位,其余的位都为0并且没有意义。

* st_shndx  符号(关联的节)的节头表索引值

Every symbol table entry is defined in relation to some section. This member holds the relevant section header table index. As the sh_link and sh_info interpretation table and the related text describe, some section indexes indicate special meanings.

每一个符号表项所代表的特定符号信息都是和一个特定的 “节” 相关联的,st_shndx成员代表的就是这个特定“节”的节头表索引(比如一个定义的全局变量global,那么符号global的属性st_shndx值应该就是.data节所对应的节头表索引;定义的函数foo,那么符号foo的属性st_shndx值应该就是.text节所对应的节头表索引)。部分符号的节头表索引会有特殊的含义。

If this member contains SHN_XINDEX, then the actual section header index is too large to fit in this field. The actual value is contained in the associated section of type SHT_SYMTAB_SHNDX.

如果这个成员的值是SHN_XINDEX时,证明该符号关联的节的节头表索引值过大,超出了st_shndx所能代表的最大数值。那么真正的节头表索引值存储在一个类型为SHT_SYMTAB_SHNDX的扩展节中。


Symbol Binding

A symbol's binding determines the linkage visibility and behavior.

一个符号的绑定属性决定了该符号在链接阶段的可见性以及链接时的处理方式。

例如全局符号和本地符号的链接可见性是不同的,而当出现同名的全局符号和弱符号时,链接器会做出相应的处理(这点可参考下文对全局符号和弱符号不同点的描述)。

* STB_LOCAL 本地符号

Local symbols are not visible outside the object file containing their definition. Local symbols of the same name may exist in multiple files without interfering with each other.

当一个符号的绑定属性是STB_LOCAL时,则表明该符号的链接属性是internal的,对其他目标文件来说是不可见的,即不可访问。所以不同的目标文件中的本地符号可以同名,它们彼此不会干扰对方。

* STB_GLOBAL 全局符号

Global symbols are visible to all object files being combined. One file's definition of a global symbol will satisfy another file's undefined reference to the same global symbol.

当一个符号的绑定属性是STB_GLOBAL时,则表明该符号的链接属性是external的,对其他目标文件来说是可见的,即可以访问。

* STB_WEAK 弱符号

Weak symbols resemble global symbols, but their definitions have lower precedence.

当一个符号的绑定属性是STB_WEAK时,则表明该符号是个弱符号,它和全局符号有类似的地方,即链接属性也是external的。但是链接器处理弱符号的优先级相对全局符号要低,即当全局符号和弱符号同名时,链接器最后使用全局符号而忽略弱符号。

* STB_LOOS through STB_HIOS

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

* STB_LOPROC through STB_HIPROC

Values in this inclusive range are reserved for processor-specific semantics. If meanings are specified, the processor supplement explains them.

Global and weak symbols differ in two major ways.

全局符号和弱符号的区别主要在两个方面。

When the link editor combines several relocatable object files, it does not allow multiple definitions of STB_GLOBAL symbols with the same name. On the other hand, if a defined global symbol exists, the appearance of a weak symbol with the same name will not cause an error. The link editor honors the global definition and ignores the weak ones. Similarly, if a common symbol exists (that is, a symbol whose st_shndx field holds SHN_COMMON), the appearance of a weak symbol with the same name will not cause an error. The link editor honors the common definition and ignores the weak ones.

当链接器链接若干可重定位文件时,它是不允许具有STB_GLOBAL属性的符号以相同名字进行重复定义的。而如果一个已定义的全局符号存在,则即便另一个具有相同名字的弱符号存在也不会引起错误。链接器将认可全局符号的定义而忽略弱符号的定义。与此类似的,如果一个符号被放在COMMON块(就是说这个符号的st_shndx成员的值为SHN_COMMON),则一个同名的弱符号也不会引起错误。链接器同样认可放在COMMON块符号的定义而忽略其他的弱符号。

-----------------------------------------------------------------------
>>>     STB_GLOBAL > SHN_COMMON > STB_WEAK
-----------------------------------------------------------------------

When the link editor searches archive libraries [see ``Archive File’’
in Chapter 7], it extracts archive members that contain definitions of
undefined global symbols. The member’s definition may be either a
global or a weak symbol. The link editor does not extract archive
members to resolve undefined weak symbols. Unresolved weak symbols
have a zero value.

在链接静态库的情况下:

(1)当链接器遇到一个未定义的全局符号(global symbol)时,链接器会去提取静态库,试图找到这个符号定义。在静态库中,这个符号可以是全局符号,也可以是弱符号。

(2)当链接器遇到一个未定义的弱符号(weak symbols)时,链接器是不会去提取静态库的,而是直接将该弱符号的值赋为0。(可以参考文章《Fun with weak symbols》。试验结果发现:如果引用了静态库中的非弱符号,那么即使链接器遇到了一个未定义的弱符号,依然会去静态库中解析符号)

NOTE: The behavior of weak symbols in areas not specified by this document is implementation defined. Weak symbols are intended primarily for use in system software. Applications using weak symbols are unreliable since changes in the runtime environment might cause the execution to fail.

注意: 弱符号在上述规则之外地方的行为是实现相关的。弱符号主要用于系统软件中,不推荐在应用程序中使用弱符号,因为在运行时,弱符号很容易被覆盖掉。

In each symbol table, all symbols with STB_LOCAL binding precede the weak and global symbols. As ``Sections'', above describes, a symbol table section's sh_info section header member holds the symbol table index for the first non-local symbol.

在符号表中,不同绑定属性的符号所在位置是不同的 -- 所有的本地符号都被安放在符号表的前头,紧接着的才是全局符号和弱符号。前文提到过,一个符号表节对应的节头表项的节头表成员sh_info中的数值代表的是第一个绑定属性为非STB_LOCAL的符号的符号表索引值(即最后一个绑定属性为STB_LOCAL符号的符号表索引值加1)。


Symbol Types

A symbol's type provides a general classification for the associated entity.

一个符号的类型为该符号关联的实体进行分类。

* STT_NOTYPE

The symbol's type is not specified.

当符号类型是STT_NOTYPE时,表明该符号未指定类型或者当前还不知道该符号的类型。

* STT_OBJECT

The symbol is associated with a data object, such as a variable, an array, and so on.

当符号类型是STT_OBJECT时,表明该符号关联的实体是个数据对象,例如一个变量,数组等。

* STT_FUNC

The symbol is associated with a function or other executable code.

当符号类型是STT_FUNC时,表明该符号关联的实体是个函数或者其他的可执行代码。

* STT_SECTION

The symbol is associated with a section. Symbol table entries of this type exist primarily for relocation and normally have STB_LOCAL binding.

当符号类型是STT_SECTION时,表明该符号关联的实体是个节。一般符号表中的一个符号是这个类型时,主要是用于重定位的目的,并且其绑定属性一般情况下是STB_LOCAL。

* STT_FILE

Conventionally, the symbol's name gives the name of the source file associated with the object file. A file symbol has STB_LOCAL binding, its section index is SHN_ABS, and it precedes the other STB_LOCAL symbols for the file, if it is present.

通常情况下,当一个符号的类型是STT_FILE时,这个符号的名称就是该目标文件相关联的源文件的名称。这种类型的符号的绑定属性是STB_LOCAL的,与它相关的节的节头表索引值为SHN_ABS,并且如果在符号表中存在此种符号的话,那么其位置排在本地符号(STB_LOCAL)的前头。

* STT_COMMON

The symbol labels an uninitialized common block. See below for details.

当符号类型是STT_COMMON时,表明该符号是个公用块数据对象,并且这个公用块在目标文件中实际是未被分配空间的。

* STT_TLS

The symbol specifies a Thread-Local Storage entity. When defined, it gives the assigned offset for the symbol, not the actual address. Symbols of type STT_TLS can be referenced by only special thread-local storage relocations and thread-local storage relocations can only reference symbols with type STT_TLS. Implementation need not support thread-local storage.

当符号的类型是STT_TLS时,表明该符号对应变量存储在线程局部存储内。

* STT_LOOS through STT_HIOS

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

* STT_LOPROC through STT_HIPROC

Values in this inclusive range are reserved for processor-specific semantics. If meanings are specified, the processor supplement explains them.

Function symbols (those with type STT_FUNC) in shared object files have special significance. When another object file references a function from a shared object, the link editor automatically creates a procedure linkage table entry for the referenced symbol. Shared object symbols with types other than STT_FUNC will not be referenced automatically through the procedure linkage table.

链接器对那些存在于共享库中的函数符号(即那些符号类型为STT_FUNC的符号)有特殊的处理。当其它的目标文件引用了共享库中的函数时,链接器会自动的为这个引用符号创建一个 程序连接表(PLT)表项。而共享库中符号类型为非STT_FUNC的符号则不是通过 程序连接表(PLT)自动访问。例如,可执行程序引用共享库中的共享对象(即符号类型为STT_OBJECT的符号)时,链接器会创建一个copy reloc来解决。

Symbols with type STT_COMMON label uninitialized common blocks. In relocatable objects, these symbols are not allocated and must have the special section index SHN_COMMON (see below). In shared objects and executables these symbols must be allocated to some section in the defining object.

当一个符号的类型是STT_COMMON时,则表明该符号是个公用块数据对象,且这个公用块在目标文件中实际是未被分配空间。在可重定位文件中,并不会为这些符号分配空间,并且与之相关的节的节头表索引值必须是SHN_COMMON。但是在共享库和可执行文件中,这些符号必须在相应的节(bss)中分配空间。

In relocatable objects, symbols with type STT_COMMON are treated just as other symbols with index SHN_COMMON. If the link-editor allocates space for the SHN_COMMON symbol in an output section of the object it is producing, it must preserve the type of the output symbol as STT_COMMON.

在可重定位文件中,对符号类型是STT_COMMON的符号的处理方式跟那些与之相关节的节头表索引值为SHN_COMMON的符号的处理方式是一样的。如果链接器在生成可执行文件或者共享库时,为这类符号分配了空间的话(.bss),那么必须保留该符号的类型为STT_COMMON.(why? -- 下文给出)

When the dynamic linker encounters a reference to a symbol that resolves to a definition of type STT_COMMON, it may (but is not required to) change its symbol resolution rules as follows: instead of binding the reference to the first symbol found with the given name, the dynamic linker searches for the first symbol with that name with type other than STT_COMMON. If no such symbol is found, it looks for the STT_COMMON definition of that name that has the largest size.

当动态链接器(/lib/ld-linux.so.2)遇到一个符号引用是指向符号类型是STT_COMMON的符号定义时,那么动态链接器也许(但是并不推荐这样做)会改变符号解析的法则如下:并不会像其它类型的符号一样,将该引用绑定到第一个同名的符号定义,而是先搜索类型为非STT_COMMON的符号定义,如果存在则绑定到该符号定义。如果不存在,那么动态链接器这才在符号类型为STT_COMMON的定义中搜索,并且最终选择占用内存空间最大的那个。


Symbol Visibility

A symbol's visibility, although it may be specified in a relocatable object, defines how that symbol may be accessed once it has become part of an executable or shared object.

尽管我们可以在编译阶段(通过在source code中或者编译器选项指定符号的可见性)和静态链接阶段(通过export list文件)指定符号的可见性属性,但其实可见性属性控制的是一个符号在运行时的解析行为。

STV_DEFAULT

The visibility of symbols with the STV_DEFAULT attribute is as specified by the symbol's binding type. That is, global and weak symbols are visible outside of their defining component (executable file or shared object). Local symbols are hidden, as described below. Global and weak symbols are also preemptable, that is, they may by preempted by definitions of the same name in another component.

当符号的可见性是STV_DEFAULT时,那么该符号的可见性由符号的绑定属性决定。这类情况下,(可执行文件和共享库中的)全局符号和弱符号默认是外部可访问的,本地符号默认外部是无法被访问的。但是,可见性是STV_DEFAULT的全局符号和弱符号是可被覆盖的。什么意思?举个最典型的例子,共享库中的可见性值为STV_DEFAULTD的全局符号和弱符号是可被可执行文件中的同名符号覆盖的。

NOTE: An implementation may restrict the set of global and weak symbols that are externally visible.

注意:一个具体的实现可能会限制对外可访问的全局符号和弱符号的数量。

* STV_PROTECTED

A symbol defined in the current component is protected if it is visible in other components but not preemptable, meaning that any reference to such a symbol from within the defining component must be resolved to the definition in that component, even if there is a definition in another component that would preempt by the default rules. A symbol with STB_LOCAL binding may not have STV_PROTECTED visibility. If a symbol definition with STV_PROTECTED visibility from a shared object is taken as resolving a reference from an executable or another shared object, the SHN_UNDEF symbol table entry created has STV_DEFAULT visibility.

当符号的可见性是STV_PROTECTED时,它是外部可见的,这点跟可见性是STV_DEFAULT的一样,但不同的是它是不可覆盖的。这样的符号在共享库中比较常见。不可覆盖意味着如果是在该符号所在的共享库中访问这个符号,那么就一定是访问的这个符号,尽管可执行文件中也会存在同样名字的符号也不会被覆盖掉。

规定绑定属性为STB_LOCAL的符号的可见性不可以是STV_PROTECTED。

NOTE: The presence of the STV_PROTECTED flag on a symbol in a given load module does not affect the symbol resolution rules for references to that symbol from outside the containing load module.

STV_HIDDEN

A symbol defined in the current component is hidden if its name is not visible to other components. Such a symbol is necessarily protected. This attribute may be used to control the external interface of a component. Note that an object named by such a symbol may still be referenced from another component if its address is passed outside.

A hidden symbol contained in a relocatable object must be either removed or converted to STB_LOCAL binding by the link-editor when the relocatable object is included in an executable file or shared object.

当符号的可见性是STV_HIDDEN时,证明该符号是外部无法访问的。这个属性主要用来控制共享库对外接口的数量。需要注意的是,一个可见性为STV_HIDDEN的数据对象,如果能获取到该符号的地址,那么依然是可以访问或者修改该数据对象的。

在可重定位文件中,如果一个符号的可见性是STV_HIDDEN的话,那么在链接生成可执行文件或者共享库的过程中,该符号要么被删除,要么绑定属性变成STB_LOCAL。

STV_INTERNAL

The meaning of this visibility attribute may be defined by processor supplements to further constrain hidden symbols. A processor supplement's definition should be such that generic tools can safely treat internal symbols as hidden.

An internal symbol contained in a relocatable object must be either removed or converted to STB_LOCAL binding by the link-editor when the relocatable object is included in an executable file or shared object.

Symbol Values

Symbol table entries for different object file types have slightly different interpretations for the st_value member.

在不同的目标文件中,对成员st_value的意义解释也是不同的。

  • In relocatable files, st_value holds alignment constraints for a symbol whose section index is SHN_COMMON.

在可重定位文件中,若符号的st_shndx等于SHN_COMMON,则st_value的值代表的是该符号的对齐字节数。

  • In relocatable files, st_value holds a section offset for a defined symbol. st_value is an offset from the beginning of the section that st_shndx identifies.

在可重定位文件中,若一个符号是已定义的,那么st_value的值代表的是该符号其所在的节中的偏移量 -- 当然了,这个节是由st_shndx指定的。

  • In executable and shared object files, st_value holds a virtual address. To make these files' symbols more useful for the dynamic linker, the section offset (file interpretation) gives way to a virtual address (memory interpretation) for which the section number is irrelevant.

在可执行文件和共行库中,一个已定义符号的st_value的值不再是一个节偏移量,而是一个虚拟地址,因为动态链接器需要知道符号的内存地址。 -- 因为虚拟地址是与节无关的,所以这种情况下,我们不需要关心st_shndx的值。

Although the symbol table values have similar meanings for different object files, the data allows efficient access by the appropriate programs.

综合以上三点可知,在不同的目标文件中st_value的值代表的含义不同。这样设计是有原因的:在静态链接阶段,链接器需要的是符号在文件中的位置信息,而在程序运行时,动态链接器需要的是却符号在内存中的位置信息。

以下程序用于输出ELF所有符号的信息(即sh_type为SHT_SYMTAB或者SHT_DYNSYM),模仿readelf的--syms选项:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <link.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <elf.h>
#include <error.h>
#include <errno.h>#define ELFW(type)  _ELFW (ELF, __ELF_NATIVE_CLASS, type)
#define _ELFW(e,w,t)    _ELFW_1 (e, w, _##t)
#define _ELFW_1(e,w,t)  e##w##tstatic const char *st_type(unsigned int stype)
{switch (stype) {case STT_NOTYPE: return "NOTYPE";case STT_OBJECT: return "OBJECT";case STT_FUNC: return "FUNC";case STT_SECTION: return "SECTION";case STT_FILE: return "FILE";case STT_COMMON: return "COMMON";case STT_TLS: return "TLS";case STT_LOOS ... STT_HIOS: return "OS_SPEC";case STT_LOPROC ... STT_HIPROC: return "PROC_SPEC";default: return "<unknown symbol type>";}
}static const char *st_bind(unsigned int stbind)
{switch (stbind) {case STB_LOCAL: return "LOCAL";case STB_GLOBAL: return "GLOBAL";case STB_WEAK: return "WEAK";
//      case STB_GNU_UNIQUE: return "UNIQUE";case STB_LOOS ... STB_HIOS: return "OS";case STB_LOPROC ... STB_HIPROC: return "PROC";default: return "<unknown symbol bind>";}
}static const char *st_vis(unsigned int svis)
{switch (svis) {case STV_DEFAULT: return "DEFAULT";case STV_INTERNAL: return "INTERNAL";case STV_HIDDEN: return "HIDDEN";case STV_PROTECTED: return "PROTECTED";default: return "<unknown symbol vis>";}
}static const char *st_shndx(unsigned int shndx)
{static char s_shndx[32];switch (shndx) {case SHN_UNDEF: return "UND";    case SHN_ABS: return "ABS";case SHN_COMMON: return "COMMON";case SHN_LOPROC ... SHN_HIPROC: return "PRC";case SHN_LOOS ... SHN_HIOS: return "OS";default:  (void)snprintf(s_shndx, sizeof(s_shndx), "%u", shndx); return (const char *)s_shndx;}
}static void print_syms(ElfW(Shdr) *shdrs, const char *shstrtab,  const char *shname, ElfW(Sym) *syms, size_t entries, const char *strtab)
{printf("Symbol table '%s' contains %zu entries:\n", shname, entries);printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type","Bind", "Vis", "Ndx", "Name");for (size_t i = 0; i < entries; i++) {ElfW(Sym) *sym = &syms[i];printf("%6zu:", i);printf(" %16.16jx", (uintmax_t)sym->st_value);printf(" %5ju", (uintmax_t)sym->st_size);printf(" %-7s", st_type(ELFW(ST_TYPE)(sym->st_info)));printf(" %-6s", st_bind(ELFW(ST_BIND)(sym->st_info)));printf(" %-8s", st_vis(ELFW(ST_VISIBILITY)(sym->st_other)));printf(" %3s", st_shndx(sym->st_shndx));if (strcmp("SECTION", st_type(ELFW(ST_TYPE)(sym->st_info))) == 0) {printf(" %s", shstrtab + shdrs[sym->st_shndx].sh_name);    } else {printf(" %s", strtab + sym->st_name);}printf("\n");}
}int main(int argc, char *argv[])
{int fd;char *file_mmbase;struct stat file_status;size_t fsize;ElfW(Ehdr) *ehdr;ElfW(Shdr) *shdrs;size_t shnum, shstrndx;const char *shstrtab;//    [ 6] .dynstr           STRTAB          0000000000000468 000468 0000dd 00   A  0   0  1
//  [32] .strtab           STRTAB          0000000000000000 003d28 000322 00      0   0  1
//  [33] .shstrtab         STRTAB          0000000000000000 00404a 00013e 00      0   0  1if (argc != 2) {error(EXIT_FAILURE, 0, "Usage: %s file-name", argv[0]);}if ((fd = open(argv[1], O_RDONLY)) < 0) {error(EXIT_FAILURE, errno, "open %s failed", argv[1]);}if (fstat(fd, &file_status) < 0) {error(EXIT_FAILURE, errno, "get file %s info err", argv[1]);}fsize = (size_t)file_status.st_size;if ((file_mmbase = mmap(NULL, fsize, PROT_READ, MAP_PRIVATE, fd, (off_t)0)) == MAP_FAILED) {error(EXIT_FAILURE, errno, "mmap file %s err", argv[1]);}ehdr = (ElfW(Ehdr) *)file_mmbase;shdrs = (ElfW(Shdr) *)(file_mmbase + ehdr->e_shoff);shnum = ehdr->e_shnum == 0 ? shdrs[0].sh_size : ehdr->e_shnum;shstrndx = ehdr->e_shstrndx == SHN_XINDEX ? shdrs[0].sh_link : ehdr->e_shstrndx;shstrtab = file_mmbase + shdrs[shstrndx].sh_offset;for (size_t i = 0; i < shnum; i++) {ElfW(Shdr) *shdr = &shdrs[i];  if (shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM) {const char *shname = shstrtab + shdr->sh_name;ElfW(Sym) *syms = (ElfW(Sym *))(file_mmbase + shdr->sh_offset); size_t entries = shdr->sh_size / shdr->sh_entsize;// sh_info: One greater than the symbol table index of //           the last local symbol (binding STB_LOCAL).// printf("shdr->sh_info = %u\n", shdr->sh_info);// sh_link: .strtab or .dynstr (The section header index of //          the associated string table.)const char *strtab = file_mmbase + shdrs[shdr->sh_link].sh_offset;print_syms(shdrs, shstrtab, shname, syms, entries, strtab); }}(void)munmap(file_mmbase, fsize);(void)close(fd);exit(EXIT_SUCCESS);
}

程序输出结果如下:

[00:26:41@astrol:/tmp]$ readelf --syms --wide print_symbol 

Symbol table '.dynsym' contains 18 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar@GLIBC_2.2.5 (2)
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@GLIBC_2.2.5 (2)
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mmap@GLIBC_2.2.5 (2)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5 (2)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND snprintf@GLIBC_2.2.5 (2)
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close@GLIBC_2.2.5 (2)
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@GLIBC_2.2.5 (2)
     9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@GLIBC_2.2.5 (2)
    10: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __fxstat@GLIBC_2.2.5 (2)
    12: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND munmap@GLIBC_2.2.5 (2)
    13: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND error@GLIBC_2.2.5 (2)
    14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND open@GLIBC_2.2.5 (2)
    15: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@GLIBC_2.2.5 (2)
    16: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    17: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@GLIBC_2.2.5 (2)

Symbol table '.symtab' contains 82 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000238     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000254     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000274     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000298     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000000002b8     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000468     0 SECTION LOCAL  DEFAULT    6 
     7: 000000000000053a     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000560     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000000580     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000000640     0 SECTION LOCAL  DEFAULT   10 
    11: 0000000000000760     0 SECTION LOCAL  DEFAULT   11 
    12: 0000000000000780     0 SECTION LOCAL  DEFAULT   12 
    13: 0000000000000850     0 SECTION LOCAL  DEFAULT   13 
    14: 0000000000000860     0 SECTION LOCAL  DEFAULT   14 
    15: 0000000000001320     0 SECTION LOCAL  DEFAULT   15 
    16: 0000000000001330     0 SECTION LOCAL  DEFAULT   16 
    17: 0000000000001590     0 SECTION LOCAL  DEFAULT   17 
    18: 0000000000001600     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000201d60     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000201d68     0 SECTION LOCAL  DEFAULT   20 
    21: 0000000000201d70     0 SECTION LOCAL  DEFAULT   21 
    22: 0000000000201f60     0 SECTION LOCAL  DEFAULT   22 
    23: 0000000000202000     0 SECTION LOCAL  DEFAULT   23 
    24: 0000000000202020     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000000000     0 SECTION LOCAL  DEFAULT   25 
    26: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    27: 0000000000000890     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    28: 00000000000008d0     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    29: 0000000000000920     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    30: 0000000000202020     1 OBJECT  LOCAL  DEFAULT   24 completed.7696
    31: 0000000000201d68     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fini_array_entry
    32: 0000000000000960     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    33: 0000000000201d60     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_entry
    34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS print_symbol.c
    35: 000000000000096a   139 FUNC    LOCAL  DEFAULT   14 st_type
    36: 00000000000009f5   103 FUNC    LOCAL  DEFAULT   14 st_bind
    37: 0000000000000a5c    77 FUNC    LOCAL  DEFAULT   14 st_vis
    38: 0000000000000aa9   145 FUNC    LOCAL  DEFAULT   14 st_shndx
    39: 0000000000202040    32 OBJECT  LOCAL  DEFAULT   24 s_shndx.4238
    40: 0000000000000b3a   575 FUNC    LOCAL  DEFAULT   14 print_syms
    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    42: 00000000000017bc     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    43: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    44: 0000000000001310    15 FUNC    LOCAL  DEFAULT   14 fstat
    45: 0000000000201d68     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end
    46: 0000000000201d70     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC
    47: 0000000000201d60     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start
    48: 0000000000001590     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    49: 0000000000201f60     0 OBJECT  LOCAL  DEFAULT   22 _GLOBAL_OFFSET_TABLE_
    50: 0000000000001300     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar@@GLIBC_2.2.5
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@@GLIBC_2.2.5
    53: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
    54: 0000000000202000     0 NOTYPE  WEAK   DEFAULT   23 data_start
    55: 0000000000202010     0 NOTYPE  GLOBAL DEFAULT   23 _edata
    56: 0000000000001320     0 FUNC    GLOBAL DEFAULT   15 _fini
    57: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mmap@@GLIBC_2.2.5
    58: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND snprintf@@GLIBC_2.2.5
    60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close@@GLIBC_2.2.5
    61: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_2.2.5
    62: 0000000000202000     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    63: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@@GLIBC_2.2.5
    64: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    65: 0000000000202008     0 OBJECT  GLOBAL HIDDEN    23 __dso_handle
    66: 0000000000001330     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    67: 0000000000001290   101 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __fxstat@@GLIBC_2.2.5
    69: 0000000000202060     0 NOTYPE  GLOBAL DEFAULT   24 _end
    70: 0000000000000860    43 FUNC    GLOBAL DEFAULT   14 _start
    71: 0000000000202010     0 NOTYPE  GLOBAL DEFAULT   24 __bss_start
    72: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND munmap@@GLIBC_2.2.5
    73: 0000000000000d79  1301 FUNC    GLOBAL DEFAULT   14 main
    74: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND error@@GLIBC_2.2.5
    75: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND open@@GLIBC_2.2.5
    76: 0000000000001310    15 FUNC    GLOBAL HIDDEN    14 __fstat
    77: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@@GLIBC_2.2.5
    78: 0000000000202010     0 OBJECT  GLOBAL HIDDEN    23 __TMC_END__
    79: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    80: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.2.5
    81: 0000000000000760     0 FUNC    GLOBAL DEFAULT   11 _init
[00:26:48@astrol:/tmp]$ ./print_symbol print_symbol 
Symbol table '.dynsym' contains 18 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mmap
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND snprintf
     7: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main
     9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp
    10: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    11: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __fxstat
    12: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND munmap
    13: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND error
    14: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND open
    15: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit
    16: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    17: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize
Symbol table '.symtab' contains 82 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000238     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000254     0 SECTION LOCAL  DEFAULT    2 
     3: 0000000000000274     0 SECTION LOCAL  DEFAULT    3 
     4: 0000000000000298     0 SECTION LOCAL  DEFAULT    4 
     5: 00000000000002b8     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000468     0 SECTION LOCAL  DEFAULT    6 
     7: 000000000000053a     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000560     0 SECTION LOCAL  DEFAULT    8 
     9: 0000000000000580     0 SECTION LOCAL  DEFAULT    9 
    10: 0000000000000640     0 SECTION LOCAL  DEFAULT   10 
    11: 0000000000000760     0 SECTION LOCAL  DEFAULT   11 
    12: 0000000000000780     0 SECTION LOCAL  DEFAULT   12 
    13: 0000000000000850     0 SECTION LOCAL  DEFAULT   13 
    14: 0000000000000860     0 SECTION LOCAL  DEFAULT   14 
    15: 0000000000001320     0 SECTION LOCAL  DEFAULT   15 
    16: 0000000000001330     0 SECTION LOCAL  DEFAULT   16 
    17: 0000000000001590     0 SECTION LOCAL  DEFAULT   17 
    18: 0000000000001600     0 SECTION LOCAL  DEFAULT   18 
    19: 0000000000201d60     0 SECTION LOCAL  DEFAULT   19 
    20: 0000000000201d68     0 SECTION LOCAL  DEFAULT   20 
    21: 0000000000201d70     0 SECTION LOCAL  DEFAULT   21 
    22: 0000000000201f60     0 SECTION LOCAL  DEFAULT   22 
    23: 0000000000202000     0 SECTION LOCAL  DEFAULT   23 
    24: 0000000000202020     0 SECTION LOCAL  DEFAULT   24 
    25: 0000000000000000     0 SECTION LOCAL  DEFAULT   25 
    26: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    27: 0000000000000890     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
    28: 00000000000008d0     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
    29: 0000000000000920     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
    30: 0000000000202020     1 OBJECT  LOCAL  DEFAULT   24 completed.7696
    31: 0000000000201d68     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtors_aux_fini_array_entry
    32: 0000000000000960     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    33: 0000000000201d60     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_init_array_entry
    34: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS print_symbol.c
    35: 000000000000096a   139 FUNC    LOCAL  DEFAULT   14 st_type
    36: 00000000000009f5   103 FUNC    LOCAL  DEFAULT   14 st_bind
    37: 0000000000000a5c    77 FUNC    LOCAL  DEFAULT   14 st_vis
    38: 0000000000000aa9   145 FUNC    LOCAL  DEFAULT   14 st_shndx
    39: 0000000000202040    32 OBJECT  LOCAL  DEFAULT   24 s_shndx.4238
    40: 0000000000000b3a   575 FUNC    LOCAL  DEFAULT   14 print_syms
    41: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    42: 00000000000017bc     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    43: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    44: 0000000000001310    15 FUNC    LOCAL  DEFAULT   14 fstat
    45: 0000000000201d68     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_end
    46: 0000000000201d70     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC
    47: 0000000000201d60     0 NOTYPE  LOCAL  DEFAULT   19 __init_array_start
    48: 0000000000001590     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    49: 0000000000201f60     0 OBJECT  LOCAL  DEFAULT   22 _GLOBAL_OFFSET_TABLE_
    50: 0000000000001300     2 FUNC    GLOBAL DEFAULT   14 __libc_csu_fini
    51: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND putchar@@GLIBC_2.2.5
    52: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __errno_location@@GLIBC_2.2.5
    53: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTable
    54: 0000000000202000     0 NOTYPE  WEAK   DEFAULT   23 data_start
    55: 0000000000202010     0 NOTYPE  GLOBAL DEFAULT   23 _edata
    56: 0000000000001320     0 FUNC    GLOBAL DEFAULT   15 _fini
    57: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND mmap@@GLIBC_2.2.5
    58: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@@GLIBC_2.2.5
    59: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND snprintf@@GLIBC_2.2.5
    60: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND close@@GLIBC_2.2.5
    61: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_main@@GLIBC_2.2.5
    62: 0000000000202000     0 NOTYPE  GLOBAL DEFAULT   23 __data_start
    63: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND strcmp@@GLIBC_2.2.5
    64: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    65: 0000000000202008     0 OBJECT  GLOBAL HIDDEN    23 __dso_handle
    66: 0000000000001330     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    67: 0000000000001290   101 FUNC    GLOBAL DEFAULT   14 __libc_csu_init
    68: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __fxstat@@GLIBC_2.2.5
    69: 0000000000202060     0 NOTYPE  GLOBAL DEFAULT   24 _end
    70: 0000000000000860    43 FUNC    GLOBAL DEFAULT   14 _start
    71: 0000000000202010     0 NOTYPE  GLOBAL DEFAULT   24 __bss_start
    72: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND munmap@@GLIBC_2.2.5
    73: 0000000000000d79  1301 FUNC    GLOBAL DEFAULT   14 main
    74: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND error@@GLIBC_2.2.5
    75: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND open@@GLIBC_2.2.5
    76: 0000000000001310    15 FUNC    GLOBAL HIDDEN    14 __fstat
    77: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND exit@@GLIBC_2.2.5
    78: 0000000000202010     0 OBJECT  GLOBAL HIDDEN    23 __TMC_END__
    79: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
    80: 0000000000000000     0 FUNC    WEAK   DEFAULT  UND __cxa_finalize@@GLIBC_2.2.5
    81: 0000000000000760     0 FUNC    GLOBAL DEFAULT   11 _init

以下是利用libelf库来输出符号表的内容:

#include <stdio.h>
#include <stdlib.h>
#include <err.h>
#include <fcntl.h>
#include <gelf.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#include <string.h>static const char *st_type(unsigned int stype)
{switch (stype) {case STT_NOTYPE: return "NOTYPE";case STT_OBJECT: return "OBJECT";case STT_FUNC: return "FUNC";case STT_SECTION: return "SECTION";case STT_FILE: return "FILE";case STT_COMMON: return "COMMON";case STT_TLS: return "TLS";case STT_LOOS ... STT_HIOS: return "OS_SPEC";case STT_LOPROC ... STT_HIPROC: return "PROC_SPEC";default: return "<unknown symbol type>";}
}static const char *st_bind(unsigned int stbind)
{switch (stbind) {case STB_LOCAL: return "LOCAL";case STB_GLOBAL: return "GLOBAL";case STB_WEAK: return "WEAK";
//      case STB_GNU_UNIQUE: return "UNIQUE";case STB_LOOS ... STB_HIOS: return "OS";case STB_LOPROC ... STB_HIPROC: return "PROC";default: return "<unknown symbol bind>";}
}static const char *st_vis(unsigned int svis)
{switch (svis) {case STV_DEFAULT: return "DEFAULT";case STV_INTERNAL: return "INTERNAL";case STV_HIDDEN: return "HIDDEN";case STV_PROTECTED: return "PROTECTED";default: return "<unknown symbol vis>";}
}static const char *st_shndx(unsigned int shndx)
{static char s_shndx[32];switch (shndx) {case SHN_UNDEF: return "UND";    case SHN_ABS: return "ABS";case SHN_COMMON: return "COMMON";case SHN_LOPROC ... SHN_HIPROC: return "PRC";case SHN_LOOS ... SHN_HIOS: return "OS";default:  (void)snprintf(s_shndx, sizeof(s_shndx), "%u", shndx); return (const char *)s_shndx;}
}static const char *get_symbol_name(Elf *pelf, size_t strtabndx, GElf_Sym *sym)
{if (GELF_ST_TYPE(sym->st_info) == STT_SECTION) {// get shstrndxsize_t shstrndx;if (elf_getshdrstrndx(pelf, &shstrndx) == -1) {errx(EXIT_FAILURE, "getshdrstrndx() failed: %s.", elf_errmsg(-1));}Elf_Scn *destscn;GElf_Shdr destshdr;if ((destscn = elf_getscn(pelf, sym->st_shndx)) == NULL) {errx(EXIT_FAILURE, "elf_getscn() failed: %s.", elf_errmsg(-1));}if (gelf_getshdr(destscn, &destshdr) != &destshdr) {errx(EXIT_FAILURE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));}return elf_strptr(pelf, shstrndx, destshdr.sh_name);}return  elf_strptr(pelf, strtabndx, sym->st_name);
}static void print_syms(Elf *pelf, Elf_Scn *symscn, GElf_Shdr *symshdr)
{Elf_Data *symdata;if ((symdata = elf_getdata(symscn, NULL)) == NULL) {errx(EXIT_FAILURE, "elf_getdata() failed: %s.", elf_errmsg(-1));}if (symdata->d_type != ELF_T_SYM) {errx(EXIT_FAILURE, "Elf_Type is not ELF_T_SYM."); }if (symdata->d_size <= 0) {errx(EXIT_FAILURE, "Section data size is wrong."); }assert(symshdr->sh_size == symdata->d_size);// get shstrndxsize_t shstrndx;if (elf_getshdrstrndx(pelf, &shstrndx) == -1) {errx(EXIT_FAILURE, "getshdrstrndx() failed: %s.", elf_errmsg(-1));   }const char *symshdrname = elf_strptr(pelf, shstrndx, symshdr->sh_name);if (symshdrname == NULL) {errx(EXIT_FAILURE, "elf_strptr() failed: %s,", elf_errmsg(-1));   }size_t entries; #if 0// 1entries = symshdr->sh_size / symshdr->sh_entsize;
#endif#if 0// 2 size_t entsize = gelf_fsize(pelf, ELF_T_SYM, 1, EV_CURRENT); entries = symshdr->sh_size / entsize;
#endif#if 1// 3size_t entsize = gelf_fsize(pelf, ELF_T_SYM, 1, EV_CURRENT); entries = symdata->d_size / entsize;
#endifprintf("\nSymbol table '%s' contains %zu entries:\n", symshdrname, entries);printf("%7s%9s%14s%5s%8s%6s%9s%5s\n", "Num:", "Value", "Size", "Type","Bind", "Vis", "Ndx", "Name");for (size_t i = 0; i < entries; i++) {GElf_Sym sym;if (gelf_getsym(symdata, i, &sym) != &sym) {errx(EXIT_FAILURE, "gelf_getsym() failed: %s.", elf_errmsg(-1));}printf("%6zu:", i);printf(" %16.16jx", (uintmax_t)sym.st_value);printf(" %5ju", (uintmax_t)sym.st_size);printf(" %-7s", st_type(GELF_ST_TYPE(sym.st_info)));printf(" %-6s", st_bind(GELF_ST_BIND(sym.st_info)));printf(" %-8s", st_vis(GELF_ST_VISIBILITY(sym.st_other)));printf(" %3s", st_shndx(sym.st_shndx));// sh_info: One greater than the symbol table index of //           the last local symbol (binding STB_LOCAL).// printf("shdr->sh_info = %u\n", shdr->sh_info);// sh_link: .strtab or .dynstr (The section header index of //          the associated string table.)printf(" %s\n", get_symbol_name(pelf, symshdr->sh_link, &sym));   }
}int main(int argc, const char *argv[])
{int fd, class;Elf *pelf = NULL;Elf_Scn *scn = NULL;if (argc != 2)errx(EXIT_FAILURE, "usage: %s file-name", argv[0]);if (elf_version(EV_CURRENT) == EV_NONE)errx(EXIT_FAILURE, "ELF library initializztion ""failed: %s", elf_errmsg(-1));if ((fd = open(argv[1], O_RDONLY, 0)) < 0)errx(EXIT_FAILURE, "open \"%s\" failed", argv[1]);if (!(pelf = elf_begin(fd, ELF_C_READ, NULL)))errx(EXIT_FAILURE, "elf_begin() failed: %s", elf_errmsg(-1));if (elf_kind(pelf) != ELF_K_ELF)errx(EXIT_FAILURE, "\"%s\" is not an ELF object.", argv[1]);// get elf class ()if ((class = gelf_getclass(pelf)) == ELFCLASSNONE)errx(EXIT_FAILURE, "getclass() failed: %s.", elf_errmsg(-1));while ((scn = elf_nextscn(pelf, scn)) != NULL) {GElf_Shdr shdr;if (gelf_getshdr(scn, &shdr) != &shdr) {errx(EXIT_FAILURE, "gelf_getshdr() failed: %s.", elf_errmsg(-1));}if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) {print_syms(pelf, scn, &shdr);}} (void)elf_end(pelf);(void)close(fd);exit(EXIT_SUCCESS);
}

参考链接:

《Symbol Table》《Symbol Table Section》

《Inside ELF Symbol Tables》

《Fun with weak symbols》

《Profiler adventures: resolving symbol addresses is hard!》

《OS Backtrace With Symbol Names》

《Executable and Linkable Format 101. Part 2: Symbols》

《Linking》

ELF符号表分析(转载)相关推荐

  1. matlab 符号表,MATLAB——matlab特殊符号表【转载】

    链接来源: matlab特殊符号表 http://blog.sina.com.cn/s/blog_4a09187801014xg9.html Character Sequence Symbol Cha ...

  2. elf section类型_ELF结构(主要是符号表)

    1.1.1   整体结构 ELF对象格式用于目标文件(.o扩展名)和执行文件. 有些信息只出现在目标文件或执行文件中. ELF文件由下列部件构成. ELF header必须放在文件的开始;其他部件可以 ...

  3. 编译原理学习笔记20——符号表

    编译原理学习笔记20--符号表 20.1 符号表的组织与操作 20.2 符号表的内容 20.3 利用符号表分析名字的作用域 20.1 符号表的组织与操作 符号表 符号表的作用与组织 符号表的整理和查找 ...

  4. 【Android 逆向】ELF 文件格式 ( 程序头数据 | 节区头数据 | 动态符号表 )

    文章目录 一.程序头数据 二.节区头数据 三.动态符号表 一.程序头数据 在上一篇博客 [Android 逆向]ELF 文件格式 ( ELF 程序头入口大小 | ELF 程序头入口个数 | ELF 文 ...

  5. ELF Format 笔记(七)—— 符号表

    最是那一低头的温柔,像一朵水莲花不胜凉风的娇羞,道一声珍重,道一声珍重,那一声珍重里有蜜甜的忧愁 -- 徐志摩 ilocker:关注 Android 安全(新手) QQ: 2597294287 符号表 ...

  6. ELF 动态链接 so的动态符号表(.dynsym)

    静态链接中有一个专门的段叫符号表 -- ".symtab"(Symbol Table), 里面保存了所有关于该目标文件的符号的定义和引用. 动态链接中同样有一个段叫 动态符号表 - ...

  7. ELF格式解读-符号表

    前言 一个优先的symtab文章 我们常常调试错误说需要符号表,那么符号表是什么?符号表仅仅用来调试? 符号表本质就是一个映射表,举个例子:某行二进制汇编代码映射到源码第几行. 符号表的作用: 调试 ...

  8. 【读书笔记】【程序员的自我修养 -- 链接、装载与库(二)】进程虚拟地址空间、装载与动态链接、GOT、全局符号表、共享库的组织、DLL、C++与动态链接

    文章目录 前言 介绍 可执行文件的装载与进程 进程虚拟地址空间 装载方式 操作系统对可执行文件的装载 进程虚存空间分布 ELF文件的链接视图和执行视图 堆和栈 Linux 内核装载ELF & ...

  9. C++编译器符号表有哪些内容?

    C++编译器符号表有哪些内容? 很早就想写一篇关于符号表的学习小结,可是迟迟不能下笔.其一是因为符号表在编译器的设计中占有举足轻重的地位[我们在学习编译原理的时候更多的是注重principles,而没 ...

最新文章

  1. 1029 Median
  2. 调整命令行的列数和行数 mode con: cols=100 lines=10000
  3. 笔记本建立wifi热点!(主要针对XP)【直播】
  4. python小游戏代码大全-20行python代码的入门级小游戏的详解
  5. JavaScript高级程序设计学习笔记二(在HTML中使用JavaScript)
  6. Faster RCNN总结
  7. java.lang.NoClassDefFoundError: com/android/build/gradle/internal/ToolingRegistryProvider
  8. 简书自动上传工具出现多余空行的问题及解决方案
  9. pytorch 使用cpu_想读读PyTorch底层代码?这份内核机制简介送给你
  10. Python+OpenCV:尺度不变特征变换 (SIFT, Scale-Invariant Feature Transform)
  11. thinkphp v5.0.11漏洞_ThinkPHP 5.0.x-5.0.23、5.1.x、5.2.x 全版本远程代码执行漏洞分析
  12. 修改DevExpress中英文提示,将英文改为中文
  13. Jquery 使用技巧总结
  14. 5个衡量软件质量的标准(可自动化)
  15. yum 安装、 rpm安装、 源码编译安装
  16. MATLAB信号与系统分析(三)——连续信号与系统的复频域分析及MATLAB实现
  17. 用友U8安装...(转)
  18. access日期如何增加年数_ACCESS 时间日期操作大全
  19. linux dstat,使用Dstat来进行Linux综合性能诊断
  20. 启明云端分享|IDO-SOM3022-V1.0:可适用于物联网等多个领域

热门文章

  1. 线程的优先级、等待线程、守护线程
  2. 公众号历史文章分类汇总
  3. P5.js创意编程之自我介绍
  4. JS调试检测 及 绕过方法
  5. 备份方法scp rsync,inotifywait
  6. Java后台开发面经汇总
  7. 百家号怎么赚钱,百家号赚钱实操攻略
  8. 表格表头php,Excel表格表头怎么设置每页都有?
  9. 关系型数据库sql与非关系型数据库nosql
  10. sql server 字段 插入备注