1.目标文件是什么?
- 从hello world讲起
"hello world"是每个程序员的必经之路,在linux下开发,我们编译代码只需要使用如下命令,就能打印出hello world;
$gcc hello.c
$./a.out
但是事实上,上述过程可以被分解为4个步骤,预处理、编译、汇编和链接
;
$gcc --help
-E preprocess only;do not compile, assemble or link
-S compile only, do not assemble or link
-c compile andn assemble, but do not link
上述4个步骤不过多描述,这个在网上资料都很多
- 汇编是什么
汇编做的事情实际上是汇编器将汇编代码转换成机器代码
- 目标文件定义
经过预处理、编译、汇编过程所生成的文件称为目标文件;
从广义上来说,由于可执行文件与目标文件的格式基本一致,所以可执行文件也可以被认为是目标文件;
2.目标文件分类
ELF文件类型 | 说明 | 实例 |
---|---|---|
可重定位文件 | 这类文件包含代码和数据段,可被用来链接成可执行文件或者共享目标文件 | linux下的.o/.a以及windows下的.obj文件 |
可执行文件 | 可以直接执行,代表就是ELF可执行文件 | windows下的.exe,linux下的a.out |
共享目标文件 | 包含了代码和数据,可以在以下两种情况下使用,1.链接器可用这种文件跟其他的可重定位文件链接,产生新的目标文件;2.动态链接器可以将将共享目标文件和其他可执行文件结合,作为进程的一部分来运行 | linxu下的.so 以及windows下的.dll |
3.使用工具分析目标文件
-
readelf工具
- display information about the contents of ELF format file
- -S选项, display the sections' header,(目标文件的各种不同的信息用section来存储,例如.text段、.data段、.bss段等等)
- -h选项,展示ELF文件的头文件的信息
-
objdump工具
- display information from object
- -D选项,反汇编出所有section
-
nm工具
- list symbols in files
4.链接的接口——符号
链接的本质是把多个不同的目标文件相互粘连在一起,在链接中我们将函数和变量统称为符号(symbol),函数名或变量名被称为符号名(symbol name)
-
c和c++的兼容
- c++是支持函数重载的,c是不支持的,关键底层原因在于编译器对这两者做处理是有一定差异的,c处理时将会将一个函数的符号变成_函数,例如hello(void)会变成_hello,而c++会把参数也带进去,变成hellov,因此c++支持重载是因为他的函数参数是可以变化的,编译的时候不会报错
- 了解原因之后,就会明白c/c++混合编程只需要将一些需要的部分用c的编译器来处理就行,加上extern C
code example:
//hello.c
void hello(void)
{
printf("hello!\n");
}
//hello.h
#ifdef __cplusplus
extern "C" {
#endif
void hello(void);
#ifdef __cplusplus
}
#endif
//main.cpp
#include "hello.h"
int main(void)
{
hello();
return 0;
}
$gcc -c hello.c
$nm hello.o
.....能看到hello的符号是_hello
$g++ -c main.cpp
$nm main.o
看到hello的符号还是_hello,如果在hello.h中将extern C去掉,则发现 nm main.o中的符号是hellov,就会报错
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。