0

题目描述

编译程序编译C语言的过程中,必须要通过操作符号表来确定各个被定义的符号(变量,数组,函数,标签等)的地址,以便于将文本形式的代码翻译为二进制机器码.而所得到的ELF文件(.o/.exe)中的符号表节区(.symtab)只包含存储类型为static/extern的变量,而不包含auto局部变量.那么,局部变量是如何被编译器翻译的?

题目来源及自己的思路

来源: 编译过程必须依靠符号表来实现.编译过程输出ELF文件,而ELF文件的符号表节区(.symtab)并不包含局部变量.那么,局部变量是如何编译的呢?
自己的思路:
1.ELF文件是编译过程的输出,是最终的结果,它的符号表节区(.symtab)也仅仅是符号表操作的最终结果,无法反映整个编译过程的符号表变化.所以,在编译过程进行的时候,局部变量是会出现在符号表之中的,而编译程序据此确定局部变量的地址(局部变量位于栈中,其地址是相对栈指针sp的偏移量),进而实现对局部变量的翻译.
2.符号表的操作包含增加项目,查找项目,删除项目.在编译过程结束时,会跳出所有的函数与块作用域,相应的,栈内存也会进行出栈操作.而与之相关的局部变量也会从符号表之中被删除掉,只保留静态变量static,全局变量以及外部变量extern.所以,最终的输出ELF文件的符号表节区(.symtab)没有局部变量的内容.

问题期望

1.上述的思路是否正确?
2.如果不正确,错误在哪?要理解正确的思路,需要查找哪些方面的知识?

2月2日提问
2 个回答
0

还特么没审核过

0

符号表并不是在编译过程中一直存在的。在最终产生汇编的编译器步骤里面才会真正往object .symtab中写符号,在编译过程中通常是有一个数据结构去存储所有的symbol,包括全局symbol,栈上面的symbol等。但是不同的symbol有不同的类型,比如全局symbol是全局类型,栈symbol是auto类型,只有特定种类的symbol才需要写到.symtab中,auto类型是不用写进去的。
栈变量的寻址,因为编译器编译的时候是知道这个函数里面所有变的局部变量的,因此编译器编译中有一个步骤会将函数里面所有的局部变量,包括用户代码定义的,以及编译器生成的临时栈变量跟当前栈帧的base建立映射,实际上就是指明这个栈变量存在离栈帧多远的地方。只要定义好这个,栈变量就能寻址了。一般abi规定从栈的什么位置开始是栈的局部变量的存储区域。

另外符号表是给linker来把很多的object文件链接生成一个binary的,所以符号表里面不需要存局部变量,因为局部变量都是相对栈帧寻址,不需要linker去给它resolve它的真正地址,这才是.symtab中为什么没有栈变量的原因。

撰写答案

推广链接