浅谈编译过程和符号表重定位问题

对于代码的编译问题千头万绪从何说起呢,首先来说一下计算机是如何处理应用程序的,实质上应用程序是通过操作系统来应用机器指令操控硬件设施完成各种任务的,就从编译的环节开始谈起吧,众所周知,程序开发人员所写的代码实际上计算机是没有办法去认识的,那么就必须通过编译将其转换为计算机可以认识的机器指令,在有操作系统根据具体指令从硬件上分配内存处理程序段。以下从预编译,编译,汇编,链接,来简单的说一下程序的编译过程。

2.1编译预处理

在这个阶段主要是宏定义的展开,以及头文件的递归处理,即展开所有的以#开头的编译命令。

2.2编译阶段

将程序代码段按字符流格式进行切割,处理,主要是词法分析,语法分析,语义分析等阶段,编译完成后生成中间代码。

2.3汇编

将编译后的中间代码通过汇编器模块生成计算机能够识别的机器指令用以操控硬件设施生成目标代码(可重定位目标代码)。

2.4链接

通过链接器模块将各种目标代码以及库文件(*.lib文件),资源文件(*,rec)进行链接处理最终生成可以执行的*.exe文件。

2.5重定位问题

通过一个例子来看:假如我们有两个头文件和两个源文件分别叫做function1.h和function2.h以及function1.cpp和function2.cpp文件其中function1.h内容如下

Function1.h

#ifndef   _FUNCTION1_H

#define   _FUNCTION1_H

Int g_val;

Int Add(int m, int n);

#endif

Function1.cpp

g_val=10;

Int Add(int m, int n)

{

Return m+n;

}

Function2.cpp其中包含了main函数内容如下

#include “function1.h”

Int main()

{

Int  l_valfri=3;

Int  l_valsec=4;

g_val=14;

Int result=Add(l_valfri,l_valsec);

Return 0;

}

对于这样的代码编译器在编译function2.cpp时对于外部符号g_val 和外部函数Add该如何决议呢,这里又会涉及到可重定位文件中的符号表问题。

其实在可重定位目标文件之中会存在一个用来放置变量和其入口地址的符号表,当编译过程中能够找到该符号的定义时就将该符号入口地址更新到符号表中否则就对该符号的地址不做任何决议一直保留到链接阶段处理。通过两个例子来看符号表的结构。

在编译过程中function1.cpp文件的可重定位目标文件中的符号表如下


变量名


内存地址


g_val


0x100


Add


0x200

为什么可以做到对于符号g_val和Add分配内存地址呢,因为在编译阶段就能够在function1.cpp文件中找到他们的定义,所以能够进行明确的内存地址分配。

再来看看function2.cpp所生成的可重定位目标文件的结构:


变量名


内存地址


g_val


0x00


Add


0x00

为什么会出现这样的状况。因为在编译阶段虽然可以看到这些符号变量的声明,但却找不到他们的定义所以编译器陷入了一个决而未决的境地。

将包含文件展开时,function2.cpp大概会是这个样子很明显只有符号变量的声明但是没有定义。

#ifndef   _FUNCTION1_H

#define   _FUNCTION1_H

Int g_val;

Int Add(int m, int n);

#endif

Int main()

{

Int  l_valfri=3;

Int  l_valsec=4;

g_val=14;

Int result=Add(l_valfri,l_valsec);

Return 0;

}

先将他们存放在符号表中但却不去为他们进行内存关联一直等到链接阶段在进行处理。

重定位发生于目标代码链接阶段,在链接阶段链接器就会查找符号表,当他发现了function2.cpp的符号表之中任然有没有决议的内存地址时,链接器就会查找所有的目标代码文件,一直到他找到了function1.cpp所生成的目标代码文件符号表时发现了这些没有决议的符号变量的真正内存地址,这是function2.cpp所生成的目标代码文件就会更新它的符号表,将这些尚未决议的符号变量的内存地址写进其符号表中。

更新之后的function2.obj文件符号表


变量名


内存地址


g_val


0x100


Add


0x200

当所有的符号变量都能够找到合法的内存地址时,链接阶段重定位完成。

时间: 2024-09-30 18:54:52

浅谈编译过程和符号表重定位问题的相关文章

浅谈编译原理

什么是编译原理? 编译原理顾名思义,编译就是将源语言(高级程序语言)翻译成等价的目标语言(机器语言即计算机可以识别的语言即0和1或汇编语言)的过程.原理就是研究这一过程的思想方法.理论和技术.从本质上来讲编译是一个算法问题,但由于它的问题相当复杂,导致设计解决这个问题的算法也十分复杂.这里的算法和我们学习的数据结构和算法中的算法有些不同,后者讲述的是基础算法,是解决我们生活中遇到的问题,而编译中的算法则是在人与计算机交流时需要解决的“沟通”问题的算法,比较专注解决一种的算法.编译的过程包括:源程

浅谈编译高通android5.1源代码

为什么会编译高通5.1源代码,原因很简单,因为公司做高通平台的手机,所以有必要编译下 Linux基础学习篇 1.常用指令 ls 显示文件或目录 –l  列出文件详细信息 l(list)   –a   列出当前目录下所有文件及目录,包括隐藏的a(all) mkdir 创建目录 -p 创建目录,若无父目录,则创建p(parent) cd 切换目录 touch 创建空文件 echo 创建带有内容的文件. cat 查看文件内容 cp 拷贝 mv 移动或重命名 rm 删除文件 -r 递归删除,可删除子目录

浅谈编译kernel+busybox构建拥有远程ssh登录和web功能最小linux系统

实验环境win7+VM11.1 本文的源码的版本了 dropbear-2013.58.tar.bz2    busybox-1.21.1.tar.bz2 linux-3.13.6.tar.xz  nginx-1.4.7 大致过程总揽 1,硬件准备以及查看硬件设备型号(不用担心,这些都是VM虚拟出来的) 2,编译环境的配置以及下载内核源码以及编译内核 3,编译busybox,以及提供系统正常运行的配置文件,初步运行linux系统 4,编译安装dropbear提供ssh服务 5,安装nginx:提供

浅谈 T-SQL语句操纵数据表

SQL是结构化查询语言,也是关系数据库的标准语言,各类数据库都支持SQL作为查询语言.T-SQL 是标准SQL的加强版,除了标准的SQL命令之外,还对SQL命令进行了许多扩充.提供类似于程序语言的基本功能.如变量说明.流程控制.功能函数等.当我们安装上数据库时,在其上常做的操作无非就是插(增).删.改.查这四类,今天我们就来围绕这四个操作来谈一谈.插入数据: insert into **表名** (列名1,列名2.....) 其中into为可选项,可以省略 #多个列名和多个值列表用逗号隔开 va

浅谈数据结构:哈希表

一.  基本概念 哈希表(hash table )是一种根据关键字直接访问内存存储位置的数据结构,通过哈希表,数据元素的存放位置和数据元素的关键字之间建立起某种对应关系,建立这种对应关系的函数称为哈希函数 二.哈希表的构造方法 假设要存储的数据元素个数是n,设置一个长度为m(m > n)的连续存储单元,分别以每个数据元素的关键字Ki(0<=i<=n-1)为自变量,通过哈希函数hash(Ki),把Ki映射为内存单元的某个地址hash(Ki),并将数据元素存储在内存单元中 从数学的角度看,哈

浅谈VUE, vue + elementui表单重置 resetFields问题(无法重置表单)

问题: elementui在重置表单时,无法使用this.$refs['formRefVal'].resetFields()清空表单数据; elementui 设置rules后没有效果 解决方法: 第一步写入el-form,首先添加ref属性 <el-form :model="form" ref="roleform"> </el-form> 第二步每一个 el-form-item标签里必须加上prop属性,属性名一定要对应表单里的每一个属性

查看程序符号表的几个命令

objdump -t xxx.o [email protected]:~/Documents/encrypchip$ objdump -t main.o main.o: file format elf32-little SYMBOL TABLE: 00000000 l df *ABS* 00000000 main.c 00000000 l d .text 00000000 .text 00000000 l d .data 00000000 .data 00000000 l d .bss 0000

浅谈算法和数据结构: 六 符号表及其基本实现

http://www.cnblogs.com/yangecnu/p/Introduce-Symbol-Table-and-Elementary-Implementations.html 浅谈算法和数据结构: 六 符号表及其基本实现 前面几篇文章介绍了基本的排序算法,排序通常是查找的前奏操作.从本文开始介绍基本的查找算法. 在介绍查找算法,首先需要了解符号表这一抽象数据结构,本文首先介绍了什么是符号表,以及这一抽象数据结构的的API,然后介绍了两种简单的符号表的实现方式. 一符号表 在开始介绍查找

C++编译与链接(2)-浅谈内部链接与外部链接

发现每次写技术博客时,都会在文章开头处花费一番功夫 ...从前,有一个程序员....他的名字叫magicsoar 为什么有时会出现aaa已在bbb中重定义的错误? 为什么有时会出现无法解析的外部符号? 为什么有的内联函数的定义需要写在头文件中? 为什么对于模板,声明和定义都在写在一起? 读完这篇博客,相信你会有一个初步的认识 注,我们现在谈的编译其实可以认为由4个环节组成,其中有编译环节,链接环节, 我会尽量在上下文中指明说的总体的编译,还是具体的编译环节,望读者周知 关于编译过程详解说明,可以