(2) arm-linux-readelf 解读 可执行程序需要的库文件
程序无法运行排错方法 :
-- 运行平台不对 : ARM 平台 和 x86 平台之间的程序不能互相运行;
-- CPU 大小端不对 : 大端格式的程序不能运行在小端 CPU 上;
-- 库不对 : 使用 arm-linux-readelf -d hello-arm 查看程序运行需要的库, '0x00000001 (NEEDED) Shared library: [libc.so.6]', 表示需要有libc.so.6 库;
[root@localhost 02_gcc_demo]# arm-linux-readelf -d hello-arm Dynamic section at offset 0x460 contains 24 entries: Tag Type Name/Value 0x00000001 (NEEDED) Shared library: [libc.so.6] 0x0000000c (INIT) 0x8274 0x0000000d (FINI) 0x8428 0x00000019 (INIT_ARRAY) 0x10454 0x0000001b (INIT_ARRAYSZ) 4 (bytes) 0x0000001a (FINI_ARRAY) 0x10458 0x0000001c (FINI_ARRAYSZ) 4 (bytes) 0x00000004 (HASH) 0x8168 0x00000005 (STRTAB) 0x81e0 0x00000006 (SYMTAB) 0x8190 0x0000000a (STRSZ) 65 (bytes) 0x0000000b (SYMENT) 16 (bytes) 0x00000015 (DEBUG) 0x0 0x00000003 (PLTGOT) 0x10548 0x00000002 (PLTRELSZ) 32 (bytes) 0x00000014 (PLTREL) REL 0x00000017 (JMPREL) 0x8254 0x00000011 (REL) 0x824c 0x00000012 (RELSZ) 8 (bytes) 0x00000013 (RELENT) 8 (bytes) 0x6ffffffe (VERNEED) 0x822c 0x6fffffff (VERNEEDNUM) 1 0x6ffffff0 (VERSYM) 0x8222 0x00000000 (NULL) 0x0 [root@localhost 02_gcc_demo]#
4. 反汇编器(arm-linux-objdump)
(1) 反汇编
反汇编示例 : arm-linux-objdump -D -S hello-arm, 太多, 省略后面几百行;
[root@localhost 02_gcc_demo]# arm-linux-objdump -D -S hello-arm hello-arm: file format elf32-littlearm Disassembly of section .interp: 00008134 <.interp>: 8134: 62696c2f rsbvs r6, r9, #12032 ; 0x2f00 8138: 2d646c2f stclcs 12, cr6, [r4, #-188]! 813c: 756e696c strbvc r6, [lr, #-2412]! 8140: 6f732e78 svcvs 0x00732e78 8144: Address 0x00008144 is out of bounds. Disassembly of section .note.ABI-tag:... ...
(2) 编译附加调试信息
带调试信息的反编译 :
-- 交叉编译带调试信息 : arm-linux-gcc -g main.c 命令, 进行交叉编译, 结果 a.out;
-- 反编译 : arm-linux-objdump -S -D a.out 命令, 反编译结果 每行 C 代码都对应 汇编代码;
... ... #includeint main(int argc, char** argv) { 837c: e92d4800 push {fp, lr} 8380: e28db004 add fp, sp, #4 ; 0x4 8384: e24dd008 sub sp, sp, #8 ; 0x8 8388: e50b0008 str r0, [fp, #-8] 838c: e50b100c str r1, [fp, #-12] printf('Hello World!n'); 8390: e59f0014 ldr r0, [pc, #20] ; 83ac 8394: ebffffc8 bl 82bc <_init+0x48> return 0; 8398: e3a03000 mov r3, #0 ; 0x0 } ... ...
5. 文件格式转换器(arm-linux-objcopy)
文件格式转换 :
-- 转换原因 : elf 格式文件不能再 arm 处理器执行;
-- 转换命令 : 进入 led 目录, 继续上面的 led 编译, 链接 生成了 led.elf 文件, 执行 arm-linux-objcopy -O binary led.elf led.bin 命令, 将 elf 文件转换为 bin 文件;
-- 命令解析 : -O 表示输出格式, -O binary 表示输出二进制格式;

三. Makefile 文件
Makefile 示例 :
all: led.o arm-linux-ld -Tled.lds -o led.elf led.o arm-linux-objcopy -O binary led.elf led.bin led.o : led.S arm-linux-gcc -g -o led.o -c led.S .PHONY: clean clean: rm *.o led.elf led.bin
1. Makefile 规则
(1) 普通规则
规则 : 用于说明文件生成过程;
-- 规则语法 :
target(目标) : prerequisites(依赖)
command(命令)
led.o : led.S arm-linux-gcc -g -o led.o -c led.S
-- 语法解析 : led.o 是目标, led.S 是依赖, arm-linux-gcc -g -o led.o -c led.S 是命令;
(2) 通用规则
通用规则示例 :
%.o : %.c
arm-linux-gcc -o %.o %.c
-- 解析 : 编译 main.c 生成 main.o;
2. Makefile 目标
(1) 伪目标
Makefile 中的伪目标示例 : 伪目标 只有命令, 没有依赖;
.PHONY: clean clean: rm *.o led.elf led.bin
-- 伪目标标示 : '.PHONY: clean' 将 clean 声明为 伪目标;
(2) 最终目标
最终目标 : Makefile 默认执行 第一个目标, 第一个目标就是最终目标;
3. Makefile 变量
(1) 自定义变量
变量使用示例 :
-- 使用标量前 :
app1: app1.o func1.o func2.o gcc app1.o func1.o func2.o -o app1 app2: app2.o func1.o func2.o gcc app2.o func1.o func2.o -o app2
-- 定义变量 : obj=func1.o func2.o, 将该定义的变量应用于 Makefile;
obj=func1.o func2.o app1: app1.o $(obj) gcc app1.o $(obj) -o app1 app2: app2.o $(obj) gcc app2.o $(obj) -o app2
(2) 系统定义变量
系统定义变量 :
-- $^ : 代表依赖的文件;
-- $@ : 代表目标;
-- $< : 代表第一个依赖文件;
-- 使用系统变量前 :
all: led.o arm-linux-ld -Tled.lds -o led.elf led.o arm-linux-objcopy -O binary led.elf led.bin led.o : led.S arm-linux-gcc -g -o led.o -c led.S .PHONY: clean clean: rm *.o led.elf led.bin
-- 使用系统变量后 :
all: led.o arm-linux-ld -Tled.lds -o led.elf $^ arm-linux-objcopy -O binary led.elf led.bin led.o : led.S arm-linux-gcc -g -o $@ -c $^ .PHONY: clean clean: rm *.o led.elf led.bin
-- 编译运行 : 编译结果与 不使用系统变量时的规则相同;

4. Makefile 技巧
(1) Makefile 去回显
Makefile 去回显 :
-- 回显 : 执行编译时, 会将命令打印到命令行中;

-- 去回显 : 在命令前添加 '@' 符号;
all: led.o @arm-linux-ld -Tled.lds -o led.elf $^ @arm-linux-objcopy -O binary led.elf led.bin led.o : led.S arm-linux-gcc -g -o $@ -c $^ .PHONY: clean clean: rm *.o led.elf led.bin
-- 执行结果 : 此时就没有上面两条显示了;
(2) Makefile 文件名称修改
Makefile 文件名称 :
-- 默认名称 : make 工具默认寻找 'Makefile' 或者 'makefile' 文件, 如果没有回报错;

-- 指明 Makefile 文件 : make -f Makefile-ARM 命令;

四. 链接器脚本
1. 链接器脚本示例
可执行程序组成 : 代码段, 数据段, bss 段; 链接器脚本就是配置这些段信息;
简单的链接器脚本示例 :
-- 代码段 : .text 表示代码段, * 表示所有文件, *(.text) 表示所有文件的代码;
-- 数据段 : .data 表示数据段, * 表示所有文件, *(.data) 表示所有文件的数据段;
上一篇:【嵌入式开发】ARM 芯片简介 (ARM芯片类型 | ARM处理器工作模式 | ARM 寄存器 | ARM 寻址)
下一篇:Linux驱动——LED闪烁
推荐阅读最新更新时间:2026-02-26 05:42



Follow me第三季第4期】英飞凌 PSOC™6 蓝牙原型开发板任务代码相关资料
Linux技术手册
MAX32625 PICO 嵌入式程序
非常经典的关于LLC的杨波博士论文
XC6406PP60DL






京公网安备 11010802033920号