解读链接脚本ld和案例分享

链接脚本ld

ld(Linker)是一个负责将目标文件和库文件链接成可执行文件或共享库的程序。在编译过程中,编译器将源代码编译成目标文件,然后ld将这些目标文件链接成可执行文件或共享库。

ld的主要作用是解决目标文件之间的符号引用关系,将所有目标文件中的符号引用和符号定义进行匹配,最终生成可执行文件或共享库。

在ld的工作过程中,会执行以下几个步骤:

  1. 读取输入文件:ld首先会读取所有需要链接的目标文件和库文件,这些文件包括目标文件、静态库文件和动态库文件。

  2. 符号解析:ld会对每个目标文件中的符号进行解析,将符号引用和符号定义进行匹配。

  3. 符号重定位:ld将所有符号引用和符号定义进行匹配后,会对所有未解析的符号进行重定位,将其指向正确的地址。

  4. 生成输出文件:最后,ld将所有目标文件链接成一个可执行文件或共享库,并生成输出文件。

在解读ld文件的过程中,需要了解目标文件和库文件的格式,以及符号表、重定位表等概念。同时,需要了解ld的工作流程,理解ld如何将所有目标文件链接成一个可执行文件或共享库。

ld文件的几部分

ld文件的语法是基于脚本语言的,主要包括以下几个部分:

  1. 指令(Directives):指令是ld文件的基本语法单元,用于控制链接器的行为。指令以“.”开头,例如“.text”、“.data”等。

  2. 命令(Commands):命令是指令的具体实现,用于指示链接器如何处理目标文件和库文件。命令包括输入命令、输出命令、符号命令、重定位命令等。

  3. 表达式(Expressions):表达式用于计算地址和大小等数值,可以包括常量、符号、运算符等。

  4. 段(Sections):段是目标文件中的一段内存区域,包括代码段、数据段、BSS段等。段可以包含多个节(Section),每个节包含一组相同类型的数据。

  5. 符号(Symbols):符号是目标文件中的标识符,包括函数名、变量名、常量等。符号可以被定义和引用,链接器会根据符号的定义和引用关系进行符号解析和重定位。

  6. 段地址(Address):段地址是指目标文件中的段在内存中的起始地址。

  7. 镜像(Image):镜像是指可执行文件或共享库在内存中的映像,包括代码段、数据段等。

下面是一个示例ld文件,用于将多个目标文件和库文件链接成一个可执行文件:

ENTRY(_start)

SECTIONS {
    .text  : { *(.text) }
    .data  : { *(.data) }
    .bss   : { *(.bss) }
}

INPUT(-lc -lm)
OUTPUT(main)

该ld文件包含了一个入口点(ENTRY)、三个节(SECTIONS)、一个输入命令(INPUT)和一个输出命令(OUTPUT)。在每个节中,使用通配符“*”匹配所有同名节中的内容。输入命令用于指定需要链接的库文件,输出命令用于指定生成的可执行文件名。

NUC980连接脚本

以下是一个NUC980的ld文件示例:

ENTRY(_start)

MEMORY {
    rom (rx)  : ORIGIN = 0x00000000, LENGTH = 0x100000
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x100000
}

SECTIONS {
    .text : {
        *(.text)
    } > rom

    .rodata : {
        *(.rodata)
    } > rom

    .data : {
        *(.data)
    } > ram AT > rom

    .bss : {
        *(.bss)
    } > ram

    .stack : {
        . = ALIGN(4);
        _estack = .;
        . = . + 0x1000;
        . = ALIGN(4);
    } > ram

    /DISCARD/ : {
        *(.note.*)
        *(.comment)
    }
}

该ld文件定义了两个内存区域:rom和ram。rom区域用于存放只读数据和代码,ram区域用于存放可读写数据。其中,rom区域的起始地址为0x00000000,长度为0x100000,ram区域的起始地址为0x20000000,长度为0x100000。

该ld文件将目标文件中的代码和只读数据放置在rom区域,可读写数据放置在ram区域。其中,代码段和只读数据段使用了“.text”和“.rodata”节,可读写数据段使用了“.data”节,BSS段使用了“.bss”节。在链接时,代码段和只读数据段被放置在rom区域,可读写数据段被放置在ram区域,BSS段被放置在ram区域。

该ld文件还定义了一个栈区(.stack),用于存放程序的运行时栈。栈区的起始地址为ram区域的末尾,大小为0x1000字节。

最后,该ld文件使用“/DISCARD/”命令将目标文件中的“.note.*”和“.comment”节丢弃,这些节通常包含调试信息,不需要放置在最终的可执行文件中。

【最后一个bug】多平台都有更新和发布,大家可以一键三连,关注+星标,不错过精彩内容~
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值