赞
踩
预编译,编译,汇编,链接
在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视角,告诉你这个文件应该如何被加载。
由上诉代码可以看出
对于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 ... 也就是说,当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.
对于堆,实际上在地址空间段,被归为数据段。
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程序内存加载:
程序运行时的虚拟地址空间,映射到物理地址示意图。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。