arm链接脚本

Posted linux-37ge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了arm链接脚本相关的知识,希望对你有一定的参考价值。

一. 为什么需要链接脚本

  1.1. 从源码到可执行程序(主要有三个步骤:预编译、编译、链接)

    1.1.1. 预编译

      a. 预编译器执行。譬如C中的宏定义就是由预编译器处理,注释等也是由预编译器处理的。

    1.1.2. 编译

      a. 由编译器来执行。把源码.c .S编程机器码.o文件。所以可以看到每个源码.s .c文件编译后都有相对应的.o文件

    1.1.3. 链接

      a. 由链接器来执行。把.o文件中的各函数(段)按照一定规则(链接脚本来指定)累积在一起,

形成可执行文件。

  1.2. 链接脚本究竟要做什么?

    1.2.1. 链接脚本其实是个规则文件,

      a. 他是程序员用来指挥链接器工作的。链接器会参考链接脚本,并且使用其中规定的规则来处理.o文件中那些段,将其链接成一个可执行程序。

    1.2.2. 常见链接脚本命令

      1.2.2.1 ENTRY(SYMBOL)

        a. 将SYMBOL的值设置成入口地址。一般设置为_start

      1.2.2.2. OUTPUT(FILENAME)

        a. 定义输出文件的名字。可以用它来指定默认的输出文件名称。当然我们一般都用手动-o进行指定,如果我们没有进行手动指定的话,输出文件名称就以这个FILENAME为输出文件名。

      1.2.2.3. OUTPUT_FORMAT(default, big, little)

        a. 定义3种输出文件的格式。若有命令行选项-EB(大端),则使用第二个输出格式,有命令行指定-EL(小端),则使用第三个格式。否则使用默认的default输出格式。

      1.2.2.4. OUT_ARCH(arch)

        a. 设置输出文件的体系架构

      1.2.2.5. SECTIONS命令

        a. 最重要的,最基本的,也是最主要的命令,它告诉链接器如何把输入文件的各个section输出到目标文件中的各个section中去

        b. ‘SECTIONS‘是一个功能很强大的命令. 这里这们会描述一个很简单的使用。让我们假设你的程序只有代码段,初始化过的数据段, 和未初始化过的数据段. 这些会存在于‘.text‘,‘.data‘和‘.bss‘段

技术分享图片
SECTIONS命令的格式如下:

  SECTIONS 

        {

                一条或者多条section-command

                或者符号赋值语句

        }

        section-command的常见格式如下:

        secname [address] : [AT(LMA)] 

        { contents } 


PS :首先中括号的选项是可选的,可以不写
View Code

    1.2.2. 简单示例:

技术分享图片
ENTRY(_start);

OUTPUT_FORMAT("elf32-littlearm""elf32-bigarm""elf32-littlearm");

OUTPUT_ARCH(arm);

SECTIONS
{
        . 0x50008000;
        . = ALIGN(4);
        .text : {
                *(.text);
        }
        . = ALIGN(4);

        .data : {

                *(.data);
        }
        . = ALIGN(4);

        .bss : {
                *(.bss);
        }
}
View Code

      a. 你使用关键字‘SECTIONS‘写了这个SECTIONS命令, 后面跟有一串放在花括号中的符号赋值和输出节描述的内容.

      b. ‘.‘ 点号在链接脚本中代表当前位置。
      c. ‘=‘ 等号代表赋值

      d. 第二行定义一个输出段,‘.text‘. 冒号是语法需要,现在可以被忽略. 段名后面的花括号中,你列出所有应当被放入到这个输出段中的输入段的名字. ‘*‘是一个通配符,匹配任何文件名.表达式‘*(.text)‘意思是所有的输
入文件中的‘.text‘输入段.
      
e. address表示当连接器执行此程序的时候应该把这个段加载到内存的哪个地址,此地址大多数情况下和CPU执行此处时地址相同,但当进行重定位是就可以实现链接地址和CPU执行地址不同(当然代码必须是位置无关编码)

      f. . = ALIGN(4);表示后面地址按四字节对齐

二. 程序段的概念

  2.1. 通用段

    2.1.1. 这种是编译器链接器内部定好的,先天性的名字

    2.1.2. 代码段:(.text)

      a. 又叫文本段,代码段其实就是函数编译后生成的东西

    2.1.3. 数据段:(.data)

      a. 数据段就是C语言中有显式初始化为非0的全局变量,以及非0静态局部变量

    2.1.3. bss段:(.bss)

      a. 又叫ZI(zero initial)段,就是零初始化段,对应C语言中初始化为0或未初始化的全局变量以及初始化为0或未初始化静态局部变量。

  2.2. 自定义段

    a. 段名由程序员自己定义,段的属性和特征也由程序员自己定义

三. uboot链接文件

技术分享图片
/*
 * (C) Copyright 2002
 * Gary Jennejohn, DENX Software Engineering, <[email protected]>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
    . = 0x00000000;

    . = ALIGN(4);
    .text      :
    {
      cpu/s5pc11x/start.o    (.text)
      cpu/s5pc11x/s5pc110/cpu_init.o    (.text)
      board/samsung/x210/lowlevel_init.o    (.text)
          cpu/s5pc11x/onenand_cp.o      (.text)                 
          cpu/s5pc11x/nand_cp.o (.text)                     
          cpu/s5pc11x/movi.o (.text) 
          common/secure_boot.o (.text) 
      common/ace_sha1.o (.text)
      cpu/s5pc11x/pmic.o (.text)
      *(.text)
    }

    . = ALIGN(4);
    .rodata : { *(.rodata) }

    . = ALIGN(4);
    .data : { *(.data) }

    . = ALIGN(4);
    .got : { *(.got) }

    __u_boot_cmd_start = .;
    .u_boot_cmd : { *(.u_boot_cmd) }
    __u_boot_cmd_end = .;

    . = ALIGN(4);
    .mmudata : { *(.mmudata) }

    . = ALIGN(4);
    __bss_start = .;
    .bss : { *(.bss) }
    _end = .;
}
View Code

 

 

参考《朱老师.1.2ARM裸机课件》

参考文献《https://blog.csdn.net/huangbo_embed/article/details/22419349





以上是关于arm链接脚本的主要内容,如果未能解决你的问题,请参考以下文章

链接脚本的简介以及简单编写

什么时候使用 .ARM.exidx

嵌入式开发(S5PV210)——u-boot的链接脚本分析

4.链接器脚本

了解 ARM Cortex-M 微控制器的链接描述文件

分享前端开发常用代码片段