静态程序编译链接与装载(一)问题的引入以及工具介绍

关于程序的编译链接与装载,有一些问题一直没有弄得很清楚。这次花了不少精力,把这些问题,好好研究了一番。在学习的过程中,熟读了<<程序员的自我修养-链接、装载与库>>这本书,收获良多。强烈推荐这本书。

此次系列文章,是针对静态编译,动态编译太多复杂,目前仍有很多问题,没有解决。

在开始之前,带有如下的一些问题:

  • 程序是如何编译成可执行程序?

  • 跨模块之间,如何知道其他模块的函数以及变量地址?

  • linux下,可执行程序elf,长什么样?

  • 对于任意一个elf,如何查看该elf的信息?

  • 反汇编中,程序的地址,以及符号,是如何得到的?

  • 为什么程序,以section为单位进行组织?

  • section与segment的区别是什么?

  • ELF中的VMA与LMA的区别是什么?链接视图与执行视图区别是什么?

  • 在EDA仿真中,elf,是如何装载到环境中去运行的?

  • 在linux中,elf程序,是如何装载到内存中运行的?

  • 链接脚本的AT,MEMORY关键字,到底有什么用?

    通过查看资料,以及自己做实验,对这些问题,有了清晰的答案。希望通过本系列博文,也能让大家,对这些问题,也有清晰的答案。

    一、工具介绍

    首先是介绍下,之后会用到的一些工具:

  • aarch64工具链,包括如下:

    • -S参数:将源程序转换成.s

    • -c参数:将源程序转换成.o

    • aarch64-none-elf-gcc:arm-gcc编译器

    • aarch64-none-elf-as: 汇编器,将.s转换成.o

    • aarch64-none-elf-ld: 链接器,将 .o 链接成elf

    • aarch64-none-elf-objdump: 反汇编,将elf反汇编

  • readelf工具,用于查看elf文件内容

    • -a: 查看elf文件的所有信息

    • -h: 查看elf文件的头信息

    • -l:  查看program段信息

    • -S: 查看section段信息

    • -s: 查看符号表信息

    • -r: 查看可重定位表信息

  • gvim工具,-b参数,表示查看的文件是二进制文件

    • :%!xxd,该命令,在gvim中查看二进制数据

  • hexdump工具,直接查看二进制文件

借助以上的一些工具,就便于之后分析.o文件,.elf文件。

二、示例程序

首先,先介绍使用的示例程序。

两个程序:

  • a.c:

 2个全局变来那个,一个有赋初值,一个没有赋初值

 2个局部静态变量,一个有赋初值,一个没有赋初值

 调用了b.c中的swap函数

  • b.c:

 引用a.c中的一个全局变量

 定义了一个全局变量

 定义了swap函数,供a.c调用

 在swap函数中,更改了a.c中定义的全局变量

程序如下图所示:

之后,便以编译这两个c文件,成最终的可执行程序out.elf为例,来进行详细的分析。

Makefile脚本如下:

后面的 .o和.elf文件的分析,就是基于这个示例程序进行分析的。

此条目发表在其他分类目录。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。