当前位置:   article > 正文

解读链接脚本ld和案例分享_ld文件详解

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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

该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)
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

该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】多平台都有更新和发布,大家可以一键三连,关注+星标,不错过精彩内容~
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/606012
推荐阅读
相关标签
  

闽ICP备14008679号