重定位

ELF文件格式解析

核能气质少年 提交于 2020-03-26 09:36:47
copy from : https://blog.csdn.net/mergerly/article/details/94585901 1. ELF文件简介 首先,你需要知道的是所谓对象文件(Object files)有三个种类: 可重定位的对象文件(Relocatable file) 这是由汇编器汇编生成的 .o 文件。后面的链接器(link editor)拿一个或一些 Relocatable object files 作为输入,经链接处理后,生成一个可执行的对象文件 (Executable file) 或者一个可被共享的对象文件(Shared object file)。我们可以使用 ar 工具将众多的 .o Relocatable object files 归档(archive)成 .a 静态库文件。如何产生 Relocatable file,你应该很熟悉了,请参见我们相关的基本概念文章和JulWiki。另外,可以预先告诉大家的是我们的内核可加载模块 .ko 文件也是 Relocatable object file。 可执行的对象文件(Executable file) 这我们见的多了。文本编辑器vi、调式用的工具gdb、播放mp3歌曲的软件mplayer等等都是Executable object file。你应该已经知道,在我们的 Linux 系统里面,存在两种可执行的东西

从可执行文件中删除.reloc字节

落花浮王杯 提交于 2020-03-17 08:31:47
1、.reloc节区 EXE形式的PE文件中,“基址重定位表”项对运行没什么影响,将其删除后程序仍能正常运行(基址重定位表对DLL/SYS形式的文件来说几乎是必需的)。VC++中生成的PE文件的重定位节区名为.reloc,删除该节区后文件可正常运行,并且缩减了文件大小。.reloc节区一般位于所有节区的最后,可以使用PEView和Win Hex Editor来手动删除。 基址重定位表: 在PE文件中,基址重定位表一般放在一个单独的 “.reloc” 区,可以通过IMAGE_OPTIONAL_HEADER 中 的DataDirectory[5] 查看基址重定位表 的RVA。 在PEview中查看notepad.exe的基址重定位表地址。 基址重定位表的地址为RAV 10000。 1、删除.reloc节区头:先用PEView打开查看.reloc节区头信息: 可以看到.reloc节区头从文件偏移270开始,大小为28(270~297)。用Win Hex打开找到该区域,然后全部用0覆盖(Ctrl+L): 2、删除.reloc节区:文件中.reloc节区的起始偏移为C000,因此从C000开始一直使用Win Hex删除到文件末端所有数据即可(Del): 这样,.reloc节区即被物理删除。但由于尚未修改其他PE头信息,文件仍无法正常运行。因此需要修改相关PE头信息,使文件最终能够正常运行。

编译和链接——程序员的自我修养

半城伤御伤魂 提交于 2020-03-10 16:28:05
常用的开发环境如Visual Studio、Delphi,是 集成开发环境 ,在集成开发环境中,将编译链接合并到一起一步完成,其合并到一起的过程称为 构建 虽然集成开发环境及编译器提供的默认配置、编译与链接参数提供的功能足以强大,但其隐藏了软件运行背后的机制,可能会产生一些莫名其妙的错误 被隐藏的过程 编译过程可分解为四个步骤:预处理、编译、汇编、链接 预处理 如对一个main.c文件预处理 #-E:仅预处理 gcc -E main.c -o main.i #或 cpp main.c > main.i 预处理过程中处理源文件中以#开始的预编译指令,规则: 将“#define”删除并展开宏定义 处理所有条件预处理指令,如“#if”,"#endif","#ifdef","#elif","#else" “#include”,将被包含文件插入到预处理位置【递归进行】 删除所有注释://、/**/ 添加行号&文件名标识,用于编译时产生调试用的行号信息及出现错误/警告时的信息显示 保留“#pragma”编译器指令 在最后,main.i文件中所有的宏已经展开,后续过程中如果无法判断宏定义/头文件包含是否正确时可以来查看该文件 编译 将main.i文件进行词法分析、语法分析、语义分析、中间代码生成、目标代码生成和优化后产生的汇编代码文件【在编译原理课程中学习】 gcc -S main.i -o

HashMap-resize重定位

爷,独闯天下 提交于 2020-03-03 16:58:53
​常量 // 默认初始化容量 16 static final int DEFAULT_INITIAL_CAPACITY = 1 << 4 ; // 最大容量 static final int MAXIMUM_CAPACITY = 1 << 30 ; // 默认加载因子 static final float DEFAULT_LOAD_FACTOR = 0.75f ; // 链 转 tree 的 节点个数 下限阈值 static final int TREEIFY_THRESHOLD = 8 ; // tree 转 链 的 节点个数 上限阈值 static final int UNTREEIFY_THRESHOLD = 6 ; // 链 转 tree 时 存储数组table的容量下限阈值. table.length小于此值时 resize()扩容。 static final int MIN_TREEIFY_CAPACITY = 64 ; 变量 // Node存储数组,在resize方法中初始化或扩容. 长度一定是 2的次方! transient Node<K,V>[] table; // 内部类 EntrySet,值对缓存 transient Set<Map.Entry<K,V>> entrySet; // table中Node的数量 transient int size; //

编译器简介

只谈情不闲聊 提交于 2020-03-03 16:47:54
语言处理系统 高级语言->汇编语言->机器码->硬件 预处理器:将源程序的存放在不同文件中的多个模块聚合起来,并替换宏。 汇编器:将编译器形成的汇编语言程序输出转换成可重定位的机器码。 编译器 是一个程序,它可以将 高级编程语言编写的程序 翻译成目标语言(如机器语言)编写的程序。 解释器 也是一个程序,但它不是翻译,而是直接根据用户的输入来执行制定的操作。 java就是编译器和解释器(虚拟机)的结合,实现一次编译,到处运行。Javac 的编译,编译 Java 源码生成“.class”文件里面实际是字节码,而不是可以直接执行的机器码。Java通过字节码和 Java 虚拟机(JVM)这种跨平台的抽象,屏蔽了操作系统和硬件的细节,这也是实现“一次编译,到处执行”的基础。 链接器:大型程序会分成多部分编译,一个文件中的代码可能指向另一文件中的位置。链接器可以解决外部内存地址的问题。 加载器:把所有可执行文件放在内存中执行。 可重定位 程序内使用的是逻辑地址,在系统加载程序,给出物理地址时,才会把逻辑地址转换为物理地址,这就是可重定位。即将逻辑地址重新定位成物理地址。 静态重定位:即在程序装入内存的过程中完成,是指在程序开始运行前,程序中的各个地址有关的项均已完成重定位,地址变换通常是在装入时一次完成的,以后不再改变,故成为静态重定位。 动态重定位:它不是在程序装入内存时完成的

GCC -fPIC选项

℡╲_俬逩灬. 提交于 2020-02-26 08:18:56
我已经阅读了 GCC的代码生成约定选项 ,但无法理解“生成与位置无关的代码(PIC)”的作用。 请举例说明一下这是什么意思。 #1楼 进一步添加...... 每个进程都有相同的虚拟地址空间(如果通过在linux OS中使用标志来停止虚拟地址的随机化)(更多详细信息 仅为我自己禁用并重新启用地址空间布局随机化 ) 因此,如果它的一个exe没有共享链接(假设情景),那么我们总是可以给同一个asm指令提供相同的虚拟地址而不会有任何伤害。 但是当我们想要将共享对象链接到exe时,我们不确定分配给共享对象的起始地址,因为它将取决于共享对象链接的顺序。那么说,asm指令里面.so将始终有不同的虚拟地址取决于其链接的进程。 因此,一个进程可以将.so的起始地址作为0x45678910放在其自己的虚拟空间中,同时其他进程可以给出起始地址0x12131415,如果它们不使用相对寻址,则.so根本不起作用。 所以他们总是必须使用相对寻址模式,因此使用fpic选项。 #2楼 对已经发布的答案的一个小补充:未编译为位置无关的目标文件是可重定位的; 它们包含重定位表条目。 这些条目允许加载程序(将程序加载到内存中的代码位)重写绝对地址,以调整虚拟地址空间中的实际加载地址。 操作系统将尝试与链接到同一共享对象库的所有程序共享加载到内存中的“共享对象库”的单个副本。 由于代码地址空间(与数据空间的部分不同

《操作系统教程》第5版-Chapter4-存储管理

ⅰ亾dé卋堺 提交于 2020-02-12 02:24:45
存储管理 存储 分配 地址 映射 存储 保护 存储 共享 存储 扩充 存储器层次:寄存器,缓存,内存,磁盘,磁带 寄存器:速度最快最贵 **源程序运行的三个阶段: 编译 :生成目标代码 链接 静态链接 :装载前将目标模块与库函数链接装配成一个完整的可执行程序 动态链接 :程序装载时一边装载一边链接 运行时链接 :目标模块与库函数的链接推迟到执行时才进行 装载 :装入物理空间 绝对装载 :始终与内存地址相同 可重定位装载 :根据内存当前状况决定放入的物理位置。使用的地址为相对地址 动态运行时装载 :允许内存的程序换出到磁盘,适当时再换入内存。前后物理位置可不同。即允许进程的内存映像不同时候在不同位置 **重定位 : 逻辑地址变物理地址 静态地址重定位 动态地址重定位 使用两个控制寄存器:基址寄存器和限长寄存器 运行时链接地址重定位 连续存储管理: 固定分区 缺点: 必须使用覆盖技术 内存利用率不高 无法动态扩充 限制多道程序的道数 动态分区 可变分区分配算法: 最先适应 :未分配区表或链表中的空闲区按地址从小到大排列 下次适应 :上次扫描结束处顺序查找 最优适应 :满足要求的 最小分区 最坏适应 :总是挑 一个最大的空闲区 给作业使用 快速适应 :经常用到的长度的空闲区设立 单独的空闲区链表 管理的数据结构:已分配区表,未分配区表 空闲区管理办法:链表 内存不足处理技术 移动

裸机——重定位

自古美人都是妖i 提交于 2020-02-07 19:29:04
1.重定位: 就是用地址无关码,把地址有关码加载到正确物理地址上。 地址有关码就是使用地址有关的汇编命令的代码。 2.地址无关码与地址有关码   地址无关码是运行地址与连接地址无关,也可以正确运行。   地址有关吗是运行地址必须匹配链接地址才能运行。 3.连接地址与运行地址   链接地址,是用来指导链接器连接的,本身可能会以立即数形式出现在代码中。(下面会有事例)   运行地址,也是物理地址,是硬件设计时就决定了的。 4.为什么地址有关码必须要链接地址与运行地址匹配?   因为地址有关码使用了地址有关的汇编指令,如长跳转 ldr(后面会分析)。 5.链接地址的指定方式   (1)默认指定     gcc test.c -o test.c // 链接地址默认从 0 开始   (2)-Ttext直接指定     ld -o test.elf -Ttext 0x10 a.o b.o c.o // 从 0x10 开始   (3)使用连接脚本   SECTIONS{ . = 0xd0020010; .text : { start.o * (.text) } .data : { * (.data) } bss_start = .; .bss : { * (.bss) } bss_end = .; }    这时连接地址从 0xd0020010开始 6. 代码分析 .global _start

代码重定位和位置无关码——运行于nor flash

久未见 提交于 2020-02-07 19:28:14
通过前面的学习,我们知道,把可执行程序从一个位置复制到另一个位置的过程叫做重定位。 现在有两种方式,第一种是只重定位data段到内存(sdram),为什么需要重定位?因为有些flash的写操作,不是简单地内存访问,通常我们使用sdram这个介质作为程序运行的载体。但是只重定位data段这种方式存在弊端。第一,我们的调试工具通常不支持这种分体形式(比如我们的之前的代码在0地址开始存放text和rodata段,而在间隔很远处sdram 0x30000000存放data段,这就是分体的形式)的代码;第二,这种分体方式需要能够直接运行程序的flash比如nor flash才可以工作,但是有些板子根本连nor flash都没有,那么只能通过第二种方式进行开发了。 第二种方式是把整个程序都复制到内存(sdram),这种方式所有数据都是紧挨着的,以后我们都使用这种方式。 现在思考一个问题,关于第二种方式,我们的bin文件是由连接脚本指定了运行地址为sdram(0x30000000)的,但是这个bin文件我们烧写在nor flash,是从0地址开始运行的,那么在nor flash上的代码就需要把整个bin文件拷贝到sdram中去,这就是重定位, 但这就要求我们必须做到,在重定位之前的代码必须是位置无关码。 (连接脚本指定我们程序的运行地址为0x30000000,为什么我们的在nor

操作系统5——存储器管理

旧巷老猫 提交于 2020-02-03 02:27:01
存储器管理 目录 存储器管理 1、程序的装入与链接 (1)程序的装入 (2)程序的连接 2、连续分配存储管理方式 (1)单一连续分配 (2)固定分区分配 (3)动态分区分配 (4)可重定位分区分配 (5)对换 3、分页和分段方式及其概述 (1)为什么要用分页和分段方式? (2)分段与分页的去区别 4、基本分页存储管理方式 (1)页面与页表 (2)页表 (3)地址变换 (4)地址变换机构 (5)具有块表的地址变换机构 (6)两级页表 (7)反置页表 5、基本分段存储管理方式 (1)分段与分页的区别: (2)分段的基本原理 (3)段表 (4)段表访问数据的过程 6、基本段页式存储管理方式 本章知识点流程图: 层次越高,越靠近CPU,访问速度越快,价格越高。 内存掉电之后信息不保存,除非已经写入到外存中。 1、程序的装入与链接 (1)程序的装入 多道程序环境下,程序要运行必须为之创建进程,而创建进程的第一件事就是分配内存。 将一个装入模块装入内存(第三步开始)时,有三种装入方式: 重定位: 把在装入时对目标程序中指令和数据的地址修改过程称为重定位。 (2)程序的连接 2、连续分配存储管理方式 连续分配方式为一个用户程序分配一个连续的内存空间 连续分配有以下几种: (1)单一连续分配 即将内存分为 系统区和用户区 ,整个内存的用户空间由该程序独占。 优点:易于管理 缺点