ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Cortex A移植概念备忘录

Cortex A移植概念备忘录 目录1.交叉编译工具链2.工具链的配置与常用命令2.1 ELF 头部信息readelf -h 查看—— 程序的“运行说明书”2. 2 符号表nm 查看strip 去除—— 程序的“源码索引”为什么对最终可执行文件 strip不影响链接也不影响运行3.生成二进制镜像文件4.生成ELF可执行文件Linux系统移植的核心步骤包括搭建交叉编译工具链、编写Bootloader、移植Linux内核、构建根文件系统。1.交叉编译工具链概念由于开发主机PC与目标机嵌入式板子CPU架构不同需要使用在宿主机上运行但能生成目标机可执行代码的工具链称为交叉编译工具链。核心组件工具链通常包含gcc、ld、ar、objcopy等工具。2.工具链的配置与常用命令环境变量配置将交叉编译工具链的路径添加到shell的环境变量PATH中以便在终端中直接调用工具。常用命令解析file用于查看文件的类型和属性确认可执行文件的架构如x86, arm。readelf用于分析ELF格式文件的头部信息如入口地址、各段信息等。size用于查看目标文件各段代码段、数据段、BSS段的大小。nm用于查看目标文件中的符号表帮助定位函数和变量。strip用于去除可执行文件中的符号表和调试信息以减小文件体积适用于最终部署到资源受限的嵌入式设备。2.1 ELF 头部信息readelf -h查看—— 程序的“运行说明书”CPU 本身是“傻子”它不知道从哪里开始执行也不知道内存怎么划分。ELF 头部就是解决这个问题的。入口地址Entry point address作用告诉操作系统或 BootLoader“加载完程序后请从内存的这一个地址开始执行第一条指令”。实战意义在嵌入式裸机开发中这个地址通常由链接脚本Linker Script指定比如 STM32 的0x08000000。如果你用readelf看到入口地址是0x0或者一个奇怪的地址那程序一运行大概率会“跑飞”或崩溃。各段信息Program Headers / Section Headers头部里会写明.text代码段、.data数据段、.bss未初始化全局变量段在文件中的偏移量、在内存中的大小以及加载地址。作用系统加载器Loader根据这些信息把代码搬运到 RAM/Flash 的指定位置并留出足够的内存空间给变量。实战意义假设你的嵌入式板子 RAM 只有 64KB你用readelf -S看到.bss段占了 70KB那程序一运行就会因为内存溢出而挂掉HardFault。提前用readelf检查就能避免烧录进去后才知道出问题。2. 2 符号表nm查看strip去除—— 程序的“源码索引”编译后的机器码全是0和1CPU 只认地址比如0x80001234不认函数名比如uart_send。符号表就是将内存地址和源代码中的函数名、全局变量名一一对应起来的“密码本”。符号表的作用nm定位函数和变量编译报错“未定义引用undefined reference”时用nm检查.o文件能立刻看到哪些函数地址是U未定义哪些是T已定义帮你排查链接错误。分析内存占用用nm --size-sort可以按大小列出所有函数让你一眼看出哪个函数编译后体积最大比如某个数组占了 10KB方便你优化代码。为什么要去除strip符号表里存着成千上万个函数名比如void init_gpio(void)这种字符串这些名字在程序运行时完全没有用CPU 只看地址不看名字。在资源受限的嵌入式设备中Flash 空间寸土寸金。一个带符号表的程序可能有 500KBstrip掉符号表和调试信息后可能只剩下 200KB文件体积直接缩小一半以上。注意strip后的程序无法再用 GDB 进行源码级单步调试崩溃后只能看到地址比如PC0x8001234所以通常是在最终量产发布前才执行strip而保留一份带符号的版本用于后期维护排查问题。如果是对“最终生成的可执行文件”执行strip完全不影响运行时动态链接程序照常运行。如果是对“还没链接的中间文件.o 目标文件或静态库.a”执行strip会严重影响后续的链接导致链接直接失败。Linux 里的“符号表”拆分成“静态符号表.symtab”和“动态符号表.dynsym”看完下面的对比你就全明白了为什么对最终可执行文件 strip不影响链接也不影响运行当你运行gcc main.c -o app生成最终程序后文件里其实有两张表静态符号表.symtab体积巨大记录了所有函数名、变量名、行号信息。这是专门给调试器GDB和链接器ld看的CPU 和操作系统加载器完全无视它。动态符号表.dynsym体积很小只记录外部依赖的库函数比如printf、malloc和导出的接口。strip默认干的事它只把那张巨大的“静态符号表”和调试信息.debug 段撕掉通常不会动“动态符号表”。所以当程序运行时动态链接器ld-linux.so依然能通过动态符号表找到libc.so里的printf地址完成链接和跳转。程序跑起来完全不受影响并且体积缩小了3.生成二进制镜像文件背景裸机程序如Bootloader、内核需要直接运行在物理内存中因此不能使用带ELF头的可执行文件必须生成纯净的二进制镜像。生成流程使用gcc编译C或汇编源码生成目标文件.o。使用ld命令链接目标文件并通过链接脚本linker script指定各段如代码段、数据段的加载地址。使用objcopy命令将链接后生成的ELF文件中的代码段等实际内容剥离生成最终的二进制镜像文件。4.生成ELF可执行文件a. 把高级语言 .c .S 生成 .o目标文件b. 不能使用ld命令而是使用gcc 将.o目标文件 做为 链接原材料进行链接 gcc会自动加载标准C库和OS初始化库的内容c. 在链接时交给默认链接脚本实现链接 使用虚拟地址d. 默认生成ELF格式的可执行文件
返回列表