lds ----linux下的通用链接脚本

社会主义新天地 提交于 2020-03-07 23:37:33

  ELF(Executable and Linkable Format)格式,linux平台下十分常见的可执行、可连接文件。

输出section的丢弃:
例子,.foo { *(.foo) },如果没有任何一个输入文件包含.foo section,那么连接器将不会创建.foo输出section。但是如果在这些输出section描述内包含了非输入section描述命令(如符号 赋值语句),那么连接器将总是创建该输出section。
有一个特殊的输出section,名为/DISCARD/,被该section引用的任何输入section将不会出现在输出文件内,这就是DISCARD的意思吧。如果/DISCARD/ section被它自己引用呢?想想看。
/DISCARD/ : { *(.discard) }  

SECTIONS {
   . = 0x00;                  //链接定位器在0x00处
   .text          :   { *(.text) }            //所有文件的代码段链接成一个.text的代码段
   .rodata ALIGN(4) : {*(.rodata)}
   .data ALIGN(4) : { *(.data) }         //所有文件的数据段链接成一个.text的数据段,4字节对齐
  .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
}

//说明:.bss段---链接完后,占用的内存释放,不同于.data段一直占有内存。

.bss节
这个节包含程序还未初始化的数据,也就是说,包含没有初值的那些变量。当操作系统装入这个程序时将把这些变量都置为0
使用.bss比使用.data的优势在于,.bss节在编译后不占用磁盘的空间,这样编译、连接生成的代码的尺寸会比较小。

关键字AT()--------输出section的LMA :默认情况下,LMA等于VMA,但可以通过关键字AT()指定LMA.

特殊符号名'.'表示定位计数器. 你只可以在'SECTIONS'命令中使用它.

 

输入节中的普通符号.
-----------------------------------

对于普通符号,需要一个特殊的标识, 因为在很多目标格式中, 普通符号没有一个特定的输入节. 连接器会把
普通符号处理成好像它们在一个叫做'COMMON'的节中.

你可能像使用带有其他输入节的文件名一样使用带有'COMMON'节的文件名。你可以通过这个把来自一个特定输
入文件的普通符号放入一个节中,同时把来自其它输入文件的普通符号放入另一个节中。

在大多数情况下,输入文件中的普通符号会被放到输出文件的'.bss'节中。比如:

    .bss { *(.bss) *(COMMON) }

有些目标文件格式具有多于一个的普通符号。比如,MIPS ELF目标文件格式区分标准普通符号和小普通符号。
在这种情况下,连接器会为其他类型的普通符号使用一个不同的特殊节名。 在MIPS ELF的情况中, 连接器
为标准普通符号使用'COMMON',并且为小普通符号使用'.common'。这就允许你把不同类型的普通符号映射到
内存的不同位置。

在一些老的连接脚本上,你有时会看到'[COMMON]'。这个符号现在已经过时了, 它等效于'*(COMMON)'

 

输出节LMA
..................

每一个节有一个虚地址(VMA)和一个载入地址(LMA);出现在输出节描述中的地址表达式设置VMS

连接器通常把LMA跟VMA设成相等。你可以通过使用‘AT’关键字改变这个。跟在关键字‘AT’后面的表达式
LMA指定节的载入地址。或者,通过`AT>LMA_REGION'表达式, 你可以为节的载入地址指定一个内存区域。

这个特性是为了便于建立ROM映像而设计的。比如,下面的连接脚本创建了三个输出节:一个叫做‘.text’
从地址‘0x1000’处开始,一个叫‘.mdata’,尽管它的VMA是'0x2000',它会被载入到'.text'节的后面,最
后一个叫做‘.bss’是用来放置未初始化的数据的,其地址从'0x3000'处开始。符号'_data'被定义为值
'0x2000', 它表示定位计数器的值是VMA的值,而不是LMA。

    SECTIONS
      {
      .text 0x1000 : { *(.text) _etext = . ; }
      .mdata 0x2000 :
        AT ( ADDR (.text) + SIZEOF (.text) )
        { _data = . ; *(.data); _edata = . ;  }
      .bss 0x3000 :
        { _bstart = . ;  *(.bss) *(COMMON) ; _bend = . ;}
    }

 

eg:

SECTIONS {
    . = 0x30000000;
    .text          :   { *(.text) }
    .rodata ALIGN(4) : {*(.rodata)}
    .data ALIGN(4) : { *(.data) }
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }

}
eg:

 

没有AT()指定,节的运行地址,与存储地址一致。0xB0004000 为运行地址,AT(2048)为存储地址。不一致。

eg:

SECTIONS {
  firtst    0x00000000 : { head.o init.o }
  second    0xB0004000 : AT(2048) { leds.o }
}

eg:

SECTIONS {
    . = 0x00000000;
    .init : AT(0){ head.o init.o nand.o}
    . = 0x30000000;
    .text : AT(4096) { *(.text) }
    .rodata ALIGN(4) : AT((LOADADDR(.text)+SIZEOF(.text)+3)&~(0x03)) {*(.rodata*)}
    .data ALIGN(4)   : AT((LOADADDR(.rodata)+SIZEOF(.rodata)+3)&~(0x03)) { *(.data) }
    __bss_start = .;
    .bss ALIGN(4)  : { *(.bss)  *(COMMON) }
    __bss_end = .;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!