LD脚本中的LONG关键字

本文探讨了使用LD脚本时,如何通过调整脚本内容使生成的BIN文件存放ModuleEntry的绝对地址而非相对地址。具体地,通过使用0x0+ModuleEntry的方式实现了这一目标。

 最近遇到一个问题,比较奇怪,有这样一个LD脚本:

SECTIONS

{

        .text 0x80800000 :

        {

               LONG(ModuleEntry);   /* ModuleEntry是程序入口,LONG会将ModuleEntry的地址放在BIN文件的最开始处 */

               ...

         }

         ...

}


写成这样以后,用objdump生成的bin文件开头处放的是ModuleEntry相对于0x80800000的偏移地址,而修改一下

 ...

LONG(0x0 + ModuleEntry);

...

这样一来,就会放绝对地址。有点想不通...


网上查了也找不到答案,先记下 来...

 

编绎器: mipsel-linux-gcc

<think>我们正在处理用户关于&ldquo;计数器ld的名称或相关概念”的查询。根据用户提供的引用内容,特别是引用[1]和引用[4],我们可以推断用户可能是在链接器脚本(linkerscript)的上下文中询问&ldquo;计数器ld”的概念。在引用[1]中,我们看到链接器脚本中使用了类似计数器的构造来管理全局构造函数和析构函数的表。具体来说,它使用了一个列表(__CTOR_LIST__和__DTOR_LIST__),并计算了条目数量。这里的关键是使用了位置计数器(.)和LONG指令来构建这些表。在引用[4]中,明确提到了位置计数器(.)的概念,它在链接器脚本中用于设置输出节的地址。位置计数器在链接器脚本中是一个核心概念,它就像一个计数器一样,随着每个节被放置而递增。因此,用户可能是在询问链接器脚本中的位置计数器(locationcounter),它通常用点号(.)表示,在链接器脚本中用于跟踪当前的输出地址。此外,在引用[2]中提到了PHDRS命令,引用[3]是关于计数器在PLC编程中的使用(CTU,CTD等),引用[5]是关于ELF格式和ld链接器的,但这些似乎与&ldquo;计数器ld”的直接关联不大。所以,我们将重点放在链接器脚本中的位置计数器上。回答结构:1.解释位置计数器(.)在链接器脚本中的定义和作用。2.举例说明如何使用位置计数器(如引用[1]和[4]中的用法)。3.如果有其他相关概念,可以简要提及。注意:用户使用了&ldquo;计数器ld”这个术语,我们应将其理解为链接器(ld中的计数器概念,即位置计数器。另外,根据用户提供的引用[1],我们看到在构建构造函数和析构函数表时,使用了位置计数器来计算条目数量,这也是一个计数器的应用场景。因此,我们可以这样回答:在GNU链接器(ld)的链接器脚本中,&ldquo;位置计数器”(用符号&ldquo;.”表示)是一个核心概念,它用于跟踪当前输出地址。在链接过程中,位置计数器随着每个输出节的放置而自动递增,类似于一个计数器。具体来说:-位置计数器(.)代表当前输出地址。-可以通过赋值来设置位置计数器的值(如引用[4]中:`.=0x10000;`)。-在定义输出节时,如果没有指定地址,则使用位置计数器的当前值作为起始地址。-位置计数器也可以用于计算大小或条目数,如引用[1]中计算构造函数表的条目数量。例如,在引用[1]的链接器脚本片段中:```__CTOR_LIST__=.;LONG((__CTOR_END__-__CTOR_LIST__)/4-2)*(.ctors)LONG(0)__CTOR_END__=.;```这里,位置计数器用于设置__CTOR_LIST__的地址,然后通过计算当前位置与结束位置之间的差值(除以4,因为LONG是4字节)并减去2(因为包含了开头和结尾的两个LONG条目)来得到构造函数的数量。另一个例子是引用[4]中的:```SECTIONS{.=0x10000;.text:{*(.text)}.=0x8000000;.data:{*(.data)}.bss:{*(.bss)}}```这里,位置计数器被显式设置两次,从而将.text节放在0x10000,而.data和.bss节则从0x8000000开始。因此,用户所询问的&ldquo;计数器ld”很可能是指链接器脚本中的位置计数器(.)。另外,在编程中,计数器还有其他含义(如引用[3]中的PLC计数器),但根据引用内容,用户更可能是在链接器脚本的上下文中提问。最后,生成相关问题。注意:引用[1]和[4]是我们回答的主要依据,所以我们在回答中引用它们。</think>### 计数器 `ld` 的名称与概念解析 在链接器脚本(Linker Script)和系统编程中,**计数器 `ld`** 通常指代 **位置计数器(Location Counter)**,用符号 `.` 表示。这是 GNU 链接器(`ld`)的核心概念之一,用于动态管理内存地址分配。以下是详细解析: --- #### 1. **位置计数器(`.`)的定义** - **核心作用**: 位置计数器是一个**隐式变量**,在链接器脚本中通过 `.` 符号表示。它记录当前输出段的地址位置,并随着段内容的添加自动递增地址值[^4]。 - **工作方式**: 当链接器处理输入段(如 `.text`、`.data`)时,位置计数器 `.` 动态跟踪当前内存地址。例如: ```lds SECTIONS { . = 0x10000; /* 将计数器初始化为地址 0x10000 */ .text : { *(.text) } /* .text 段起始于 0x10000 */ . = 0x8000000; /* 跳转计数器到新地址 */ .data : { *(.data) } /* .data 段起始于 0x8000000 */ } ``` 此脚本将 `.text` 段分配到 `0x10000`,`.data` 段分配到 `0x8000000`[^4]。 --- #### 2. **关键应用场景** - **动态地址分配**: 位置计数器允许灵活控制输出段的物理地址,无需硬编码固定地址。例如在嵌入式系统中为不同内存区域(ROM/RAM)分配代码和数据[^4][^5]。 - **长度计算**: 通过对比计数器变化值,可计算段长度或条目数量。例如构造全局函数表时: ```lds __CTOR_LIST__ = .; LONG((__CTOR_END__ - __CTOR_LIST__) / 4 - 2) /* 计算条目数 */ *(.ctors) /* 存储构造函数地址 */ LONG(0); /* 结束标记 */ __CTOR_END__ = .; ``` 这里 `__CTOR_END__ - __CTOR_LIST__` 利用计数器的差值计算表长度[^1]。 --- #### 3. **与编程计数器的区别** 需区分 **链接器位置计数器** 和 **程序逻辑计数器**: | **类型** | 符号 | 作用域 | 用途 | 示例来源 | |------------------|-----------|----------------|--------------------------|---------------| | 链接器位置计数器 | `.` | 链接器脚本 | 内存地址分配 | [^1][^4][^5] | | 程序逻辑计数器 | `CTU/CTD` | PLC/SCL 代码 | 工业控制计数逻辑 | [^3] | 例如 PLC 中的 `CTU`(加计数器)属于应用程序逻辑,与链接器无关[^3]。 --- #### 4. **技术关联** - **ELF 文件格式**: 位置计数器的输出直接影响 ELF 文件中段的布局(如 `.text`、`.ctors`),决定可执行文件的内存映射[^5]。 - **高级命令**: 在 `PHDRS` 命令中,位置计数器可与关键字 `AT`、`FLAGS` 结合,精确控制程序头(Program Header)的属性[^2]。 --- ### 总结 计数器 `ld` 的核心概念是 **位置计数器 `.`**,它是 GNU 链接器脚本中的动态地址指针,用于管理输出段的内存分配和长度计算[^1][^4][^5]。与工业控制系统中的逻辑计数器(如 `CTU`)不同,它属于系统级工具链范畴,直接影响可执行文件的物理布局。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值