编译原理-链接实例分析

news2024/11/28 12:55:10

gcc-arm-none-eabi 工具链功能

1.arm-none-eabi-gcc :c语言编译器,可以将.c文件编译为.o的执行文件

2.arm-none-eabi-g++ :c++编译器,可以将.cpp文件编译成.o的执行文件

3.arm-none-eabi-ld : 链接器,链接所有的.o文件生成可执行文件

4.arm-none-eabi-objcopy :将链接器生成的文件转换为bin/hex等可烧写的格式

5.arm-none-eabi-gdb :调试器,将gdb连接到硬件产生的网络端口就可以实现硬件和代码的调试。

https://sourceware.org/binutils/docs/binutils/objcopy.html

objcopy can be used to generate a raw binary file by using an output target of ‘binary’ (e.g., use -O binary). When objcopy generates a raw binary file, it will essentially produce a memory dump of the contents of the input object file. All symbols and relocation information will be discarded. The memory dump will start at the load address of the lowest section copied into the output file.

https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html

Every section has a virtual address (VMA) and a load address (LMA);

The load address is specified by the AT or AT> keywords. Specifying a load address is optional.

If neither AT nor AT> is specified for an allocatable section, the linker will use the following heuristic to determine the load address:

  • If the section has a specific VMA address, then this is used as the LMA address as well.

  • If the section is not allocatable then its LMA is set to its VMA.

  • Otherwise if a memory region can be found that is compatible with the current section, and this region contains at least one section, then the LMA is set so the difference between the VMA and LMA is the same as the difference between the VMA and LMA of the last section in the located region.

  • If no memory regions have been declared then a default region that covers the entire address space is used in the previous step.

  • If no suitable region could be found, or there was no previous section then the LMA is set equal to the VMA.

This feature is designed to make it easy to build a ROM image. For example, the following linker script creates three output sections: one called ‘.text’, which starts at 0x1000, one called ‘.mdata’, which is loaded at the end of the ‘.text’ section even though its VMA is 0x2000, and one called ‘.bss’ to hold uninitialized data at address 0x3000. The symbol _data is defined with the value 0x2000, which shows that the location counter holds the VMA value, not the LMA value.

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

The run-time initialization code for use with a program generated with this linker script would include something like the following, to copy the initialized data from the ROM image to its runtime address. Notice how this code takes advantage of the symbols defined by the linker script.

extern char _etext, _data, _edata, _bstart, _bend;char *src = &_etext;char *dst = &_data;/* ROM has data at end of text; copy it. */while (dst < &_edata) *dst++ = *src++;/* Zero bss. */for (dst = &_bstart; dst< &_bend; dst++) *dst = 0;

案例:

编码

main.c

int i = 10 ;
int f ;

int main(void){
        
        int k = 0 ; int m = 10; 
        
        k = m+i+f;
        
        return k ;
        
}

编译

$System/Tools/GNUArmToolchain/windows/bin/arm-none-eabi-gcc.exe -c main.c

生成main.o ,查看main.o的sections状态:

$System/Tools/GNUArmToolchain/windows/bin/arm-none-eabi-readelf.exe -S main.o

重点关注text.data.bass段的大小。

There are 10 section headers, starting at offset 0x260:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000058 00  AX  0   0  4  [ 2] .rel.text         REL             00000000 0001fc 000018 08   I  7   1  4  [ 3] .data             PROGBITS        00000000 00008c 000004 00  WA  0   0  4  [ 4] .bss              NOBITS          00000000 000090 000004 00  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 000090 00004a 01  MS  0   0  1
  [ 6] .ARM.attributes   ARM_ATTRIBUTES  00000000 0000da 00002a 00      0   0  1
  [ 7] .symtab           SYMTAB          00000000 000104 0000e0 10      8  11  4
  [ 8] .strtab           STRTAB          00000000 0001e4 000017 00      0   0  1
  [ 9] .shstrtab         STRTAB          00000000 000214 000049 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  y (purecode), p (processor specific)

链接生成elf

写一个链接脚本linktest.ld

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(main)
MEMORY
{
    IRAM1_CODE (r) : ORIGIN = 0x410000,  LENGTH = 0xEFFFF        
    TCM   (rw) : ORIGIN = 0x40,   LENGTH = 0x1ffc0
}

SECTIONS
{
    /*vector start_1 VMA在TCM,LMA在IRAM1_CODE*/
    .start_1 : {
        *(.text*)
    } > TCM AT >IRAM1_CODE

    .start_2 : ALIGN(32) {
        __bss_start__ = . ;
        *(.bss .bss.*)
        __bss_end__ = . ;
    } > IRAM1_CODE 
        
        .start_3 : ALIGN(32) {
        *(.data .data.*)
    } > IRAM1_CODE 
        _exit = . ;
}

$System/Tools/GNUArmToolchain/windows/bin/arm-none-eabi-gcc.exe -o main.elf main.o -T ../linktest.ld

链接生成elf文件。

$System/Tools/GNUArmToolchain/windows/bin/arm-none-eabi-readelf.exe -S main.elf

There are 19 section headers, starting at offset 0x21c5c:

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .start_1          PROGBITS        00000040 010040 000688 00  AX  0   0  4
  [ 2] .init             PROGBITS        000006c8 0106c8 000018 00  AX  0   0  4
  [ 3] .fini             PROGBITS        000006e0 0106e0 000018 00  AX  0   0  4
  [ 4] .rodata           PROGBITS        000006f8 0106f8 000048 00   A  0   0  4
  [ 5] .eh_frame         PROGBITS        00000740 010740 000004 00   A  0   0  4
  [ 6] .ARM.exidx        ARM_EXIDX       00000744 010744 000008 00  AL  1   0  4
  [ 7] .rodata._glo[...] PROGBITS        0000074c 01074c 000004 00   A  0   0  4
  [ 8] .start_2          NOBITS          00410720 020720 000041 00  WA  0   0 32  
  [ 9] .start_3          PROGBITS        00410780 020780 00043c 00  WA  0   0 32
  [10] .init_array       INIT_ARRAY      00410bbc 020bbc 000004 04  WA  0   0  4
  [11] .fini_array       FINI_ARRAY      00410bc0 020bc0 000004 04  WA  0   0  4
  [12] .init_array.00000 INIT_ARRAY      00410bc4 020bc4 000004 04  WA  0   0  4
  [13] .ARM.attributes   ARM_ATTRIBUTES  00000000 020bc8 000026 00      0   0  1
  [14] .comment          PROGBITS        00000000 020bee 000049 01  MS  0   0  1
  [15] .debug_frame      PROGBITS        00000000 020c38 000258 00      0   0  4
  [16] .symtab           SYMTAB          00000000 020e90 000900 10     17 103  4
  [17] .strtab           STRTAB          00000000 021790 000401 00      0   0  1
  [18] .shstrtab         STRTAB          00000000 021b91 0000ca 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  y (purecode), p (processor specific)

objcopy生成bin

$System/Tools/GNUArmToolchain/windows/bin/arm-none-eabi-objcopy.exe -O binary main.elf main.bin

objcopy can be used to generate a raw binary file by using an output target of ‘binary’ (e.g., use -O binary). When objcopy generates a raw binary file, it will essentially produce a memory dump of the contents of the input object file. All symbols and relocation information will be discarded. The memory dump will start at the load address of the lowest section copied into the output file.

elf文件包含各个sections的信息,地址信息,调试信息等。

bin文件时剔除了elf文件中的各种信息,只保留二进制汇编指令,按照LMA的顺序进行排序存储。

比如start_1 ,start_2 ,start_3的LMA,都指向IRAM1_CODE 中,按照顺序排列后生成bin。

如果

.start_1 : { *(.text*) } > TCM

去除AT >IRAM1_CODE,则.start_1的LMA,则指向了TCM,0x40。那么生成的bin文件将会很大,因为空洞的产生。

分析LMA VMA地址关系

总结:

1,BIN文件时按照LMA地址顺序存储,使用objcopy工具。

2,ELF文件按照VMA地址顺序存储,相当于内存映像,多用于调试。

3,If neither AT nor AT> is specified for an allocatable section,the linker will likely use VMA to determine the load address(LMA)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/166512.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CDH6.3生产环境中禁用Kerberos

在集群启用Kerberos后&#xff0c;会对现有环境的部分代码做改造&#xff0c;有些人觉得使用起来不方便&#xff0c;想取消Kerberos。本篇文章主要介绍如何禁用CDH集群的Kerberos及禁用后对各组件服务的测试。修改了网上相关文档的一些缺陷&#xff0c;在生产环境中实际使用过通…

GIT ---- GitHub配置SSH Key的完整步骤

1. 配置 SSH Key 由于提交代码每次输入用户名和密码&#xff0c;很繁琐&#xff0c;所以直接配置 SSH Key&#xff0c;直接自动验证&#xff0c;减少提交代码的操作步骤。 2. 查看配置命令 git config --list 查看当前Git环境所有配置&#xff0c;还可以配置一些命令别名之类…

这一年,熬过许多夜,也有些许收获 | 2022年度总结

弹指一挥间&#xff0c;时间如白驹过隙。光阴似箭&#xff0c;日月如梭&#xff0c;时间如闪电&#xff0c;转瞬即逝。回望来时路&#xff0c;不觉潸然泪下… 一说到年终总结&#xff0c;好像都离不开这样煽情的开场白。但不可否认的是&#xff0c;时间确实过得很快&#xff0…

学习记录661@项目管理之项目立项管理

什么是项目立项管理 项目立项管理关注的重点在于是否要启动一个项目&#xff0c;并为其提供相应的预算支持具体来说&#xff0c;项目立项管理包括以下 5 个典型环节&#xff0c;分别是 项目建议项目可行性分析项目审批项目招投标项目合同谈判与签订 需要说明的是&#xff0c…

两大技巧教你轻松应对IB数学

同学想要在IB数学科取得好成绩&#xff0c;可以从两个方面来着手。 1.复习技巧第一个是复习技巧。这方面&#xff0c;同学要清楚知道自己读的课程&#xff0c;它的教学大纲&#xff08;Syllabus&#xff09;要求是什么&#xff0c;还有它背后想要同学达到什么样的目标。 IB数学…

浅谈DNS解析

DNS介绍IP是计算机里的地址簿&#xff0c;但是IP是由一串数字组成&#xff0c;我们的大脑很难记住&#xff0c;所以就需要定义一个符合人类记忆规则的地址&#xff0c;而这就是我们现在常用的网站域名&#xff0c;域名就是我们和计算机作为地址沟通的桥梁&#xff0c; 虽然我们…

物流企业如何确保网络安全?

随着网上购物的发展&#xff0c;人们的日常生活越来越离不开物流企业的服务了。而且在一些企业的供应链中&#xff0c;物流运输也是非常重要的一环节。与此同时&#xff0c;伴随着供应链数字化&#xff0c;透明度、速度和成本优势增加了公司对技术的兴趣。物流企业也更喜欢使用…

开放式基金净值实时数据 API 数据接口

开放式基金净值实时数据 API 数据接口 实时净值&#xff0c;全量实时数据&#xff0c;包含净值与增长率。 1. 产品功能 支持所有开放式基金净值数据查询&#xff1b;实时数据&#xff0c;包含实时净值与增长率信息&#xff0c;16:00 ~ 23:00 更新当日数据&#xff1b;包含前一…

C语言模拟实现库函数strstr

传入两个地址&#xff0c;第一个是母串首地址&#xff0c;第二个是子串首地址&#xff0c;判断是否是子串&#xff0c;如果不是&#xff0c;返回NULL&#xff0c;如果是&#xff0c;返回母串中第一次出现子串的首地址。 代码如下&#xff1a; #define _CRT_SECURE_NO_WARNING…

Android | Activity

Android Activity Activity 概念 Activity 是一种包含用户界面、主要用于与用户进行交互的Android应用组件。一个应用程序可以包含零个或多个 Activity 。 Activity 生命周期 Activity 类中定义了7个回调方法&#xff0c;覆盖了 Activity 生命周期的每一个环节。 onCreate(…

力扣sql基础篇(九)

力扣sql基础篇(九) 1 每位经理的下属员工数量 1.1 题目内容 1.1.1 基本题目信息 1.1.2 示例输入输出 1.2 示例sql语句 # 如果是得出来每组都是一个值,就可以在SELECT子句中写非分组字段 # e1.reports_to IS NOT NULL是为了确保是员工,通过员工去找经理 SELECT e2.employee_…

第二章.线性回归以及非线性回归—标准方程法

第二章.线性回归以及非线性回归 2.8 标准方程法 1.公式 1).代价函数&#xff1a; 2).累加平方和用矩阵表示&#xff1a; 2.对(&#x1d466; − &#x1d44b;&#x1d464;)&#x1d447;(&#x1d466; − &#x1d44b;&#x1d464;)求导的两种布局方式&#xff1a; 1).分子…

【初阶数据结构】——写了将近 5 万字,终于把 二叉树 初阶的内容讲清楚了

文章目录前言1. 树的概念及结构1.1 树的概念1.2 树与非树1.3 树的相关概念1.4 树的表示1.5 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09;2. 二叉树概念及结构2.1 概念2.2 现实中的二叉树2.3 特殊的二叉树2.3.1 满二叉树2.3.1 完全二叉树2.4 二叉树的性质…

2022年Tesla技术分享

Autopilot&#xff1a;允许车辆保持车道&#xff0c;跟随前车&#xff0c;弯道减速&#xff0c;等等&#xff0c;处理从停车场到城市街道&#xff0c;再到高速公路的所有驾驶过程。 一、硬件&#xff1a; 8个120W像素的摄像头&#xff0c;每秒36帧&#xff0c;360度空间&#…

牛客竞赛每日俩题 - 动态规划4

目录 经典dp1&#xff08;最长公共序列&#xff09; 经典dp2&#xff08;最长上升子序列 &#xff09; 经典dp&#xff08;最长公共序列&#xff09; 最长公共子序列__牛客网 解析&#xff1a; 有两个字符串T和S&#xff0c;S的长度为n T的长度为m 状态&#xff1a;f[i][j…

C# LINQ查询

一、什么是LINQ LINQ是Language-Integrated Query的缩写&#xff0c;它可以视为一组语言和框架特性的集合。LINQ可以对本地对象集合或远程数据源进行结构化的类型安全的查询操作。LINQ支持查询任何实现了IEnumerable<T>接口的集合类型&#xff0c;无论是数组、列表还是X…

oracle12c数据库安装(静默安装

写在前面 本教程是在Linux下安装oracle12c数据库&#xff0c;由于在有些情况下并没有图形化安装界面&#xff0c;所以这里介绍在linux下通用的安装方式&#xff1a;静默安装&#xff0c;通俗的说就是在linux的命令行窗口安装。 关闭防火墙 systemctl disable firewalld sy…

LeetCode 300. 最长递增子序列

&#x1f308;&#x1f308;&#x1f604;&#x1f604; 欢迎来到茶色岛独家岛屿&#xff0c;本期将为大家揭晓LeetCode 300. 最长递增子序列&#xff0c;做好准备了么&#xff0c;那么开始吧。 &#x1f332;&#x1f332;&#x1f434;&#x1f434; 一、题目名称 LeetCo…

Spring之AOP简单讲解

目录 一&#xff1a;基本概念 二&#xff1a;案例&#xff1a;模拟AOP的基础代码 三&#xff1a;AOP相关概念 四&#xff1a;AOP入门案例思路分析 五&#xff1a;AOP工作流程 六&#xff1a;AOP核心概念 七&#xff1a;AOP切入点表达式 八&#xff1a;xml方式AOP快速入门…

动态内存分配/管理

目录 1、为什么要有动态内存分配 2、动态内存函数介绍 1、malloc 2、free 3、calloc ​编辑 4、realloc 3、动态内存常见的错误 4、动态内存开辟相关好题 5、c/c程序内存开辟示意图 int a, int arr[10] 是固定地向内存申请连续的一块空间&#xff0c;但不能变长或变…