本文由Jacky原创,来自http://blog.chinaunix.net/u1/58780/showart.php?id=462971

对于.lds文件,它定义了整个程序编译之后的连接过程,决定了一个可执行程序的各个段的存储位置。虽然现在我还没怎么用它,但感觉还是挺重要的,有必要了解一下。

先看一下GNU官方网站上对.lds文件形式的完整描述:

SECTIONS {
...
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
  { contents } >region :phdr =fill
...
}


secname和contents是必须的,其他的都是可选的。下面挑几个常用的看看:

1、secname:段名

2、contents:决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)

3、start:本段连接(运行)的地址,如果没有使用AT(ldadr),本段存储的地址也是start。GNU网站上说start可以用任意一种描述地址的符号来描述。

4、AT(ldadr):定义本段存储(加载)的地址。

看一个简单的例子:(摘自《2410完全开发》)

/* nand.lds */
SECTIONS { 
firtst 0x00000000 : { head.o init.o } 
second 0x30000000 : AT(4096) { main.o } 
}

以上,head.o放在0x00000000地址开始处,init.o放在head.o后面,他们的运行地址也是0x00000000,即连接和存储地址相同(没有AT指定);main.o放在4096(0x1000,是AT指定的,存储地址)开始处,但是它的运行地址在0x30000000,运行之前需要从0x1000(加载处)复制到0x30000000(运行处),此过程也就用到了读取Nand flash。

这就是存储地址和连接(运行)地址的不同,称为加载时域和运行时域,可以在.lds连接脚本文件中分别指定。

编写好的.lds文件,在用arm-linux-ld连接命令时带-Tfilename来调用执行,如
arm-linux-ld –Tnand.lds x.o y.o –o xy.o。也用-Ttext参数直接指定连接地址,如
arm-linux-ld –Ttext 0x30000000 x.o y.o –o xy.o。

既然程序有了两种地址,就涉及到一些跳转指令的区别,这里正好写下来,以后万一忘记了也可查看,以前不少东西没记下来现在忘得差不多了。。。

ARM汇编中,常有两种跳转方法:b跳转指令、ldr指令向PC赋值。

我自己经过归纳如下:

(1)       b step1 :b跳转指令是相对跳转,依赖当前PC的值,偏移量是通过该指令本身的bit[23:0]算出来的,这使得使用b指令的程序不依赖于要跳到的代码的位置,只看指令本身。

(2)       ldr pc, =step1 :该指令是从内存中的某个位置(step1)读出数据并赋给PC,同样依赖当前PC的值,但是偏移量是那个位置(step1)的连接地址(运行时的地址),所以可以用它实现从Flash到RAM的程序跳转。

(3)       此外,有必要回味一下adr伪指令,U-boot中那段relocate代码就是通过adr实现当前程序是在RAM中还是flash中。仍然用我当时的注释:

relocate: /* 把U-Boot重新定位到RAM */
    adr r0, _start /* r0是代码的当前位置 */ 
/* adr伪指令,汇编器自动通过当前PC的值算出 如果执行到_start时PC的值,放到r0中:
当此段在flash中执行时r0 = _start = 0;当此段在RAM中执行时_start = _TEXT_BASE(在board/smdk2410/config.mk中指定的值为0x33F80000,即u-boot在把代码拷贝到RAM中去执行的代码段的开始) */
    ldr r1, _TEXT_BASE /* 测试判断是从Flash启动,还是RAM */ 
/* 此句执行的结果r1始终是0x33FF80000,因为此值是又编译器指定的(ads中设置,或-D设置编译器参数) */
    cmp r0, r1 /* 比较r0和r1,调试的时候不要执行重定位 */

下面,结合u-boot.lds看看一个正式的连接脚本文件。这个文件的基本功能还能看明白,虽然上面分析了好多,但其中那些GNU风格的符号还是着实让我感到迷惑。。。

OUTPUT_FORMAT("elf32­littlearm", "elf32­littlearm", "elf32­littlearm")
  ;指定输出可执行文件是elf格式,32位ARM指令,小端
OUTPUT_ARCH(arm)
  ;指定输出可执行文件的平台为ARM
ENTRY(_start)
  ;指定输出可执行文件的起始代码段为_start.
SECTIONS
{
        . = 0x00000000 ; 从0x0位置开始
        . = ALIGN(4) ; 代码以4字节对齐
        .text : ;指定代码段
        {
          cpu/arm920t/start.o (.text) ; 代码的第一个代码部分
          *(.text) ;其它代码部分
        }
        . = ALIGN(4) 
        .rodata : { *(.rodata) } ;指定只读数据段
        . = ALIGN(4);
        .data : { *(.data) } ;指定读/写数据段
        . = ALIGN(4);
        .got : { *(.got) } ;指定got段, got段式是uboot自定义的一个段, 非标准段
        __u_boot_cmd_start = . ;把__u_boot_cmd_start赋值为当前位置, 即起始位置
        .u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在该段.
        __u_boot_cmd_end = .;把__u_boot_cmd_end赋值为当前位置,即结束位置
        . = ALIGN(4);
        __bss_start = .; 把__bss_start赋值为当前位置,即bss段的开始位置
        .bss : { *(.bss) }; 指定bss段
        _end = .; 把_end赋值为当前位置,即bss段的结束位置
}

ARM 链接配置.lds文件学习<转>的更多相关文章

  1. U-boot.lds文件分析

    OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") ...

  2. iOS日常学习 - 如何配置.gitignore文件

    文章为转载学习,原文地址 为什么要配置.gitigore 在我们使用git的过程当中,不是任何文件都需要commit到本地或者远程仓库的,比如一些三方库文件. 那么作为一个git新手,很多人不知道如何 ...

  3. Django学习(6)配置静态文件

      本文将详细讲述如何在Django中配置静态文件,如图片(images),JavaScript,CSS等.   我们将要实现的网页如下: 当按下按钮"Change Text"时, ...

  4. 各种数据库maven的pom文件编写与ibernate链接配置

    各种数据库Hibernate链接配置 Derby db driver maven dependency <dependency>         <groupId>org.ap ...

  5. vue-cli脚手架中webpack配置基础文件详解

    一.前言 原文:https://segmentfault.com/a/1190000014804826 vue-cli是构建vue单页应用的脚手架,输入一串指定的命令行从而自动生成vue.js+wep ...

  6. u-boot.lds文件简介

    可执行文件由许多链接在一起的对象文件组成.对象文件有许多节,如文本.数据.init 数据.bss等.这些对象文件都是由一个称为 链接器脚本(*lds)的文件链接并装入的.这个链接器脚本的功能是将输入对 ...

  7. Configure文件学习

    Linux安装软件有一种方式就是通过源码安装,源码通常是一个压缩包,打开压缩包,经常会看到一个叫configure的文件,而不见makefile文件.通常我们在自己的电脑写应用的时候都是通过makef ...

  8. Python 进行 SSH 操作,实现本地与服务器的链接,进行文件的上传和下载

    Python 进行 SSH 操作,实现本地与服务器的链接,进行文件的上传和下载 2018年5月26日 19:03 阅读 375 评论 7 我本地和服务器的连接一直使用的是 Xshell 5,而在与服务 ...

  9. Hibernate入门3.配置映射文件深入

    Hibernate入门3.配置映射文件深入 2013.11.27 前言: 之前的两节是在Java项目中如何使用hibernate,并且通过一个简单地项目实践,期间有很多的错误,一般都是因为配置包的问题 ...

随机推荐

  1. C# lambda 实现 Ascii 排序

    var dir = new Dictionary<string, string>();            dir.Add("channelId", "1& ...

  2. Shell系列(37)- while和until循环

    while循环 只要条件判断式成立则进行循环,并执行循环程序:一旦循环条件不成立,则终止循环 格式 while [ 条件判断式 ] do 程序 done 例子 需求:计算工具,1+2+--100的和 ...

  3. webpack工具学习 构建简单vue项目(不依赖vue-cli) webpack4.0

    目的用webpack构建简单前端项目 1.npm init   (npm init -y)  形成package.json 2.npm install --save-dev webpack  形成 n ...

  4. vue 主次页面区分

    1.路由设定,增加meta参数 { path: '/', name: 'Home', component: Home, meta: { index: 0, showFooter: true //由这个 ...

  5. [转载]SELinux安全系统基础

    链接:http://www.cnblogs.com/xiaoluo501395377/archive/2013/05/26/3100444.html 本篇随笔将记录一下学习SELinux的一些心得与体 ...

  6. python二级 第9套

    1. prInt.默认输出空格 2. 我的这种想法也行不通啊 format() 一次只能有一个未知量 2. 分割的结果就是列表 3. 对比"大学"    上一套的split('&q ...

  7. 判断javaScript变量是Ojbect类型还是Array类型

      JavaScript是弱类型的语言,所以对变量的类型并没有强制控制类型.所以声明的变量可能会成为其他类型的变量, 所以在使用中经常会去判断变量的实际类型. 对于一般的变量我们会使用typeof来判 ...

  8. GDOI2021划水记

    Day0 上午有意志行,一大早就醒了,然后走了五个小时脚痛.中午洗澡,宿舍轮流看巨人最终话然后聊了一个小时? 下午老师带着我和全爷先开溜,宿舍好像很破旧还还没得充电,领了牌牌和斐爷去吃饭. 然后六点多 ...

  9. Springboot --- Bug集

    一. 启动springboot报错:找不到或无法加载主类 解决:直接选中项目,在ecplise选中"project",点击clean 清理项目再运行 问题解决. 二.报错:Fail ...

  10. 好未来数据中台 Node.js BFF实践(一):基础篇

    好未来数据中台 Node.js BFF实践系列文章列表: 基础篇 实战篇(TODO) 进阶篇(TODO) 好未来数据中台的Node.js中间层从7月份开始讨论可行性,截止到9月已经支持了4个平台,其中 ...