编译、链接、目标文件格式学习简记

来源:互联网 发布:网络传播 传统传播 编辑:程序博客网 时间:2024/06/07 06:08


1、编译的过程可以为分为4个阶段:预处理、编译、汇编、链接



2、gcc命令实际只是一些后台程序的包装,它会根据不同的参数要求去调用预编译程序ccl,汇编器as、链接器ld


3、汇编器是将汇编代码转成机器可以执行的指令,每一个汇编语句都对应一条机器指令。


4、词法分析:
     首先代码程序被输入到扫描器,扫描器的任务很简单,他只是简单地进行词法分析,
运用一种类似于有限状态机的算法可以很轻松地将源代码的字符序列分割成一系列的记号。
 
语法分析:
  接下来语法分析器将对记号进行语法分析,从而产生语法树,整个分析过程采用了上下文无关语法的分析手段。
  
  简单来说,由语法分析器生成的语法树就是以表达式为节点的树。
  
    词法分析工具:lex
语法分析工具:yacc

5、编译器所能分析的语义是静态语义,与之对应的是动态语义


    静态语义通常包括声明和类型的匹配,类型的转换


目标文件里有什么:


1、ELF格式文件:可重定位文件、可执行文件、共享目标文件(动态库)、核心转储文件


2、目标文件里包括:机器指令码、数据、符号表、调试信息、字符串等。
    一般目标文件将这些信息按不同的属性,以“节”的形式存储,有时候也叫“段”


3、程序源代码编译后的机器指令经常放在“代码段”里,代码段常见的名字有“.code”或“.text”
   
    全局变量和局部静态变量数据经常放在数据段,“.data”


4、段表:一个描述文件中各个段的数组


   ELF文件的开头是“文件头(File Header)”,包括:是否可执行、是静态链接还是动态链接、入口地址(如果是可执行文件)


5、已初始化的全局变量和局部变量都保存在.data段,未初始化的全局变量和局部静态变量一般放在一个叫“.bss”的段里


   .bss段只是为未初始化的全局变量和局部静态变量预留位置而已
 
6、程序源代码被编译以后主要分成两种段:程序指令和程序数据。代码段属于程序指令,而数据段和.bss段属于程序数据


7:、数据区域对于进程来说是可读写的,而指令区域对于进程来说是只读的


    当系统中运行着该程序的多个副本时,它们的指令都是一样的,所以内存中只需要保存一份该程序的指令部分


8、Linux中有一个专门的命令叫做“size”,它可以用来查看ELF文件的代码段、数据段和BSS段的长度


9、“.rodata”段存放的是只读数据,一般程序里面的只读变量(如const修饰的变量)和字符串常量


1、GCC提供了一个扩展机制,使得程序员可以指定变量所处的段:
   __attribute__((section("FOO"))) int global = 42;
   
   __attribute__((section("BAR"))) void foo()
   {
   
   }
   
在全局变量或函数之前加上“__attribute__((section("name")))”属性就可以把相应的变量或函数放在以“name”作为段名的段中


2、ELF魔数:
   ELF 文件头的开始16个字节即成员e_ident被用来标识ELF文件的平台属性。
   
   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
   
   前4个字节是所有ELF都必须相同的标识符,分别为  0x7F 0x45 0x 4c 0x46,分别表示ASCII码字符的DEL控制符,后面3个字节刚好是E L F这3个字母的ASCII码
   
   这4个字节称为ELF魔数
   
   魔数用来确认文件的类型,操作系统在加载可执行文件的时候会确认魔数是否正确,如果不正确会拒绝加载。
   
   第5个字节用来标识ELF文件类,0x01表示是32位的,0x02表示是64位的
   
   第6个字节是字节序,规定该ELF文件是大端还是小端
   
   第7个字节规定ELF文件的主版本号,一般是1
   
3、e_type成员表示ELF文件类型:
     
  ET_REL   1  可重定位文件,一般为.o文件
  ET_EXEC  2  可执行文件
  ET_DYN   3  共享目标文件,一般为.so文件


4、段表:
     段表是ELF文件中除了文件头以外最重要的结构,他描述了ELF各个段的信息,包括:
        段名、段的长度、在文件中偏移、读写权限及段的其他属性   


5、段表的结构比较简单,它是一个以“Elf32_Shdr”的结构体为元素的数组。“Elf32_Shdr”又被称为段描述符


6、段的标志位:表示该段在进程虚拟地址空间中的属性,比如是否可写,是否可执行等


7、字符串表:字符串表中通过偏移来引用字符串
   “.strtab”和“.shstrtab”分别表示字符串表和段字符串表
   
8、符号
   目标文件之间相互拼合实际上是目标文件之间对地址的引用,即对函数和变量的地址的引用
   
   在链接中,我们将函数和变量统称为符号,函数名和变量名就是符号名
   
9、每一个目标文件都有一个相应的符号表,这个表里记录了目标文件中所用到的所有符号,每个符号有一个对应的值,叫做符号值


   符号表符号分类:
     1)、定义在本目标文件中的全局符号,可以被其他目标文件引用
2)、在本目标文件中引用的全局符号,却没有定义在本目标文件,这一般叫做外部符号
3)、段名,这种符号往往由编译器产生,它的值就是该段的起始地址
4)、局部符号,这类符号只在编译单元内部可见
5)、行号信息,即目标文件指令与源代码中代码行的对应关系


10、对于那些STT_SECTION类型的符号,他们表示下标为Ndx的段的段名


11、当我们使用ld作为链接器来链接生成可执行文件时,会定义很多特殊符号。


    __executeable_start   程序的起始地址    不是入口地址

__etext或_etext或etext   该符号为代码段结束地址

_edata或edata   该符号为数据段结束地址

_end或end    该符号为程序结束地址

12、  编译器在将C++源代码编译成目标文件时,会将函数和变量的名字进行修饰,形成符号名


      函数签名: 函数签名包含了一个函数的信息,包括函数名、它的参数类型、它所在的类和名称空间及其他信息

0 0
原创粉丝点击