第七课 程序的装载(4)

来源:互联网 发布:快易数据恢复 破解版 编辑:程序博客网 时间:2024/06/06 12:44

本文主要写实验内容

源文件

创建hello.c,文件内容如下:

#include <stdio.h>int main(int argc,char *argv[]){    printf("hello world!\n");    return 0;}

预编译

,命令:

gcc -E -o hello.cpp hello.c -m32

生成hello.cpp,在hello.cpp中增加了头文件的说明,内容中包括了对printf的声明。由于其他内容较多,都为stdlib.h头文件的内容,这里不再赘述。
extern int printf (const char *__restrict __format, …);

编译

命令为:

gcc -x cpp-output -S -o hello.s hello.cpp -m32

生成汇编文件hello.s
文件内容如下:

    .file   "hello.c"    .section    .rodata.LC0:    .string "hello world!"    .text    .globl  main    .type   main, @functionmain:.LFB0:    .cfi_startproc    pushl   %ebp    .cfi_def_cfa_offset 8    .cfi_offset 5, -8    movl    %esp, %ebp    .cfi_def_cfa_register 5    andl    $-16, %esp    subl    $16, %esp    movl    $.LC0, (%esp)    call    puts    movl    $0, %eax    leave    .cfi_restore 5    .cfi_def_cfa 4, 4    ret    .cfi_endproc.LFE0:    .size   main, .-main    .ident  "GCC: (Ubuntu 4.8.2-19ubuntu1) 4.8.2"    .section    .note.GNU-stack,"",@progbits

通过上述代码,我们能够看到熟悉的函数调用的流程。清空栈空间,调用了puts函数实现printf函数。
汇编
汇编命令为:

gcc -x assembler -c hello.s -o hello.o -m32

生成目标文件hello.o是可重定位的目标文件。

链接

生成可执行文件,命令为:

gcc -o hello  hello.o -m32

目标文件

目标文件是不能直接被打开,需要在linux下使用readelf工具打开。
hello.o文件头部信息:

hello.o的头部信息
在头部中指明了文件类型为elf32的文件类型。type为rel是可重定位的目标文件。运行的机器类型为intel 80386
入口点地址为0x0,没有入口地址。
可执行文件的elf文件格式为:
hello的文件头部信息
这里非常重要的是指出了文件的入口地址是0x8048320,文件的类型为可执行类型。
我们再把elf的头部信息的定义的结构体写在这里,与hello可执行文件进行对比分析。

  #define EI_NIDENT       16  typedef struct {      unsigned char       e_ident[EI_NIDENT];      Elf32_Half          e_type;      Elf32_Half          e_machine;      Elf32_Word          e_version;      Elf32_Addr          e_entry;      Elf32_Off           e_phoff;      Elf32_Off           e_shoff;      Elf32_Word          e_flags;      Elf32_Half          e_ehsize;      Elf32_Half          e_phentsize;      Elf32_Half          e_phnum;      Elf32_Half          e_shentsize;      Elf32_Half          e_shnum;      Elf32_Half          e_shstrndx;  } Elf32_Ehdr;

e_type指出了文件的类型,为EXEC可执行文件或者REL可重定位文件。
e_machine都是intel 80386的机器类型
e_version都取值为0x01,表示了object的当前版本。如果为0x0则表示了invalid文件版本。
e_entry:入口地址。指出了进程的入口位置,但是在hello.o中就没有可执行入口位置取值为0x0.在有入口位置的情况下,我们需要记住这个值,特殊的值,虚拟地址值:0x0804 8320.
e_phoff:程序头表在文件中的偏移量,在hello可执行文件中,程序头表是必须的,因此在hello中值为52字节。但是在hello.o可重定位的文件中,程序头表不是必须的,偏移值为0字节,表示没有。
e_shoff:section的头表。在可执行文件中不是必须的,在relocate文件中是必须的。在例子中都是存在的。hello中取值为:4428Bytes,hello.o中取值为:284bytes。
e_flags: 该成员保存着相关文件的特定处理器标志。都为0x0.
e_ehsize:ELF头大小。hello和hello.o中都是52字节大小,两个长度相等。
e_phentsize:在文件的程序头表(program header table)中一个入口的大小 (以字节计数)。所有的入口都是同样的大小。hello中有程序头表,大小为32字节,但是hello.o没有程序头表,大小为0x0.
e_phnum:程序头个数,hello中有9个。自然hello.o中有0个。
e_shentsize:节头大小。hello:中为40字节,hello.o中为40字节。
e_shnum:节头个数,hello中为30个。个数为13个。
e_shstrndx: 该成员保存着跟section名字字符表相关入口的section头表(section header table)索引。

静态链接

静态链接的指令为:

gcc -o hello.static -c hello.o -static -m32

如果静态链接文件后,生成的可执行文件将会变大而且文件的入口地址变为:0x804 8d0a地址处。
静态编译的文件

0 0
原创粉丝点击