【说明】本文章从本人的CSDN博客搬过来的,因个人感觉CSDN的博客系统太差,so,搬到这里。
1.Linux下的可执行文件是什么格式?
2.假设我们有个文件 hello.c ,那么gcc hello.c 后输出什么,gcc -c hello.c 输出什么 ?
3.这些文件的内部是什么样子的?
这是我们的hello.c文件
#include<stdio.h>
int global_init = 100;
int global_un_init ;
void function1(){
static int static_init = 10;
static int static_un_init;
printf("static_int = %d\n",static_init);
}
int main(int argc,char**argv){
printf("this is main \n");
function1();
return 0;
}
首先,先回答第一个问题。
一些历史的东西不想都搬出来,只想弄点有用的。
a.out 格式 意思 : assembler and link editor output
COFF格式 意思 :Common Object File Format
ELF 格式 意思 : Executable and Linking Format
这3种格式中,ELF是现在主流的格式。a.out很古老了,但是现在默认的a.out好像也是ELF格式了。ELF格式是从COFF格式变种而来的,还有Windows下的PE格式。
现在回答第2个问题。
gcc hello.c 输出的是 a.out,是可执行文件。
而加上参数 -o ,执行gcc hello.c -o hello ,输出的hello是可执行文件。
那么gcc -c hello.c 输出的是什么?是hello.o,它是目标文件。
现在我们有了3个文件a.out , hello , hello.o
为什么说a.out也是ELF格式呢?现在看a.out的文件头信息
再来看hello的文件头:
比较上面两张图片,你会发现左列最上面都写着ELF头,最重要的是,它们的魔数是相同的!魔数的概念应该都知道,操作系统并不是靠文件后缀来识别
,加载执行 可执行文件的,而是靠魔数来判断这个文件是否是可以执行的。就像java的class文件里的魔数一样,虚拟机是靠魔数来判断这个文件是否可以被
解释执行,class文件的魔数是0xCAFEBABE,占了class文件的前四个字节。
那么,我们的ELF文件的前4字节是什么意思呢 ?下面是magic这串数字的意义:
这样,我们便得知了原来Linux下的执行文件同样是靠magic来识别的。
a.out和hello都是可执行文件,他们的格式是ELF,那么hello.o这个目标文件呢,它是什么?答案也是ELF。下面是它的头部信息:
这说明hello.o也是ELF文件。
仔细对比这3个文件的头部信息,可以发现hello.o的头部信息里,入口点地址,程序头起点并没有数值,或者说为0.这是为什么呢 ?
现在回想程序源代码到可执行文件的过程:
预处理
编译
汇编
链接
hello.o是通过gcc -c hello.c 得到的。而-c 选项的意思简答来说,就是只编译,不链接。
没有经过链接这一步,所以这里是不能确定它的入口地址,不仅仅是入口地址,程序中的一些函数 变量等的地址也是不能确定的。
关于链接,在后面的文章里会继续深入讨论。
现在回答第3个问题。
首先,我们已经知道这些文件都是ELF文件
ELF文件的大致格式如下,
当然这只是一个简单的轮廓,实际的要远远别这个复杂,以后会慢慢的道来。