首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

使用GCC修复与位置无关的可执行文件中全局变量的重新定位

问题:使用GCC修复与位置无关的可执行文件中全局变量的重新定位。

回答:

与位置无关的可执行文件(Position Independent Executable,简称PIE)是一种在内存中可以加载到任意地址执行的可执行文件格式。在PIE中,全局变量的地址是相对于代码段的偏移量,而不是固定的绝对地址。这种设计使得可执行文件更加灵活,可以在不同的内存地址空间中加载和执行。

然而,由于全局变量的地址是相对的,当可执行文件被加载到不同的地址空间时,全局变量的地址需要重新定位。GCC提供了一种修复与位置无关的可执行文件中全局变量重新定位的方法,即使用特殊的链接选项和编译指令。

具体步骤如下:

  1. 在编译时,使用GCC的-fPIC选项来生成与位置无关的目标文件。例如,可以使用以下命令编译C源文件:gcc -c -fPIC foo.c -o foo.o
  2. 在链接时,使用GCC的-shared选项来生成共享库文件。例如,可以使用以下命令将目标文件链接为共享库:gcc -shared foo.o -o libfoo.so
  3. 在可执行文件中使用全局变量时,使用GCC的外部声明(extern)来引用共享库中的全局变量。例如,在C源文件中可以这样声明全局变量:extern int global_variable;
  4. 在运行时,可执行文件加载共享库时,操作系统会自动为全局变量重新定位,使其指向正确的地址。

修复与位置无关的可执行文件中全局变量的重新定位可以提高可执行文件的灵活性和可移植性。它适用于需要在不同的环境中部署和执行的应用程序,特别是在云计算环境中。

腾讯云提供了一系列与云计算相关的产品和服务,包括云服务器、云数据库、云存储等。这些产品可以帮助用户快速构建和部署云原生应用,提供高可用性和可扩展性。具体推荐的腾讯云产品和产品介绍链接如下:

  1. 云服务器(Elastic Compute Cloud,简称EC2):提供可扩展的计算资源,支持多种操作系统和应用程序。了解更多:腾讯云云服务器
  2. 云数据库(Cloud Database,简称DB):提供高性能、可靠的数据库服务,包括关系型数据库(如MySQL、SQL Server)和NoSQL数据库(如MongoDB、Redis)。了解更多:腾讯云云数据库
  3. 云存储(Cloud Storage,简称COS):提供安全、可靠的对象存储服务,适用于存储和管理大量的非结构化数据。了解更多:腾讯云云存储

请注意,以上推荐的腾讯云产品仅供参考,具体选择应根据实际需求和情况进行。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

地址无关

Linux和GCC支持这种装载时重定位方法,我们前面在产生共享对象时,使用了两个GCC参数“shared”和“-fPIC”,如果只使用“- shared”,那么输出共享对象就是使用装载时重定位方法...因为被调用函数调用者都处于同一个模块,它们之间相对位置是固定,它们之间相对位置都是固定,所以这种情况比较简单。...$gcc -shared pic. c -o pic. so 上面这个命令就会产生一个不使用地址无关代码而使用装载时重定位共享对象。...但是装载时重定位共享对象运行速度要比使用地址无关代码共享对象快,因为它省去了地址无关代码每次访问全局数据和函数时需要做一次计算当前地址以及间接地址寻址过程 对于可执行文件来说,默认情况下,如果可执行文件是动态链接...,那么GCC使用PC方法来产生可执行文件代码段部分,以便于不同进程能够共享代码段,节省内存。

97220

程序员C语言快速上手——工程篇(十二)

动态库 生成位置无关目标文件 打包动态库 关联动态库 动态库静态库区别 动态链接 位置无关代码 总结 动态库运行时加载 链接库 前言 其实学完C语言语法后,我们往往会有数不清疑惑...市场上主流应用程序,并不会使用这种开发方式,包括我们使用QQ之类,他们修复了问题,并不需要用户去重新下载,重新安装。...生成位置无关目标文件 使用一下代码,生成位置无关目标文件add.o、sub.o、div.o gcc -fPIC -c add.c sub.c div.c -f后面跟PIC表示生成位置无关代码(...位置无关代码 前面我们编译动态库时,添加-fPIC参数,生成位置无关代码,那么什么是位置无关代码呢? 如果我们不加这个参数,不生成位置无关代码,那么动态库中被引用符号地址只能被固定写死。...总结 静态库 生成可执行文件体积大 任何修改都需要重新编译发布,不便于更新和维护 整个应用只由一个可执行文件构成 符号使用绝对地址,性能略高动态库 动态库 生成可执行文件体积小 可以热更新,修改和维护方便

1.3K20

动态链接步骤实现

从这一步开始,动态链接器代码才可以使用自己全局变量和静态变量。 实际上在动态链接器自举代码,除了不可以使用全局变量和静态变量之外,甚至不能调用函数,即动态链接器本身函数也不能调用。...其实我们在前面分析地址无关代码时已经提到过,实际上使用PIC模式编译共享对象,对于模块内部函数调用也是采用跟模块外部函数调用一样方式,即使用 GOT/PLT方式,所以在 GOT/PLT没有被重定位之前...我们假设b1.so依赖于a1.so,b2.so依赖于a2.so,将b1.soa1.so进行链接,b2.soa2.so进行链接: $gcc -fPIC -shared a1.c -o a1.so $gcc...全局符号介入地址无关代码 前面介绍地址无关代码时,对于第一类模块内部调用或跳转处理时,我们简单地将其当作是相对地址调用/跳转。...重定位初始化 当上面的步骤完成之后,链接器开始重新遍历可执行文件和每个共享对象定位表,将它们GOT/PLT每个需要重定位位置进行修正。

1.3K20

Javascript局部变量、全局变量详解var、let使用区别

前言 Javascript变量定义方式有以下三种方式: 1、直接定义变量,varlet均不写; a = 10; 2、使用var关键字定义变量 var a = 10; 3、使用let关键字定义变量...得出结论: 在函数体外使用var关键字定义变量和在函数体内未用任何关键字声明变量是全局变量,在函数体内使用var关键字声明变量是局部变量。...JavaScript变量有块范围吗? 在Java、C、C++等语言中,在 if块 ,循环块定义变量,出了该块之后将,不能继续访问。那JavaScript是否也如此呢?...变量提升 前面介绍已经知道:局部变量和全局变量同名时,局部变量会覆盖全局变量。...小结 本文介绍了JavaScript局部变量和全局变量知识和var,let声明变量区别。给我们启示是如果浏览器支持let关键字,那么就尽量用let来避免变量提升机制等情况。

3K20

CSAPP---第七章-链接

加载可执行文件 动态链接 运行时动态链接和加载某个共享库 位置无关代码 PLTGOT 小结 参考 ---- 本文是对CSAPP第7章学习整理简单笔记 ---- 什么是链接 链接是将各种代码和数据片段收集并组合为一个单一文件过程...例如: 使用c标准库函数程序可以用如下命令行进行编译和链接 gcc main.c /usr/lib/libm.a 在链接时,链接器只复制被程序引用目标模块,这就减少了可执行文件在磁盘和内存大小...---- 位置无关代码 由于动态链接通过动态共享一份目标代码,解决了空间浪费和重新链接问题。不同进程之间共享可以通过地址映射解决。...被编译为位置无关代码共享库可以加载到任何地方,也可以在运行时被多个进程共享。为了加载、链接和访问共享库函数和数据,应用程序也可以在运行时使用动态链接器。...编译器驱动程序 [原创] 深入理解计算机系统 - CSAPP重点导读(更新完毕) 动态链接位置无关代码 聊聊Linux动态链接PLT和GOT(1)——何谓PLTGOT

84310

Linux编译工具:gcc入门

汇编器生成是可重定位目标文件,学过操作系统,我们知道,在源程序地址是从0开始,这是一个相对地址,而程序真正在内存运行时地址肯定不是从0开始,而且在编写源代码时候也不能知道程序绝对地址,...hello.c 或 gcc -c hello.c -o hello.o 编译生成可重定位目标文件 使用gcc时可以加上-Wall选项。...使用优点在于: 模块化开发 可重用性 可维护性 库又可以分为静态库动态库: 静态库(.a):程序在编译链接时候把库代码链接到可执行文件。程序运行时候将不再需要静态库。...-lhello 该命令使用静态库命令相同,但是在共享库静态库共存情况下,优先使用共享库。...fPIC表示产生位置无关码(position independent code),位置无关码表示它运行、加载内存位置无关,可以在任何内存地址进行加载。 9.

4.7K50

一文领略链接装载

本文主要根据《程序员自我修养 —— 链接、装载库》和自己理解总结而来,书内容是基于 GCC ,不过笔者尽量以更抽象、更简洁方式把问题讲清楚,避开那些恼人细节。...动态链接:动态链接器将可执行文件和共享对象需要重定位位置进行修正。 最后,进程控制权转交给程序入口,程序终于运行起来了。 大致流程就是如此,不同平台在细节处理上会有所不同,下面分析具体过程。...弱符号强符号 符号分为弱符号强符号,对于 C/C++ 来说,编译器默认函数和已初始化全局变量为强符号,未初始化全局变量为弱符号,可以使用__attribute__ ((weak))定义一个弱符号...在这之前需要了解一下重定位入口集合——重定位表。每一个需要重定位段都有一个之对应定位表。 重定位表也是一个结构体数组,该结构体包含: 重定位入口偏移,即需要修正位置相对于段起始偏移。...动态链接器遍历可执行文件和所有共享对象定位表,通过重定位入口符号在全局符号表中找到对应目标地址,通过重定位入口偏移将这个目标地址填入合适位置(这和静态链接过程基本一样)。

89930

链接加载原理及ELF文件格式

定位表(Relocation): 有了符号表,就需要有人对符号表进行引用,在程序执行过程全局变量引用、跳转、调用函数,这些都涉及到相应符号引用。...因为符号值改变时候,也需要对所有引用符号地方代码进行修改,所以需要还有一张表来记录符号表引用关系,这就是重定位表: 从上图可见,重定位表项用来记录链接和加载过程需要重新定位位置,在各个段位置发生改变而引起符号地址改变时...所以加载过程定位使用了一种改良定位手段:即通过两张间接访问表来屏蔽掉重定位带来对代码修改,访问外部数据使用GOT,访问外部程序使用PLT。...这样可链接出位置无关代码PIC(Position Independent Code),需要重定位时只需要修改GOT和PLT值,而不需要去改动可执行代码。...elf文件格式 Linux环境下,三种类型执行文件都可以使用elf格式来表示:可重定位文件(即编译生成但是未连接文件)、动态库文件、可执行文件

1.1K20

ELF文件及android hook原理

链接器在处理目标文件时,需要对目标文件某些部位进行重定位,即代码段和数据那些绝对地址引用位置。对于每个需要重定位代码段或数据段,都会有一个相应定位表。...第二步 符号解析定位 使用第一步收集到信息,读取输入文件中段数据、重定位信息,并且进行符号解析定位、调整代码地址等 使用ld链接器将”a.o”和”b.o”链接起来: $ld a.o b.o...CPU将控制权交给操作系统,操作系统将查询虚拟空间可执行文件映射关系表,找到空页面所在VMA,计算相应页面在可执行文件偏移,然后在物理内存中分配一个物理页面,将进程该虚拟页分配物理页之间建立映射关系...,然后把控制权再还给进程,进程从刚才页错误位置重新开始执行。.../** 使用静态链接方式将其编译成可执行文件: $gcc -static SectionMapping.c -o SectionMapping.elf **/ #include

3.7K81

《程序员自我修养》第三章学习笔记

从结构上说,是编译后可执行文件,只不过还没有经过链接 3.1 目标文件格式 1,可执行文件格式: Windows下PE  和   Linux下ELF 2,从广义上说,目标文件可执行文件格式几乎是一样...,所以广义上可以将目标文件可执行文件看成是一种类型文件。...它只是为未初始化全局变量和静态局部变量预留位置而已,并没有内容,在文件不占空间。 6,  总体来说:程序源代码被编译后主要分成两种段:程序指令(代码段),程序数据(数据段,bss段)。...3.4.3 重定位表 1,一个叫”rel.text”段,类型是”SHT_REL”,就是重定位表 2,链接器在处理目标文件时,需要对目标文件某些部位进行重定位(即代码段和数据段那些对绝对地址引用位置...3.4.3 字符串表 1,把ELF文件中用到字符串(段名、变量名等)集中起来存放到一个表。然后使用字符串在表偏移来引用字符串。这个表就是字符串表。

1.1K60

【C语言】程序翻译环境和执行环境

指令是:gcc test.i - S,生成 test.s Ⅲ→汇编:对.s文件进行汇编,把汇编代码转换成机器代码指令(二进制代码),还有进行了生成符号表(生成全局变量符号)。...链接器使用每个目标模块定位信息和符号表,来解析所有未定义标签。...采用链接器原因是修补代码比重新编译和汇编要快得多。可以说,通过这个地址就可以找到它所在函数。 如果所有外部引用都解析完,链接器接着决定每个模块将要占用内存位置。...当链接器将一个模块放到内存时候,所有绝对引用(absolute reference),即寄存器无关内存地址必须重定位以反映它真实地址。...链接器产生一个可执行文件(executable file),它可以在一台计算机上运行。通常,这个文件目标文件具有相同格式,但是它不包含未解决引用。

98520

高级语言编译:链接及装载过程介绍

由于 Linux 和 c语言使用相对广泛,同时笔者对 Linux 和C/C++相对熟悉,本文剩下部分都是基于在 Linux 平台下使用 gcc/g++ 编译器编译 c/c++ 源代码进行说明和解释。...然后我们需要来看一下 C 源码程序变量类型和函数类型,最基本 C 程序(不使用 C++ 功能)是比较简单,我们可以声明定义变量和局部变量,全局变量和局部变量可以声明为 static 变量和非 static...对不同目标文件变量进行地址重定位。 这也是链接器所需要实现最基本功能。...对于某一个动态链接库来说,所有使用这个库可执行文件都共享同一块物理地址空间,这个物理地址空间在当前动态链接库第一次被链接时 load 到内存。...,而在 linux ,这个_GLOBAL_OFFSET_TABLE_对应代码段是为了给“地址无关代码”做动态地址重定位

1.4K80

后台开发:核心技术应用实践 -- 编译调试

有相关目标文件牵涉到函数库被链接合成一个可执行文件。程序在运行时,函数库再无瓜葛,因为所有需要函数已复制到相关位置,这些函数库被称为静态库,通常文件名 为 libxxx.a 形式。...ELF 标准目的是为软件开发人员提供二进制接口定义,这些接口可以延伸到多种操作环境,从而减少重新编码、编译程序需要 目标文件有3种类型,如下所述: 可重定位目标文件 这是由汇编器汇编生成 ....组成不同可重定位文件,以参与可执行文件或者可被共享对象文件链接。2. 组成可执行文件或者可被共享对象文件,以在运行时内存中进程映像构建。构建对象文件组成如表: ?.../可执行文件 gdb gdb是gcc 调试工具,主要用于 C和C++ 这两种语言编写程序。...需要强调是,以上内容都是位于程序可执行文件,内核在调用 exec 函数启动该程序时从源程序文件读人数据段属于静态内存分配 未初始化数据段(.bss segment):通常是指用来存放程序未初始化全局变量一块内存区域

74310

程序编译、链接、装载运行

gcc可以使用如下命令对C语言进行预编译并且把预编译结果输出到hello.i文件 gcc -E hello.c -o hello.i 编译 编译就是对预处理之后文件进行词法分析、语法分析、语义分析并优化后生成相应汇编文件...(Object File),目标文件结构可执行文件是一致,它们之间只存在着一些细微差异。...静态链接过程分为两步 扫描所有的目标文件,获取它们每个段长度、位置和属性,并将每个目标文件符号表符号定义和符号引用收集起来放在一个全局符号表,建立起可执行文件到目标文件段映射关系 读取目标文件段数据...堆(Heap)内存管理 堆是一块巨大内存,程序可以在堆申请内存,这些内存在被程序主动放弃之前都可以随意使用。...(寄存器或内存) 系统调用返回,将控制权重新交给用户程序 用户程序从指定区域获取系统调用结果,系统调用结束 用户写C语言时并不会手动调用系统调用,它们一般都被封装在库函数

1.3K10

Operating System 06 - 链接

链接 编译 在unix系统, 由编译器把源文件转换为目标文件: gcc -o hello hello.c 过程如下: ?...链接器主要完成两个任务: 符号解析: 每个符号对应一个函数, 一个全局变量, 或者一个静态变量, 符号解析目的是将每个符号引用一个符号定义关联起来....重定位: 链接器通过把每个符号定义一个内存位置关联起来, 然后修改所有对这些符号引用, 使得他们指向这个内存位置. ?...动态链接 静态库存在下列两个问题: 当静态库更新时那么整个冲虚都需要重新进行链接 对于printf这种标准函数库, 如果每个程序都要有代码, 那么会极大浪费资源....他具有以下特点: 在给定文件系统中一个库只有一个文件, 所有引用该库可执行目标都共享这个文件, 他不会被复制到引用他可执行文件.

21730

Linux基础——gcc编译、静态库动态库(共享库)

优点: 寻址方便,速度快 库在链接时被打包到可执行文件,直接发布可执行程序即可以使用 缺点: 静态库代码被加载到可执行程序,因此体积过大 如果静态库函数发生改变,必须重新编译可执行程序 3、静态库制作使用...优点: 节省内存 易于更新,不用重新编译可执行程序,运行时自动加载 缺点: 延时绑定,速度略慢 3、动态库制作使用 测试代码目录结构静态库相同。...第一步:生成位置无关.o文件 gcc -fPIC *.c -I ...../include -c 参数-fPIC表示生成位置无关代码 第二步:创建动态库 gcc -shared -o libMyTest.so *.o 参数:-shared 制作动态库 -...+ -o 可执行文件gcc main.c -I include lib/libMyTest.so -o app (执行成功,已经指明了动态库路径) 如何解决第一种方法找不到链接库问题 使用命令

7.9K40

【图片+代码】:Linux 动态链接过程【重定位】底层原理

详细静态链接过程,请参考上一篇文章:【图片+代码】:GCC 链接过程【重定位】过程分析。 也就是说:符号重定位过程,是直接对可执行文件进行修改。...只有当所有需要被重定位符号被解决了之后,才能开始执行程序。 既然也是重定位静态链接过程一样:也需要把符号目标地址填写到代码段需要重定位地方。 矛盾:代码段不可写 问题来了!...a.c -o liba.so -lb -L./ $ gcc -m32 -fPIC main.c -o main -ldl -la -lb -L./ 有几点内容说明一下: -fPIC 参数意思是:生成位置无关代码...但是动态链接过程定位静态链接处理方式差别就大很多了,因为每个符号地址只有在运行时候才能知道它们地址。...,重新贴图如下: 因为编译动态库时,使用了代码位置无关参数(-fPIC),这里虚拟地址从0x0000_0000开始。

1.9K11

linux 什么是SO文件

-fPIC -g -c s.c -o libs.o ———————————————————————- -fPIC: -fPIC作用于编译阶段,告诉编译器产生位置无关代码(Position-Independent...Code),则产生代码,没有绝对地址,全部使用相对地址,故而代码可以被加载器加载到内存任意 位置,都可以正确执行。...这正是共享库所要求,共享库被加载时,在内存位置不是固定。 -g: 令 gcc 生成调试信息,该选项可以利用操作系统“原生格式(native format)”生成调试信息。...这个特性使得在Linux下,升级使得共享库程序和定位错误变得十分容易。   .../ts 关键就在LD_PRELOAD上了,这个路径指定so将在所有的so之前加载,并且符号会覆盖后面加载so文件符号。如果可执行文件权限不合适(SID),这个变量会被忽略。 执行:.

5.7K20

【图片+代码】:GCC 链接过程【重定位】过程分析

按照惯例,还是以一个简短示例代码作为载体,看一看GCC在链接过程,是如何根据目标文件(.o文件)来进行重定位,生成最终可执行文件。...在sub.c定义了一个全局变量和一个全局函数,然后在main.c中使用这个全局变量和全局函数。...代码如下: sub.c main.c 在一般开发过程,都是使用GCC工具,直接把这2个源文件编译得到可执行文件。...以上这两个编译过程是各自独立,虽然main.o中使用了两个符号(全局变量和全局函数),但是此时main.o并不知道这2个符号是在哪个文件定义。...再来看一下可执行文件main反汇编代码: 从黄色和红色矩形框可以看出,二进制指令地址值上面的分析是一致

65510
领券