《Note of System computer》 [on-going]

Questions

text段的每一条指令因操作数不同,所占内存空间也不一样,

那么pc++,怎么知道下一条指令是几个字节呢?一般是4字节?

比如:

  289 00000000004004d0 <main>:
  290   4004d0:       55                      push   %rbp
  291   4004d1:       48 89 e5                mov    %rsp,%rbp
  292   4004d4:       48 83 ec 10             sub    $0x10,%rsp
  293   4004d8:       c7 45 fc 00 00 00 00    movl   $0x0,-0x4(%rbp)
  294   4004df:       be 03 00 00 00          mov    $0x3,%esi
  295   4004e4:       bf 02 00 00 00          mov    $0x2,%edi
  296   4004e9:       e8 16 00 00 00          callq  400504 <swap>

 

Comments:

skip: no build note for this section

missing: no study for this section

Chapter Seven LINKING

链接(linking)是将各种代码和数据收集并组合起来为单一文件的过程,生成的文件可以被加载到存储器并执行。

linking可以执行于compile time,也可以执行于load time,甚至可以执行于run time

linking过程是由连接器(linker)来完成的。

 

编译系统流程

cpp(C Preprocessor)将C代码翻译成*.i;

cc(C compiler)翻译成*.s;

as(assemble)生成relocatable object file(可重定向目标文件)*.o;

ld(linker)最终链接为executable object file

 

 

输入段 vs 输出段

输 入段和输出段是相对于要生成最终的elf或binary时的Link过程说的,Link过程的输入大都是由源代码编绎生成的目标文件.o,那么这些.o文 件中包含的段相对link过程来说就是输入段,而Link的输出一般是可执行文件elf或库等,这些输出文件中也包含有段,这些输出文件中的段就叫做输出段。

 

7.2 Static linking

ld是静态连接器。主要完成两件事情:

1. sybmol resolution:将每个符号引用和对应定义建立联系

2. relocation:修改符号引用地址,使指向其符号在储存器存放的位置

7.3 Object file

目标文件的三种形式:

1. relocatable object file,由as生成,可以被linking为executable object file

2. executable object file

3. shared object file, like dynamic lib fie

在Unix(linux)版本中,以上三种目标文件的格式为Unix Executable and Linkable Format(ELF)

7.4 Relocatable object file

ELF relocatable object file格式如下:

ELF header(16 bytes)+ each section ..... + section header table

eg.

-------------------------------------------------------------

chuan.jiang:~/temp$ readelf -a main.o
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          312 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           64 (bytes)
  Number of section headers:         12
  Section header string table index: 9

其中ELF header主要包含系统字长和字节序,目标文件类型,节头部表的offset和section number等

主要的section介绍,其余的参见【P451 7.4】

.text 机器代码

.rodata 只读数据

.data 已初始化全局C变量

.bss 未初始化全局C变量(主要为了节省elf空间)

.symtab 符号表,存放定义和引用的函数和全局变量信息,不包含局部变量

 

7.5 Symble table

符号表中的符号有三类:

1. 本模块定义的可以被其他模块引用的全局符号

2. 其他模块定义,由本模块引用的全局符号

3. 只被本模块定义和引用的本地符号

注意:不包含局部变量,他们只在stack中创建和使用

Example of Symbol table '.symtab'

For example, dump symbol table of main.o by using readelf

-------------------------------------------------------------

chuan.jiang:~/temp$ cat main.c
#include <string.h>
#include <stdio.h>

extern int swap(int a, int b);

int buf[2] = {1, 2};
int main()
{
        int *ret = NULL;

        *ret = swap(2, 3);
        return *ret;
}

-------------------------------------------------------------

chuan.jiang:~/temp$ readelf main.o -aV

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       000000000000002d  0000000000000000  AX       0     0     4
  [ 2] .rela.text        RELA             0000000000000000  00000558
       0000000000000018  0000000000000018          10     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000070
       0000000000000008  0000000000000000  WA       0     0     4
  [ 4] .bss              NOBITS           0000000000000000  00000078
       0000000000000000  0000000000000000  WA       0     0     4
  [ 5] .comment          PROGBITS         0000000000000000  00000078
       0000000000000026  0000000000000001  MS       0     0     1
  [ 6] .note.GNU-stack   PROGBITS         0000000000000000  0000009e
       0000000000000000  0000000000000000           0     0     1
  [ 7] .eh_frame         PROGBITS         0000000000000000  000000a0
       0000000000000038  0000000000000000   A       0     0     8
  [ 8] .rela.eh_frame    RELA             0000000000000000  00000570
       0000000000000018  0000000000000018          10     7     8
  [ 9] .shstrtab         STRTAB           0000000000000000  000000d8
       0000000000000059  0000000000000000           0     0     1
  [10] .symtab           SYMTAB           0000000000000000  00000438
       0000000000000108  0000000000000018          11     8     8
  [11] .strtab           STRTAB           0000000000000000  00000540
       0000000000000016  0000000000000000           0     0     1

........

Symbol table '.symtab' contains 11 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS main.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    3
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    4
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    6
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    7
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    5
     8: 0000000000000000     8 OBJECT  GLOBAL DEFAULT    3 buf
     9: 0000000000000000    45 FUNC    GLOBAL DEFAULT    1 main
    10: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND swap

其中,Ndx表示本符号对应的section在section header table中的index,其中有三种特殊伪节(pseudo section), ABS代表不被重定义的符号;UNDEF代表未定义的符号,即在本模块引用,在其他模块定义;COMMON表示未被分配位置的未初始化数据目标。

可见,符号main在section 1中,即 .text section;buf在 .data section

其中value为section offset(对于executable file为absolute runtime address),size表示object的大小,Bind表示local or global

 

7.6 Symbol resolution

7.6.1 解析多重定义的全局变量

规则1:不允许有多个strong symbol

规则2:存在一个strong symbol和多个weak symbol,选择strong

规则3:存在多个weak,任意选择一个weak

strong symbol:函数和已经初始化的全局变量

weak symbol:未初始化的全局变量

 

举例1:

int f()

{

static int x = 0;

return x;

}

int f()

{

static int x = 1;

return x;

}

NOTE:以上是合法的,并且符号表main.o 和 swap.o 中x的name 有区分,如下:

     5: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    4 x.2216

     5: 0000000000000000     4 OBJECT  LOCAL  DEFAULT    5 x.1595


举例2:

file1.c

int x = 1;

int y = 0;

....

file2.c

double x;

x = 1.0;

以上编译OK,但是file2.c会关联到file1.c的int类型x,导致1.0赋值后会对y存储区覆盖

 

7.6.2 Static library

静态库为一种存档(archived file)文件,是将一组组合起来的relocatable object file的set,后缀名为*.a。

由ar工具生成,作为ld的输入,ld仅仅将依赖的*.o链接入ELF中。

ld使用*.a来解析符号时,*.a一般放在命令行的末尾,否则无法找到*.a中相应的符号,如下:

gcc -static main.c ./libvector.a

另外,各个*.a之间也会存在互相依赖,一种方法是把互相依赖的*.a重复交替写在gcc命令参数中,一种方法是将这些*.a合并成一个*.a

 

7.7 Relocation

大体上说,重定位的步骤是按照section的顺序,依次合并各个section

,并依次将各个section中引用的地址改写为运行时地址

重定位分两步骤:

1. 重定位section和symbol definition

2. 重定位symbol reference

NOTE:linker会对每个符号引用记录一个relocation entry,以便在linking时修改这个符号的引用,代码和数据的重定位条目放在.rel.text and .rel.data。

注意,不同寻址方式对应的地址有所差异

 

7.7.2 symbol relocation

没有完全理解,书中是x86_32的汇编码,不同机器的汇编码有所差异。

skip left

7.8 Executable Object File

ELF文件格式大致如下:

[ELF header + segment header table + .init + .text + .rodata ]+ [.data + .bss] + [.symtab ....... section header table]

以上三部分分别为:只读代码段,读写数据段,不加载到存储器的符号表和调试信息

其中segment header table为连续文件节到运行存储器的映射关系;

.init包含_init函数,负责程序的初始化

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值