• 链接 与 加载


    一、GUN处理目标文件的工具

    AR 创建静态库,插入、删除、列出和提取成员;
    SRING 列出目标文件中的字符串;
    SIRIP 从目标文件中删除符号表信息;
    NM 列出目标文件符号表中定义的符号;
    READELF 显示一个目标文件的完整结构 SIZE 列出目标文件中节的名字和大小; OBJDUMP 所有二进制工具之母,可显示一个目标文件中所有的信息。
    LDD 列出一个可执行文件在运行时所需要的动态库

    首先对一个c文件进行编译生成.o目标文件

    然后可以通过nm 和readelf来查看目标文件的符号表

    nm------->

    00000000 t $d
    00000014 t $d
    00000000 t $d
    00000010 t $d
             U heap_init
    00000000 T init_all
    00000000 T main
             U printf
    00000000 t $t
    00000000 t $t
             U uart_init

    其中

             B --- 全局非初始化数据段(BBS段)的符号,其值表示该符号在bss段中的偏移,如g1

               b --- 全局static的符号,如g3

               r --- const型只读的变量(readonly)

               N --- debug用的符号

               T --- 位于代码区的符号,比如本文件里的函数main foo

               t  --- 位于代码区的符号,一般是static函数

               U --- 位于本文件外的调用函数或变量符号,比如系统的printf()函数

     

    readelf -s xxx.o

    Symbol table '.symtab' contains 31 entries:
       Num:    Value  Size Type    Bind   Vis      Ndx Name
         0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
         1: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
         2: 00000000     0 SECTION LOCAL  DEFAULT    1 
         3: 00000000     0 SECTION LOCAL  DEFAULT    2 
         4: 00000000     0 SECTION LOCAL  DEFAULT    3 
         5: 00000000     0 SECTION LOCAL  DEFAULT    4 
         6: 00000000     0 SECTION LOCAL  DEFAULT    5 
         7: 00000000     0 SECTION LOCAL  DEFAULT    7 
         8: 00000000     0 SECTION LOCAL  DEFAULT    9 
         9: 00000000     0 NOTYPE  LOCAL  DEFAULT    9 $d
        10: 00000000     0 NOTYPE  LOCAL  DEFAULT    9 $t
        11: 00000014     0 NOTYPE  LOCAL  DEFAULT    9 $d
        12: 00000000     0 SECTION LOCAL  DEFAULT   11 
        13: 00000000     0 NOTYPE  LOCAL  DEFAULT   11 $d
        14: 00000000     0 NOTYPE  LOCAL  DEFAULT   11 $t
        15: 00000010     0 NOTYPE  LOCAL  DEFAULT   11 $d
        16: 00000000     0 SECTION LOCAL  DEFAULT   13 
        17: 00000000     0 SECTION LOCAL  DEFAULT   14 
        18: 00000000     0 SECTION LOCAL  DEFAULT   16 
        19: 00000000     0 SECTION LOCAL  DEFAULT   18 
        20: 00000000     0 SECTION LOCAL  DEFAULT   20 
        21: 00000000     0 SECTION LOCAL  DEFAULT   22 
        22: 00000000     0 SECTION LOCAL  DEFAULT   24 
        23: 00000000     0 SECTION LOCAL  DEFAULT   28 
        24: 00000000     0 SECTION LOCAL  DEFAULT   25 
        25: 00000000     0 SECTION LOCAL  DEFAULT   26 
        26: 00000000    24 FUNC    GLOBAL DEFAULT    9 init_all
        27: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND heap_init
        28: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND uart_init
        29: 00000000    20 FUNC    GLOBAL DEFAULT   11 main
        30: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND printf

     

     

    二、链接

    通过ld进行链接

    链接可以把包括 目标文件,静态库,动态库,编译链接生成完全链接的可执行目标文件

    链接器主要完成以下操作

    1)符号解析:将符号引用和符号定义联系起来

    2)重定位:从0地址开始生成代码数据节

    目标文件.o (可重定位目标文件): 

    静态库.a (通过ar命令生成) :合并静态库和目标文件使未定义符号能引用到唯一一个定义生成可执行文件

    动态库.so(gcc -shared -fPIC -o xxx.so x1.c x2.c): 在链接时加载时进行动态链接(-fpic生成位置无关代码)

      将动态库的文本数据重定位到某个存储器段

      在链接时会在elf的text段生成PLT过程链接表  在data段开始的地方生成GOT全局偏移表

    三、项目的地址规划

    1)elf目标文件包含的各个节段

    ①text段:代码段(codesegment/textsegment)

      通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定。

    ②rodata段:只读数据

    存放C中的字符串和#define定义的常量

    ③data段:数据段(datasegment

    通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。

    ④bss段: BSS段(bsssegment)  

    通常是指用来存放程序中未初始化的全局变量的一块内存区域。不占任何实际的磁盘空间。

    ⑤其他

    symtab段:符号表

    rel.text段

    rel.data段

    debug段

    line段

    strtab段

    ⑥stack栈:

    是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。

    ⑦heap堆:

    堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)

    写一个链接脚本

    ENTRY( __reset);
    
    MEMORY
    {
        dram : ORIGIN = 0x00080000, LENGTH = 0x10000
    }
    
    SECTIONS
    {
        .text : { 
            _start_text_ = .;
            /*start.o(.text*)*/
            *(.text*)
            *(.rodata*)
            . = ALIGN(4);
            _end_text = .;
        } > dram
    
        .data : { 
            _start_data = .;
            *(.data*)
            . = ALIGN(4);
            _end_data = .;
        } > dram
    
        .bss : { 
            _start_bss_ = .;
            *(.bss) *(COMMON)
            . = ALIGN(4);
            _end_bss_ = .;
        } > dram
    
    }

    规划了各个节段从0x00080000开始,大小0x10000

    各个段顺序是text < rodata < data < bss,4字节对齐

    通过     ld ldflags -T link.ld *.o *.a -o x.elf

    四、启动代码

    .S文件为汇编代码,一般为系统刚跑起来的时候运行的代码

    包括了stage1 stage2的代码

    http://blog.chinaunix.net/uid-22891435-id-380150.html

    1、异常向量处理

    包括中断等

    2、初始化硬件,设置时钟分频

    3、设置堆栈

    4、跳转到main

  • 相关阅读:
    洛谷 P1578 奶牛浴场 题解
    LOJ167 康托展开 题解
    三校联训 【NOIP模拟】寻找
    洛谷 P1809 过河问题 题解
    有关多边形面积的总结
    LOJ 103 字串查找 题解
    洛谷 P2384 最短路 题解
    POJ 2492 A Bug's Life 题解
    LOJ 10214 计算器 题解
    洛谷 P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题解
  • 原文地址:https://www.cnblogs.com/chencesc/p/6589277.html
Copyright © 2020-2023  润新知