`

第3章 目标文件(ELF格式)

 
阅读更多

源文件SimpleSection.c为:

int printf(const char* format, ...);

int global_init_var=84;
int global_uninit_var;

void func1(int i){
	printf("%d\n", i);
}

int main(void){
	static int static_var=85;
	static int static_var2;

	int a=1;
	int b;
	
	func1(static_var+static_var2+a+b);
	
	return a;
}

 

经过: $ gcc -c SimpleSection.c    预处理 -> 编译(产生汇编代码) -> 汇编(产生obj文件),尚未链接。

此时得到SimpleSection.o,下面均是对SimpleSection.o的观察分析:

 

一、查看ELF文件整体

       按照ELF格式文件从前到后的顺序查看(ELF文件头,program headers, sections, section headers):

 

[hadoop@sam1 test]$ readelf -h SimpleSection.o  ==> 查看ELF格式的目标文件 "File Header"

ELF Header:

  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 

  Class:                             ELF32

  Data:                              2's complement, little endian

  Version:                           1 (current)

  OS/ABI:                            UNIX - System V

  ABI Version:                       0

  Type:                              REL (Relocatable file)

  Machine:                           Intel 80386

  Version:                           0x1

  Entry point address:               0x0

  Start of program headers:          0 (bytes into file)

  Start of section headers:          272 (bytes into file)

  Flags:                             0x0

  Size of this header:               52 (bytes)

  Size of program headers:           0 (bytes)

  Number of program headers:         0

  Size of section headers:           40 (bytes)

  Number of section headers:         11

  Section header string table index: 8

 

[hadoop@sam1 test]$ readelf -S SimpleSection.o   ==> 查看ELF格式的目标文件 "Section Header Table"

There are 11 section headers, starting at offset 0x110:

 

Section Headers:

  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al

  [ 0]                   NULL            00000000 000000 000000 00      0   0  0

  [ 1] .text             PROGBITS        00000000 000034 000050 00  AX  0   0  4

  [ 2] .rel.text         REL             00000000 000420 000028 08      9   1  4

==>.rel.text:对于必须要重定位的代码段和数据段,都会有一个相应的重定位表——因为链接器处理目标文件时,须要对目标文件中“对绝对地址引用的位置”进行重定位。

  [ 3] .data             PROGBITS        00000000 000084 000008 00  WA  0   0  4

  [ 4] .bss              NOBITS          00000000 00008c 000004 00  WA  0   0  4

  [ 5] .rodata           PROGBITS        00000000 00008c 000004 00   A  0   0  1

  [ 6] .comment          PROGBITS        00000000 000090 00002d 01  MS  0   0  1

  [ 7] .note.GNU-stack   PROGBITS        00000000 0000bd 000000 00      0   0  1

  [ 8] .shstrtab         STRTAB          00000000 0000bd 000051 00      0   0  1

==> .shstrtab段表字符串表:保存段表中用到的字符串,如“段名”

  [ 9] .symtab           SYMTAB          00000000 0002c8 0000f0 10     10  10  4

==> .symtab符号表:目标文件中的“函数”和“变量”统称为符号(Symbol)

  [10] .strtab           STRTAB          00000000 0003b8 000066 00      0   0  1

==> .strtab字符串表:保存普通的字符串

Key to Flags:

  W (write), A (alloc), X (execute), M (merge), S (strings)

  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)

  O (extra OS processing required) o (OS specific), p (processor specific)

 

还可以反汇编SimpleSection.o中的.text段或者所有段:

objdump  -d  SImpleSection.o  ==>  --disassemble: Display the contents of executable sections (i.e. [.text])

objdump  -D  SImpleSection.o  ==>  --disassemble-all: Display the contents of all sections

 

二、查看ELF文件细节

 

[hadoop@sam1 test]$ readelf -s SimpleSection.o ==> 查看ELF格式目标文件的“符号表”(符号表也是目标文件中的一个段,即.symtab这个段) 

Symbol table '.symtab' contains 15 entries:

   Num:    Value  Size Type    Bind   Vis      Ndx Name

     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 

     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS SimpleSection.c

     2: 00000000     0 SECTION LOCAL  DEFAULT    1 

     3: 00000000     0 SECTION LOCAL  DEFAULT    3 

     4: 00000000     0 SECTION LOCAL  DEFAULT    4 

     5: 00000000     0 SECTION LOCAL  DEFAULT    5 

     6: 00000004     4 OBJECT  LOCAL  DEFAULT    3 static_var.1222

     7: 00000000     4 OBJECT  LOCAL  DEFAULT    4 static_var2.1223

     8: 00000000     0 SECTION LOCAL  DEFAULT    7 

     9: 00000000     0 SECTION LOCAL  DEFAULT    6 

    10: 00000000     4 OBJECT  GLOBAL DEFAULT    3 global_init_var

    11: 00000004     4 OBJECT  GLOBAL DEFAULT  COM global_uninit_var

    12: 00000000    27 FUNC    GLOBAL DEFAULT    1 func1

    13: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf

    14: 0000001b    53 FUNC    GLOBAL DEFAULT    1 main

 

 理解Ndx字段
    static_var.1222为3,表示在第3个section[.data]中;
    static_var2.1223为4,表示在第4个section[.bss]中;
    global_init_var为3,表示在第3个section中[.data];
    global_uninit_var为COM,表示这个全局变量未显式初始化,下面有详解;
    func1为1,表示在第1个section[.text]中;
    printf为UND,表示这个函数在外部模块定义,下面有详解
    main为1,表示在第1个section[.text]中;


Ndx为COM的含义
    gcc treats uninitialised globals which are not explicitly declared extern as "common" symbols (hence "COM").
    Multiple definitions of the same common symbol (across multiple object files) are merged together by the linker when creating the final executable, so that they all refer to the same storage. One of the object files may initialise it to a particular value (in which case it will end up in the data section); if no object files initialise it, is will end up in the BSS; if more than one object initialises it, you'll get a linker error.
    In summary, if you have, say, two definitions of int a:

    int a; in one object and int a; in another object is OK: both refer to the same a, initialised to 0
    int a; in one object and int a = 42; in another object is OK: both refer to the same a, initialised to 42
    int a = 23; in one object and int a= 42; in another object will give a link error.

    Do note that the use of multiple definitions of the same symbol across two objects is not technically allowed by standard C; but it is supported by many compilers, including gcc, as an extension. (It's listed under "Common extensions" - no pun intended - in the C99 spec.)

 

Ndx为UND的含义

#readelf -a SimpleSection.o| grep UND

         你会看到很多熟悉的库函数(i.e. printf),但是现在还是没有确定它的地址,用的UND,当你运行这个程序的时候,loader会把这个应用装到内存,同时确定这些动态连接的函数的地址,loader会到这个应用程序头的一个字段找到这个应用程序依赖的共享库。例如:

         在另一个文件a.c中显式定义int global_uninit_var=7; 并编译gcc -c a.c产生a.o

         然后将gcc  SimpleSection.o a.o -o b

# readelf -d b(显示Dynamic section)既可以看到类似

Dynamic section at offset 0x4c4 contains 20 entries:

         Tag                     Type                                      Name/Value

0x00000001              (NEEDED)                            Shared library: [libc.so.6]

...

      可知b依赖 libc.so.6,但是loader会到哪个路径去找这个文件呢?它会到环境变量LD_LIBRARY_PATH 去找这个文件,找到之后,把共享库装入内存(如果是第一次使用这个库),把这些库函数在内存的地址反填到应用程序中,这样这个应用就可以运行了。

 

分享到:
评论

相关推荐

    ELF文件格式详细分析

    它由UNIX系统实验室开发并发布,旨在作为应用程序二进制接口(Application Binary Interface, ABI)的一部分,以标准化的方式支持软件开发过程中涉及的各种目标文件。 ELF格式被设计成高度可移植的,并且能够跨不同的...

    ELF 文件格式分析.pdf

    ELF (Executable and Linkable Format) 是一种广泛应用于 Unix 类操作系统中的目标文件格式。它被设计用于存储可执行文件、目标代码、共享库和其他类型的程序数据。ELF 格式具有高度可移植性,并且支持多种处理器...

    第7题-ELF文件注入1

    3. **修改ELF文件**: - **增加页面大小**:可能需要根据操作系统的页面大小(通常是4KB)来调整ELF文件。 - **修正ELF头部(e_header)**:更新e_shoff字段,以容纳新增的代码。 - **调整程序头部表**:第一个程序...

    ELF格式可执行代码的嵌入

    3. 节区(Sections):节区包含了目标文件的所有数据,如代码、数据、符号表、重定位表、调试信息等。每个节区都有特定的属性和类型,比如".text"存放代码,".data"存放已初始化的数据,".bss"存放未初始化的数据,...

    Linux下的ELF文件格式简介.doc

    - `e_ident`:16字节的标识符,确认文件为ELF格式,并指明文件的字节序、版本等信息。 - `e_type`:标识文件类型,如可执行文件(ET_EXEC)或共享目标文件(ET_DYN)。 - `e_machine`:指示文件适用的处理器架构,如...

    Tasking_elf_hex_hex_elf_bat_

    批处理文件的工作原理是读取并执行其中的一系列命令,这些命令通常是操作系统内建的命令或者第三方工具。在"elf2hex.bat"中,可能会包含像`xxd`或`objcopy`这样的工具,这些工具通常作为GCC交叉编译工具链的一部分,...

    ReadELF, ELF格式分析程序源码

    1. **头部**(ELF Header):这是ELF文件的第一个部分,它提供了文件的整体信息,包括ELF文件的版本、目标体系结构、入口点地址、程序头表和节区头表的偏移量等。 2. **程序头表**(Program Headers):这个表包含...

    elf文件格式(中文版).pdf

    1. 目标文件(Object Files) - **可重定位文件**:包含了代码和数据,用于与其他object文件合并生成可执行或共享文件。 - **可执行文件**:存储执行程序,指示操作系统如何创建进程映像。 - **共享对象文件**:...

    ELF-64.pdf

    ELF(Executable and Linkable Format)是一种在Unix系统上广泛使用的文件格式,它用于可执行文件、目标代码、共享库和核心转储等多种类型。ELF文件格式提供了一种在不同计算机平台之间共享和迁移二进制代码的方式,...

    ELF format.pdf 中文 高清带标签

    ELF格式最初由UNIX系统实验室开发,并作为应用程序二进制接口(Application Binary Interface, ABI)的一部分发布。随后,TIS委员会采纳了正在发展中的ELF标准作为一种便携式的文件格式标准,特别是在32位Intel架构...

    Android So ELF的文件格式分析(1).pdf

    ELF格式是一种广泛应用于Unix/Linux操作系统上的二进制文件格式标准,它不仅支持可执行文件,还支持共享库和目标文件等。对于Android开发人员而言,了解So文件内部结构有助于更好地进行性能优化、调试及安全性分析等...

    Understanding_ELF.pdf

    ELF格式由TIS(Tool Interface Standards–工具接口标准)委员会制定,该委员会是一个微型计算机工业的联合组织,其目的是为32位操作系统下的开发工具提供标准化的软件接口,包括目标文件格式、可执行文件格式以及...

    linux的elf手册

    ELF (Executable and Linkable Format) 是一种标准的文件格式,主要用于表示可执行文件、目标文件、共享库以及核心转储文件。它广泛应用于Unix-like操作系统中,如Linux。本文档主要介绍了Linux环境下ELF文件格式的...

    ucos.zip_arm-elf_elf

    3. **编译源码**:使用arm-elf-gcc编译源代码,生成相应的.o目标文件。通常会包括CPU相关的初始化代码、UCOSII的核心函数、应用程序代码等。 4. **链接生成可执行文件**:使用arm-elf-ld将所有.o文件链接成一个单一...

    Linux 可执行文件格式详细文档

    ELF格式不仅适用于可执行文件,还适用于目标文件、共享库等多种类型的文件。本文档旨在深入探讨ELF文件格式的具体细节,并为开发者提供一份详尽的技术参考。 #### 二、对象文件 ##### 1. 引言 对象文件是程序编译...

    c语言目标文件在无可奈何花落去否极泰来需要

    目标文件一般遵循某种标准格式,例如S-record格式或者ELF格式等。本文讨论的是S-record格式下的目标文件,其结构主要包括文件头、数据区和文件尾三个部分。下面以一个具体的例子来详细介绍各个部分的含义及其在添加...

    xtensa-esp32-elf-gcc8_4_0-esp-2021r2-linux-armel.tar.gz

    "elf"代表Executable and Linkable Format,这是一种在多种操作系统和处理器架构上广泛使用的可执行文件和共享对象的文件格式。"2021r2"可能表示这是该工具链的2021年第二个发布版本。 标签为空,说明没有提供特定...

    Linux病毒原型的工作过程和关键环节.pdf

    ELFInfector 是一种专门针对Linux下可执行文件(ELF格式)的感染工具,用于制造第一个带有病毒代码的文件。在了解ELFInfector之前,我们先简要回顾一下ELF文件格式的一些基本概念: - **ELF文件结构**:ELF文件主要...

    xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch3-linux-armel.tar.gz

    此工具链基于GCC 8.4.0版本,并且是Espressif Systems在2021年第二季度发布的第二个修订版(R2)的第三个补丁版本。交叉编译工具链是为在一种操作系统上构建为另一种操作系统设计的软件工具,这里是在Linux环境下...

    xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch5-linux-armel.tar.gz

    描述中的"xtensa-esp32s3-elf-gcc8_4_0-esp-2021r2-patch5-linux-armel.tar"可能是指未压缩的tar文件,与标题中的gz压缩文件是同一内容的不同格式。在Linux下,通常使用tar命令来处理这种文件,解压缩后可以得到一...

Global site tag (gtag.js) - Google Analytics