当前位置:   article > 正文

elf可执行文件的生成及加载_eclipse无法生成elf文件

eclipse无法生成elf文件

The compiler, assembler, linker, loader and process address space tutorial - hacking the process of building programs using C language: notes and illustrations

预编译,编译,汇编,链接

  • 预编译:处理 #include , #ifdef ,#ifndef ,#define 等语句,加载.h文件,条件编译,宏定义
  • 编译:拿到预编译的输出和源码,生成汇编指令。
  • 汇编:汇编是编译的第三阶段。它获取汇编源代码并生成带有偏移量的汇编列表。汇编器输出存储在目标文件中。这个目标文件已经是这个C程序的机器码了(不包含链接)
  • 链接:把汇编生成的.o文件还有lib文件作为输入,把他们组合到一起,生成一个真正的可执行文件,在此过程中,它解析对外部符号的引用,为过程/函数和变量分配最终地址,并修改代码和数据以反映新地址(称为重定位的过程)

在linux中,最终链接生成的文件是elf文件。可以同readelf 来查看文件头,维基百科对elf文件进行了详细的论述: https://en.wikipedia.org/wiki/Executable_and_Linkable_Format

这里有一段小代码,可以看出,系统加载elf文件的过程。

static uintptr_t loader(PCB *pcb, const char *filename) {
  Elf_Ehdr* elf  = (Elf_Ehdr*)&ramdisk_start;
  assert(*(uint32_t *)elf->e_ident == 0x464C457F);
  assert(elf->e_machine == EXPECT_TYPE);
  Elf_Phdr* phdr = (Elf_Phdr*)((void *) elf + elf->e_phoff);

  for(int i = 0 ; i < elf->e_phnum ; i++){

    if(phdr->p_type == PT_LOAD){
      ramdisk_read((void *)phdr->p_vaddr, phdr->p_offset , phdr->p_memsz);
      memset( ((void*)phdr->p_vaddr + phdr->p_memsz),0,phdr->p_memsz-phdr->p_filesz);
    }
    phdr = phdr+1;
  }
  return elf->e_entry;
}

elf文件可以用两个视角了看,一个是section视角,也就是存在文件系统中的视角,告诉你这个elf文件是怎么链接起来的。(上诉链接有更详细说明,建议阅读)

另外一个视角是segment视角,告诉你这个文件应该如何被加载。

由上诉代码可以看出

  • 只有当phdr->p_type == PT_LOAD,这段内容才会被加载到内存中去。
  • 返回的elf->e_entry其实是elf文件中的机器码,也就是说,程序本质是一系列的指令,而这个指令真的存在于我们的elf文件中。

对于elf文件:

Section

Description

.text

This section contains the executable instruction codes and is shared among every process running the same binary. This section usually has READ and EXECUTE permissions only. This section is the one most affected by optimization.

要执行的代码段,进程只能读,执行 。 这部分是受优化影响最大的部分(比如我们编译选择-O2,那么有一些指令就会不被执行。)

.bss

BSS stands for ‘Block Started by Symbol’. It holds un-initialized global and static variables. Since the BSS only holds variables that don't have any values yet, it doesn't actually need to store the image of these variables. The size that BSS will require at runtime is recorded in the object file, but the BSS (unlike the data section) doesn't take up any actual space in the object file.

bss是 由符号开始的块(没有初始化),它保存未初始化的全局和静态变量 , 由于 BSS 只保存没有任何值的变量,它实际上并不需要存储这些变量的图像。 BSS 在运行时需要的大小记录在目标文件中,但 BSS(与数据部分不同)不占用目标文件中的任何实际空间。(只记录大小,并没有实际的存储空间,这也是非常容易理解的,因为没有初始化,那我只需要记录下你需要多大的空间,在机器码执行时,让这些变量依次放在这个空间中即可。)

.data

Contains the initialized global and static variables and their values. It is usually the largest part of the executable. It usually has READ/WRITE permissions.

包含初始化的全局和静态变量 ,以及他们的数值,通常是可执行文件的最大的部分,通常都是有读写权限。

.rdata

Also known as .rodata (read-only data) section. This contains constants and string literals.

保存常量和字符文字,只能读。

.reloc

Stores the information required for relocating the image while loading.

存放重定位信息,在加载的时候需要用到这些信息,有一些elf文件是没有的。

Symbol table

A symbol is basically a name and an address.  Symbol table holds information needed to locate and relocate a program’s symbolic definitions and references. A symbol table index is a subscript into this array. Index 0 both designates the first entry in the table and serves as the undefined symbol index.  The symbol table contains an array of symbol entries.

一些名字和地址,比如:

Num: Value Size Type Bind Vis Ndx Name
...
14: 00000000 0 FILE LOCAL DEFAULT ABS impure.c
15: 830066d8 1064 OBJECT LOCAL DEFAULT 3 impure_data
16: 00000000 0 FILE LOCAL DEFAULT ABS writer.c
17: 00000000 0 FILE LOCAL DEFAULT ABS memchr.c
18: 00000000 0 FILE LOCAL DEFAULT ABS strlen.c

...

也就是说,当elf文件被加载到内存地址空间之后,访问某个函数的代码,实际上就是去访问其对应的地址。

Relocation records

Relocation is the process of connecting symbolic references with symbolic definitions. For example, when a program calls a function, the associated call instruction must transfer control to the proper destination address at execution. Re-locatable files must have relocation entries’ which are necessary because they contain information that describes how to modify their section contents, thus allowing executable and shared object files to hold the right information for a process's program image.  Simply said relocation records are information used by the linker to adjust section contents.

重定位是将符号引用与符号定义连接起来的过程。例如,当程序调用一个函数时,相关的调用指令必须在执行时将控制转移到正确的目标地址。可重定位文件必须具有重定位条目,这是必要的,因为它们包含描述如何修改其节内容的信息,从而允许可执行和共享目标文件保存进程程序映像的正确信息。简单地说,重定位记录是链接器用来调整节内容的信息。

通过这个记录,我们可以把多个.o文件,链接到一起。

静态链接和动态链接

静态链接,在链接时,把整个库都链接进去。

动态链接,只有在加载程序时, 再去系统中去找动态链接库。

对于一些只读的库,我们可以只加载一次,让多个进程共享这个库。(怎么证明?需要补充一个例子)

运行时的程序分5段,text, data ,bss, stack  heap. 

Process memory layout

对于堆,实际上在地址空间段,被归为数据段。

Executable file section

(disk file)

Address space segment

Program memory segment

.text

Text

Code

.data

Data

Initialized data

.bss

Data

BSS

-

Data

Heap

-

Stack

Stack

C程序内存加载:

Another big picture of the C process memory layout

程序运行时的虚拟地址空间,映射到物理地址示意图。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/160703
推荐阅读
  

闽ICP备14008679号