链接 与 加载

一、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的代码

时间: 2024-11-29 07:14:44

链接 与 加载的相关文章

链接与加载过程中,几个关键的概念

http://www.cnblogs.com/qiaoconglovelife/p/5870000.html 加载(load) 将程序拷贝到存储器并运行的过程,由加载器(loader)执行. 链接分类 编译时(compile time)链接:也称为传统静态链接.静态链接: 加载时(load time)链接:在程序被加载的时候动态链接共享库: 运行时(run time)链接:在程序运行时根据需要动态链接共享库. 目标文件 可重定位目标文件:可被链接生成可执行目标文件: 可执行目标文件:可被直接拷贝

C编译器、链接器、加载器详解

摘自http://blog.csdn.net/zzxian/article/details/16820035 C编译器.链接器.加载器详解 一.概述 C语言的编译链接过程要把我们编写的一个c程序(源代码)转换成可以在硬件上运行的程序(可执行代码),需要进行编译和链接.编译就是把文本形式源代码翻译为机器语言形式的目标文件的过程.链接是把目标文件.操作系统的启动代码和用到的库文件进行组织形成最终生成可加载.可执行代码的过程. 过程图解如下: 预处理器:将.c 文件转化成 .i文件,使用的gcc命令是

AutoSharedLibrary -- 基于模板元编程技术的跨平台C++动态链接加载库

基于模板元编程技术的跨平台C++动态链接加载库.通过模板技术,使用者仅需通过简单的宏,即可使编译器在编译期自动生成加载动态链接库导出符号的代码,无任何额外的运行时开销. ASL_LIBRARY_BEGIN(TestLib) ASL_SYMBOL(Proc_test1, test1, false) ASL_SYMBOL(Proc_test2, test2, true) ASL_LIBRARY_END() TestLib theLib; try { theLib.Load("./1.so"

编译 链接 加载

本篇文章是组内分享的小结,主要介绍源代码 -> 可执行程序 -> 执行这一过程.也就是源代码是如何转化为可执行程序,然后可执行程序又是如何执行的.在用java或python时,只需要java ClsName或者python a.py就可以执行相应的程序,实际上它们都是依托于底层的虚拟机.本文主要介绍的是操作系统级别的连接.加载.执行等,而不是虚拟机语言的执行.这里只对链接.加载进行一个简介,详细内容推荐大家去看<深入理解计算机系统>和<程序员的自我修养>,第二本要比第一

移动网站性能优化:网页加载技术概览

性能一直是网站成功的关键.越来越多的研究已经证明,不管是小型电商,还是像沃尔玛那样的连锁店,即使是页面加载时间方面的细微改善,都可以带来更多的业务,更多的广告收入,更多的用户粘性和更多的客户满意度. 在过去几年,Web开发者都是基于改善硬件或者提高带宽速度来优化用户体验.但是最近几年,爆炸式的移动Web浏览器的使用打破了这个途径.低带宽,高延迟,小内存,低处理器性能的移动设备环境,迫使开发者不得不想办法通过优化前端页面的性能来满足用户的性能预期. 在强调如何解决移动端性能问题上,这篇文章总结了一

ELF文件的加载过程(load_elf_binary函数详解)--Linux进程的管理与调度(十三)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-04 Linux-4.6 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 加载和动态链接 从编译/链接和运行的角度看,应用程序和库程序的连接有两种方式. 一种是固定的.静态的连接,就是把需要用到的库函数的目标代码(二进制)代码从程序库中抽取出来,链接进应用软件的目标映像中: 另一种是动态链接,是指库函数的代码并不进入应用软件的目标映像,应用软件在编译/链接阶段并

加载页面遮挡耗时操作任务页面--第三方开源--AndroidProgressLayout

在Android的开发中,往往有这种需求,比如一个耗时的操作,联网获取网络图片.内容,数据库耗时读写等等,在此耗时操作过程中,开发者也许不希望用户再进行其他操作(其他操作可能会引起逻辑混乱),而此时需要给用户一个额外的加载页面遮挡住主逻辑代码的运行,待主页面的耗时操作完成后,自动消失这样加载过度页面,恢复出正常应该显示的页面. 举个实际的例子,如代码使用Android WebView打开一个网页链接试图加载某个网站,但网络质量不佳,需要耗时很久,那么在这个过程中,较好的用户体验做法是:给用户一个

共享库加载时重定位

原作者:Eli Bendersky http://eli.thegreenplace.net/2011/08/25/load-time-relocation-of-shared-libraries 本文的目的是解释现代操作系统怎样使得共享库加载时重定位成为可能.它关注执行在32位x86的LinuxOS.但通用的原则也适用于其它OS与CPU. 共享库有很多名字--共享库,共享对象,动态共享对象(DSO),动态链接库(DLL--假设你有Windows背景).为了统一起见.我将尽量在本文里使用"共享库

移动网站性能优化:网页加载(转)

原文链接:http://caibaojian.com/mobile-optimization.html 由于移动设备存在的环境限制,如低带宽,高延迟,小内存,低处理器性能的等,迫使开发者不得不想办法通过优化前端页面的性能来满足用户的性能预期.在强调如何解决移动端性能问题上,这篇文章总结了一些前端优化的案例,并且概括了一些加速页面的方法和策略.· 为什么性能会影响这么多 不论你的页面设计地多么有趣.漂亮.交互性好,不管是在桌面还是移动设备上,如果页面需要花2到3秒时间去渲染展示,那么用户都会很快变