临夏市| 乃东| 辉县| 常熟| 兴安| 山东| 祁连| 无为| 盐源| 察哈尔右翼中旗| 泰兴| 台江| 高碑店| 汕头| 斗门| 嘉善| 阳信| 阜新市| 昂仁| 射阳| 宣汉| 华阴| 岢岚| 灵璧| 奉新| 峰峰矿| 岳普湖| 乌拉特中旗| 江苏| 衢江| 峨眉山| 深州| 顺义| 黄梅| 玛纳斯| 黄岛| 防城区| 钓鱼岛| 高安| 江油| 巢湖| 临邑| 沙湾| 榆林| 东乡| 兖州| 旬阳| 娄烦| 盐亭| 米易| 长治县| 新乐| 浪卡子| 德清| 玉林| 永州| 兴业| 任丘| 灯塔| 周村| 海沧| 榆树| 青阳| 巨鹿| 梨树| 保亭| 合川| 贵溪| 富拉尔基| 景宁| 灵寿| 泽州| 闽清| 永新| 天等| 新民| 霍山| 连州| 内黄| 沙坪坝| 甘孜| 偃师| 清流| 隆化| 永泰| 句容| 万宁| 宁蒗| 石门| 三亚| 金湖| 道真| 永年| 卫辉| 石景山| 玛沁| 富县| 南漳| 乌伊岭| 沈阳| 永靖| 疏附| 新津| 华坪| 江阴| 驻马店| 彭泽| 凤台| 歙县| 佛冈| 乾安| 献县| 宣汉| 诸城| 猇亭| 涉县| 虞城| 麻江| 五原| 武安| 溧水| 海沧| 垣曲| 富锦| 惠州| 兴化| 南投| 稻城| 新和| 赫章| 广东| 万盛| 保德| 华蓥| 土默特左旗| 且末| 泸县| 荔波| 宣恩| 博湖| 会理| 福鼎| 枝江| 盘县| 修文| 珠穆朗玛峰| 安图| 通渭| 马边| 荣昌| 富蕴| 岳普湖| 寿县| 安西| 基隆| 盘山| 沙湾| 望都| 扎鲁特旗| 临海| 开封市| 元阳| 武鸣| 藤县| 友好| 朗县| 德化| 盘县| 灌云| 宁德| 惠安| 南汇| 四方台| 永年| 商水| 和龙| 武宁| 会昌| 鱼台| 清水河| 丹阳| 潼南| 佳县| 即墨| 繁峙| 玉树| 丹东| 铜鼓| 策勒| 连山| 濮阳| 新龙| 大连| 津南| 丰县| 八一镇| 邯郸| 资兴| 怀远| 万全| 拉萨| 左权| 罗山| 四川| 玉田| 班戈| 岱岳| 长治市| 兴义| 三门峡| 萨嘎| 琼山| 都江堰| 永昌| 惠来| 铅山| 邢台| 保山| 青川| 金佛山| 玛多| 勐腊| 连州| 始兴| 和龙| 博兴| 潜山| 鄂托克前旗| 南江| 郓城| 白城| 武定| 舞阳| 澳门金沙注册送38 游艇会娱乐平台 威尼斯注册网站 新濠天地国际娱乐城 澳门美高梅娱乐场网站 时时彩 532-36总管 澳门赌城网址亚洲城 澳门皇冠赌场 财神娱乐平台 ag电子竞技俱乐部 利来老牌国际娱乐 真人博狗网 葡京网投 网站 威尼斯在线网投 威尼斯网上 永利网上娱乐 五大联赛开赛时间 ewin棋牌官网首页 足球现金网注册 威廉希尔注册送18元 即时比分90 新2备用网址 威尼斯官网注册 现场轮盘 澳博官网 N60.com|葡京平台|威尼斯开户|澳门指定官网APP下载 日博365备用网址 威尼斯人线上娱乐场 12bet网址 澳门威尼斯注册送300 明升娱乐网 澳门威尼斯娱乐城中文版 澳门皇冠赌城网址 威尼斯在线网址

澳门威尼斯人彩票登录:

2018-12-14 22:40 来源:京华网

  澳门威尼斯人彩票登录:

  威尼斯投注站"在我来到一汽丰田的半年多时间里,最先了解到的是小型车战略和年轻化战略,这两项工作是一汽丰田这几年工作的重心,未来还将继续下去。个位、十位、百位,电商谷已经聚集了超过100家入园企业,完成了基本量的积累。

但到目前为止,这个所谓的一体化网络仍处于构想阶段,且不说技术和产品的成熟度尚需极大的提升。这些区域里有区域限制,回家上不了牌,厂家那边不会给你打出来一个信息表。

  车顶行李架配合横杆使用可以放行李箱或自行车,拓展载物能力。【发明的前言】要把汽车发明的发明工作抓好,这是陈光祖老给我二年机工出版的汽车自主研发系列丛书作的序言。

  创业维艰贵在起步,到底什么样的项目能够创业成功,在创业的过程中我们需要注意什么样的问题,如何突破创业的瓶颈,步入发展的平稳期,这都是创业者们难以言喻的伤痛。2018年相对增速放缓了,您如何看待?或者请您为我们讲一下这125家的战略规划是怎么考虑的?林恺音:首先,虽然我不是经销商网络规划团队的,但可以和您分享的是,您可能觉得60、100、125,看起来好像在2018年我们的增势是趋缓的。

某次参观儿童画展,年届80的说出了上面这番充满颠覆意味的话。

  凤凰网汽车评论继2017年销量摸高万辆,同比增长%后,2018刚刚开局,摆在汽车集团全球高级副、亚太区总裁兼CEO袁小林和沃尔沃中国团队面前的中国业务发展路径看上去选择多多,但似乎哪一条又都充满挑战和困难。

  5月26日,由中国房地产业协会、中国房地产测评中心联合开展的“2016中国房地产上市公司测评成果发布会暨上市房企高峰论坛”在香港举行,《2016中国房地产上市公司测评研究报告》也同期发布。中控锁集成在主驾门板上,标识清晰易操作。

  作为全球首款三座版总裁级专项豪华轿车,S90荣誉版是目前细分市场独一无二的产品类型,它不仅对传统豪华车内部空间进行了颠覆性设计和再造,也是豪华车市场产品理念的一次大胆创新。

  ”左晖在讲话中表示,“中国的城镇化率,实际上是高度的集中,到今天为止,我们城市人口主要还是集中在东部沿海的大型的城市里边”。在全民皆创业的时代,90后创业者被称为最“生猛”的一批,他们颇具“霸蛮”精神和创新思维,坚韧而不失灵活。

  出境携带物品规定如旅客携带价格昂贵的手提电脑、摄影摄像器材、手表等出境并计划再次携带入境泰国必须向海关申报。

  现金网评级二是在产业的核心资源控制上,上下游产业链开始形成自己的定位,核心资源不断向引领创新的企业高度聚集。

  根据特鲁利亚网络房产公司的数据,在美国非亚裔人口占多数的社区,在2017年挂出的所有房源中,房源价格最后一位数字除零之外是8的仅有4%,而在亚裔人口占多数的社区,相应的比例为25%——而在2012年时还只有5%。凤凰汽车评论在俄罗斯车市始终跌跌撞撞,浑然不觉,好似刚入俄罗斯的新丁,风波不断,笔者早前就长城与其俄罗斯官方经销商伊利托公司作出过评论,长城与伊利托龌蹉不断,早就貌合神离,但长城还时不常出来辟谣,称其与伊利托合作还将持续,并无中断合约的可能性。

  拉菲2娱乐 和记娱乐平台 永利官方网站

  澳门威尼斯人彩票登录:

 
责编:
  忘记密码   免费注册 查看新帖 |

ChinaUnix.net

  平台 论坛 博客 文库 频道自动化运维 虚拟化 储存备份 C/C++ PHP MySQL 嵌入式 Linux系统
12下一页
最近访问板块 发新帖
查看: 47915 | 回复: 11
打印 上一主题 下一主题

[内核入门] 通过elf各种重定位类型,理解不同场合的链接过程 [复制链接]

葡京网站大全 值得说明的是,与一般4S店常见的燃油车最多30分钟试驾不同,腾势还给杭州意向客户予意向客户2—3天的全天侯试驾。

大富大贵

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2018-12-14 21:00:1415-16赛季CBA联赛之同曦
日期:2018-12-14 14:26:1515-16赛季CBA联赛之佛山
日期:2018-12-14 14:19:2615-16赛季CBA联赛之青岛
日期:2018-12-14 16:49:1115-16赛季CBA联赛之广夏
日期:2018-12-14 09:13:1215-16赛季CBA联赛之广东
日期:2018-12-14 22:34:3615-16赛季CBA联赛之江苏
日期:2018-12-14 12:10:2115-16赛季CBA联赛之上海
日期:2018-12-14 03:49:2215-16赛季CBA联赛之广东
日期:2018-12-14 04:09:12
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2018-12-14 18:12 |只看该作者 |倒序浏览
本帖最后由 _nosay 于 2018-12-14 18:12 编辑

    最近为了理解elf格式规范中的各种重定位类型,晕了。跑出去玩了几天,终于为每种重定位类型,找到了对应的case。elf规范总共定义了10种重定位类型,之所以需要这么多种不同类型的重定位信息,是由于如下原因:
    ① 硬件对变量和函数的寻址方式不同,寻找变量要求绝对地址,寻找函数要求相对地址;
    ② 不同场合下,程序员对最终可执行文件或动态库的期望不一样(位置无关、动态库函数重定位延迟),从而加了不同的编译选项(比如-fPIC、-Ox等);
    ③ C语言的static、extern特性,导致不同特性的变量或函数地址可以被确定的时机不同;
    ④ 内核加载可执行文件,约定从固定地址0x80480000开始,但加载.so的起始地址无法约定(一个可执行程序只有一个main(),但可能依赖多个动态库)。
    疑问:那整个系统中,可执行程序也不只一个呀,都约定从相同的起始地址加载,不会冲突吗?
    因为每个进程访问的都是虚拟地址,由内核在背后负责将不同进程的相同虚拟地址,映射到不同的实际物理地址(属于内核范畴,不理解没关系,不影响对本贴关键内容的理解)。

  • 静态链接/动态链接简单理解
    .c文件中的代码最终被执行,需要经历如下过程:
    ① 编译:词法解析 → 语法解析 → 静态链接
    ② 加载:加载可执行文件 → 可执行文件启动或执行时,加载依赖的.so文件 → 动态链接

    本帖仅关注静态链接、动态链接过程,静态链接与动态链接区别:
    ① 静态链接处于将1个或多个.o文件“拼凑”成可执行文件阶段,处理对象是文件,文件中的代码区没有只读属性,链接过程中可以直接修改;动态链接处于可执行文件或.so文件已被加载到内存阶段,处理对象是内存,内核为代码区所在的内存区域设置了只读属性,如果代码区有内容需要重定位,需要在编译或静态链接时,事先准备一个间接位置(加载到内存不会被设置只读属性),动态链接是对该间接位置进行重定位。
    ② 通过下图可以看出,静态链接将.o的各个节“撕开”,属性相同的节“拼凑”为可执行文件的段;动态链接是将“整个”.so文件安排在与可执行文件镜像相独立的位置(图中最简化了.o、.so、可执行文件的内容,用于说明静态链接与动态链接的区别,它们的内容远远不止.data、.text)。
    另外,.so文件还涉及到位置无关(-fPIC)、延迟加载的选择(应该是跟优化级别有关),接下来即将详细总结。
   
    编译阶段,.o文件的全局变量位置不确定,因为这时无法确定还有其它哪些.o文件,以及链接器将来会按什么顺序“排列”这些.o文件(见静态链接示意图),链接阶段,.so文件的全局变量位置也不确定,是因为这时不知道.so文件将来被加载到进程空间的什么位置(见动态链接示意图)。既然不能确定,只能瞎写,但计算机世界一是一、二是二,瞎写完一定要留下一个“交待”(重定位项),等将来时机成熟时,再补上正确的值。

  • R_386_32
   
    R_386_32计算公式:S+A。
    S:对于.o文件,表示全局变量被链接器安排的位置或其所在xx节的起始位置;对于.so文件,表示全局变量被加载到的虚拟地址。
    A:被重定位处的原始值(4字节,由重定位项offset指向)。

    晕了,没关系,先看具体的case(看完R_386_32,再理解其它重定位类型就有感觉了):
    6处的指令“a1 00 00 00 00”,由于此时无法预测g1经过加载后的地址,就先写一个假地址0,16处指令“a1 04 00 00 00”,由于此时无法预测g3经过链接后的位置,就先写一个假地址4。但0、4都不是编译器随意写上的,因为随后做重定位计算时要将它们作为A值。
    另外,g4是未初始化的static全局变量,所以被“放在”.bss段,所以重定位项指定用.bss节位置作为S值(“放在”加了引号,是因为.bss在文件中不占空间,只有一个结构用于指示加载到内存时,它应该处于的位置以及大小,比如一万个0,在程序要执行时,才需要为这些0分配内存为它们所代表的变量占据位置,而在文件中不需要分配一万个字节,它只需要能提供一个简短的信息,提供加载时能正确的分配一万个字节并填充为0即可)。
   

    为了验证图中提出的问题,继续分析链接该.o文件得到的.so文件:
   
    可以看出,对.o留下的不同类型重定位项,处理结果不一样,暂时只关注g1、g3,链接器(ld)在.so文件中为g1仍然留了一条R_386_32重定位项,而为g3留了一条R_386_RELATIVE重定位项,再次处理这两条重定位项,就已经是加载到内存后由动态链接器完成了(ld-linux.so.2),计算公式中的成员含义也会改变,比如S表示符号加载到的虚拟地址。
    不是说内核会为代码对应的内存区域设置只读属性么,加载到内存后还能修改的了吗?
    准确的说,内核将代码加载到内存,需要做很多处理,设置只读只是其中一个,并且在完成重定位之后:“加载→重定位→设置只读→执行”。


    上述这种不加-fPIC选项编译得到的.so文件,只是单纯将一个完整的二进制文件分隔成可执行文件和.so文件,将重定位操作延迟到加载时了,并没有发挥.so关键设计意图:.so共享。
    因为各个进程的虚拟空间使用情况不一样,会导致这种情况:进程A的100地址空闲,并将libc.so加载到100开始的虚拟空间,将.so镜像中各个重定位处依据100地址计算重定位值,进程B的200地址空闲,如果直接将内存中已经存在的libc.so镜像映射到200位置,之前按100地址修改的重定位处,就不满足进程B的要求了,所以只能再加载一份libc.so并映射到自己的虚拟空间(稍后说明的位置无关就是为了解决这个问题)。

  • R_386_PC32
   
    R_386_PC32计算公式:S+A-P。
    S:对于.o文件,表示链接阶段全局变量被安排的位置或其所在xx节起始位置;
         对于.so文件,表示全局变量被加载到的虚拟地址。
    A:被重定位处的原始值(4字节,由重定位项offset指向)。
    P:重定位项中的offset值。对于.o、.so文件,表示被重定位处在.o、.so文件中的偏移;对于可执行文件,表示被重定位处被加载到的虚拟地址。

    10处的指令“e8 fc ff ff ff”,由于此时无法预测f1()经过加载后的地址,就先写一个假地址-4,15处指令“e8 fc ff ff ff”,由于此时无法预测f2()经过链接后的位置,就先写一个假地址-4。
    -4-P解释:首先P代表被重定位处位置(对于10处指令,P=11,对于15处指令,P=16),则P+4分别代表下一条指令位置15、1a(运行时就是下一条指令的虚拟地址),而硬件在处理机器码e8(call指令)时,不是将紧接着后面的4字节直接作为跳转地址,而是要加上下一条指令的地址,所以重定位时只好事先-(P+4)。
    对比说明R_386_32的case,g1的A值为0,g3的A值为4,而这里两条重定位项的A值都是-4,因为它们的差距体现在这两处,P值本身就不同。
   
    为什么f1()、f2()都有重定位项,fun()没有?
    重定位项的生成是根据调用,而不是定义。

    另外,有了对R_386_32的理解基础,可以想象将该.o文件链接成.so文件,链接器会如何处理重定位项,并动手验证一下(注意:有些电脑编译.so文件必须加-fPIC选项,一方面可能跟系统是32/64位有关,另一方面可能跟编译器版本有关)
   
    非static函数fun()调用static函数f3(),为什么直接使用相对偏移即可
    当前.so加载位置确定,f3()加载位置就确定了,不能确定fun()位置(同链接阶段无法通过R_386_32重定位类型确定g1位置一个道理),那么此时计算的相对位置不也失效了吗?

  • R_386_GOT32
   
    R_386_GOT32计算公式:G+A-P。
    G:链接阶段生成的GOT表位置。
    A:被重定位处的原始值(4字节,由重定位项offset指向)。
    P:重定位项中的offset值,表示被重定位处在.o文件中的偏移。

    对于G的解释,提到GOT表,什么是GOT表?
    通过R_386_32、R_386_PC32的说明可知,不加-fPIC选项编译得到的.so文件,并没有给计算机带来什么实惠,因为它的代码根据前一个进程对它的加载地址完成重定位后,之后其它进程不能直接将它映射到自己的虚拟空间使用,因为它们对重定位计算的基准不一样。
    got表正是用于将需要重定位的内容剥离出来,从大范围(整个.so的代码区域)汇聚到小范围(.got表),即将加载地址对代码区域的影响,转移到对.got表的影响。所以说,.so共享并不是完全的共享,各个进程仍然有一个.got表的副本,而.got表往往很小。

    主要利用两个技巧:
    ① 在程序编写阶段,虽然不知道以下两条指令真正执行后ebx寄存会得到什么值,但能确定它的含义是当时eip寄存器的值,那么跟这条指令相对位置固定的运行时地址,在逻辑上都能在编译阶段“获知”:
        call L1
        L1: pop ebx
    ② 那么,在.so文件中相对于指令区域确定位置生成一个.got表,.so被执行时.got表的绝对地址也是可以“获知”的。这样,就可以用.got表项的绝对地址,覆盖原本在指令区域的重定位处,而.got表中存放将来才能确定的最终重定位的符号地址。

     一份代码区域,多份.got表:
   

    理解mmap()函数,有助于更深入理解上图,在此只大概说明(涉及内核的内存管理和文件系统):
   
    ① 假设进程A先将libc.so映射到自己的一块虚拟空间,当首次访问这块区间时发生缺页异常,分配物理页面并读入内容,然后建立映射。接着,进程B也将libc.so映射到自己的一块虚拟空间,首次访问这块区间仍然会发生缺页异常,但与其建立映射的物理页面,就不用再重新分配读入了。从而,物理内存只需要一份.so的内容,就可以供A、B两个进程使用。
    ② 思维敏锐的可能会发现一个问题:.so文件中如果有全局变量,被多个进程共享,不是会相互干扰吗?
        COW(写时复制):内核为虚拟页面、物理页面都设置了一些属性,比如如果对某个虚拟页面进行写操作,就重新分配一个物理页面,复制内容并重新建立映射(为.so数据区分配的页面,就具有这样的属性)。
    ③ 各个进程将.so文件映射到自己的虚拟空间,数据区、代码区的相对位置,仍然保持和刚链接过后一致,所以在代码区向.got的重定位计算仍然有效,只不过动态链接器为不同进程向.got表初始化全局变量的地址时,要向.got表进行写操作,导致每个进程有一个.got副本。

    编译说明R_386_32时使用的case代码,加上-fPIC选项,就能看到编译器为g1、g2变量在.o文件中生成了R_386_GOT32重定位项以及为g3、g4变量在.o文件中生成了R_386_GOTOFF重定位项,稍后说明)
   
    6、b处两条指令执行后,ecx寄存器会得到.got表加载地址,为什么?
    ① 前面已经说明过R_386_PC32重定位类型,7处经过这种类型重定位后,执行时会跳转到__x86.get_pc_thunk.cx,得到b处指令的加载地址(CPU没有提供直接获取当前ip的指令,所以利用call会将返回地址压栈的特点);
    ② R_386_GOTPC,提示链接器创建.got表,并修改d处的值,保证执行时用它加ecx寄存器可以得到.got表地址(可以通过R_386_GLOB_DAT类型分析过程,编译得到的.so验证):
        通过①可能确定,执行过6处指令后ecx得到的b处指令的加载地址,拿什么和它相加可以得到.got表位置呢?
        +A:从ecx所指位置往后推2字节(机器码“81 c1”),就到了被重定位处(重定位项中的offset/规范文档中的P);
        +G-P:再向后推.got表相对此处的距离,就到.got表了。
        注意:$0x2只是作为链接器计算重定位值的A,在执行时就被G-P-2覆盖了,不要疑惑为什么要从ecx减2,它的含义根本就不是减数。

  • R_386_GLOB_DAT
   
    R_386_GLOB_DAT计算公式:S。

    对比R_386_32、R_386_GOT32,就是在编译.o文件时,加了-fPIC选项,R_386_GOT32重定位类型就是希望将重定位处从代码区域转移到.got表,链接阶段创建.got表,完成代码区域重定位,添加对.got表项的重定位项(转移≠消除)。
    将说明R_386_GOT32时编译得到的.o文件,链接成.so文件:
   
    ① 532、537处(对应.o文件中6、b处)指令,确实可以将.got表位置计算到ecx寄存器中(不过是结束位置,后面指令取.got表项地址时,用的是负偏移,可能不同编译器不一样吧,用开始位置、结束位置计算,道理是一样的)
    ② g1、g2的重定位类型变成R_386_GLOB_DAT,它是用于告诉动态链接器,在确定g1、g2地址时,放到它们的.got表项里(0x1fe8、0x1ff4)。

  • R_386_PLT32
   
    R_386_PLT32计算公式:L+A-P

    与R_386_GOT32、R_386_GLOB_DAT道理相似,R_386_PLT32、R_386_JUMP_SLOT也是为支持PIC定义的重定位类型,前者面向的是全局变量,后者面向函数。
    不过由于为了支持“动态库函数重定位延迟”,在.got.plt表跳转前,还多了一层.plt表跳转,.plt表里是一些链接器为重定位函数生成的跳转代码片段,计算公式中的L表示为重定位函数生成的跳转代码片段在.so文件中的位置(可以通过R_386_JUMP_SLOT类型分析过程,编译得到的.so验证)。
   

  • R_386_JUMP_SLOT
   
    R_386_JUMP_SLOT计算公式:S

    相比链接器对R_386_GLOB_DAT重定位项的处理,R_386_JUMP_SLOT重定位项的处理过程更复杂,不光在.so文件中创建.got.plt表,还为f1()、f2()对应生成了f1@pltf2@plt代码片段,并将代码中对f1()、f2()的调用,分别替换成对f1@pltf2@plt的调用,同时对f1()、f2()的重定位类型变成了R_386_JUMP_SLOT,这个重定位类型不会在.so文件一加载时就被动态链接器处理,而是调用f1()、f2()的指令首次被执行时,才进行重定位操作(比如我喜欢学习内核,但我目前的工作跟内核并没有多大关系,聪明的人都是等工作需要的时候,再学)。

    不防看一下f1()首次被调用的过程:
    ① 562地址处的指令执行后,ebx寄存器指向.got.plt表开始位置0x2000;
    ② 568、56d处原本对f1()、f2()的调用,被替换为对f1@pltf2@plt的调用:
        <f1@plt>:
        410: jmp  *0x18(%ebx)    ;0x2018,f1()在.got.plt表中占据的表项位置,表项内容初始值为0x416,即首次执行这条指令时,相当于“jmp 0x416”
        416: push $0x18
        41b: jmp  3d0 <_init+0x2c>

        有点奇怪,首次从410→416干嘛要特意绕个圈?
        这个圈只会在第一次执行f1@plt时才会绕,当416、41b处指令调用动态链接器,将f1()地址填到.got.plt表项0x2018后,以后再执行410处指令时,就相当于“jmp f1”了。即:
        第一次执行f1@plt:410 → 416、41b → f1()
        第二次执行f1@plt:410 → f1()
    而且链接器将所有调用f1()的地方都替换成调用f1@plt了,所以410→416这个圈,只会绕一次,不过即使这样,每次调用f1(),也要先“call <fl@plt>”,所以延迟加载虽然“聪明”,但有得也有失。
   

  • R_386_COPY
   
    R_386_COPY计算公式:冇

    初始化的全局变量和未初始化全局变量,被安排的位置是不同的,分别在.data、.bss,那么,如果某个模块通过extern引用了另外一个模块中定义的全局变量,编译阶段是不知道这个变量是否被初始化了,因为它根本看不到其它.c文件,所以就暂时把该变量安排在.bss,等链接阶段得知它如果有初始值的话,就依据此重定位项,修改一下.bss相应位置的值。
   

  • R_386_RELATIVE
   
    R_386_RELATIVE计算公式:B+A
    B:.so文件加载地址。

    分析R_386_32类型时,已经说明过R_386_RELATIVE,静态变量位置在链接阶段可以确定在.so文件中的偏移,那么计算它的加载地址,自然是加上.so文件的加载地址B就可以了。

  • R_386_GOTOFF
   
    R_386_GOTOFF计算公式:S+A-GOT

    编译说明R_386_32时使用的case代码,加上-fPIC选项,就能看到编译器为g3、g4变量在.o文件中生成了R_386_GOTOFF重定位项(在分析R_386_GOT32类型时提到过,基于静态变量相对于.so文件加载地址,距离固定,利用GOT表位置进行重定位)
   

  • R_386_GOTPC
   
    R_386_GOTPC计算公式:GOT+A-P

    分析R_386_GOT32类型时,已经说明过R_386_GOTPC,它与R_386_32类似,只不过一个用于重定位变量位置,一个用于重定位.got表位置。

  • 总结
    把对各种重定位类型的理解放在同一张表格对比,它们之间的区别就暴露的赤裸裸,再也不扑朔迷离了:
  (为了xx,需要在xx阶段xx,前一阶段提供准备,后一阶段完成计算,或变换为另一种计算方式)
   

  • 参考
      http://www.cnblogs.com.fenshop.com.cn/catch/p/3857964.html
      http://blog.csdn.net.fenshop.com.cn/stonesharp/article/details/12943963
      http://blog.csdn.net.fenshop.com.cn/wuhui_gdnt/article/details/51035557
      http://blog.csdn.net.fenshop.com.cn/wuhui_gdnt/article/details/51094732
      http://blog.csdn.net.fenshop.com.cn/wuhui_gdnt/article/details/51160465
      http://jzhihui.iteye.com.fenshop.com.cn/blog/1447570
      http://blog.csdn.net.fenshop.com.cn/yuyin86/article/details/10239479

1-2018-12-14-TN05.ELF.Format.Summary.pdf

852.96 KB, 下载次数: 174

评分

参与人数 1信誉积分 +10 收起 理由
nswcfd + 10 很给力!

查看全部评分

论坛徽章:
20
程序设计版块每日发帖之星
日期:2018-12-14 06:20:00程序设计版块每日发帖之星
日期:2018-12-14 06:20:00程序设计版块每日发帖之星
日期:2018-12-14 06:20:00每日论坛发贴之星
日期:2018-12-14 06:20:00黑曼巴
日期:2018-12-14 16:00:3215-16赛季CBA联赛之江苏
日期:2018-12-14 11:05:5615-16赛季CBA联赛之上海
日期:2018-12-14 18:12:5015-16赛季CBA联赛之青岛
日期:2018-12-14 17:32:0515-16赛季CBA联赛之吉林
日期:2018-12-14 10:02:16程序设计版块每日发帖之星
日期:2018-12-14 06:20:0015-16赛季CBA联赛之江苏
日期:2018-12-14 18:37:512015亚冠之萨济拖拉机
日期:2018-12-14 12:21:08
2 [报告]
发表于 2018-12-14 14:29 |只看该作者
下子写帖子之前可以先把PS1修改一下,这样就不用给每张图打马赛克了

也可以使用script命令来记录程序的输出。或者使用screen/tmux等终端软件的“截屏”功能。

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2018-12-14 21:00:1415-16赛季CBA联赛之同曦
日期:2018-12-14 14:26:1515-16赛季CBA联赛之佛山
日期:2018-12-14 14:19:2615-16赛季CBA联赛之青岛
日期:2018-12-14 16:49:1115-16赛季CBA联赛之广夏
日期:2018-12-14 09:13:1215-16赛季CBA联赛之广东
日期:2018-12-14 22:34:3615-16赛季CBA联赛之江苏
日期:2018-12-14 12:10:2115-16赛季CBA联赛之上海
日期:2018-12-14 03:49:2215-16赛季CBA联赛之广东
日期:2018-12-14 04:09:12
3 [报告]
发表于 2018-12-14 15:10 |只看该作者
回复 2# nswcfd

嗯嗯,我是远程别人电脑的,改成啥他不会怪我呢

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2018-12-14 21:00:1415-16赛季CBA联赛之同曦
日期:2018-12-14 14:26:1515-16赛季CBA联赛之佛山
日期:2018-12-14 14:19:2615-16赛季CBA联赛之青岛
日期:2018-12-14 16:49:1115-16赛季CBA联赛之广夏
日期:2018-12-14 09:13:1215-16赛季CBA联赛之广东
日期:2018-12-14 22:34:3615-16赛季CBA联赛之江苏
日期:2018-12-14 12:10:2115-16赛季CBA联赛之上海
日期:2018-12-14 03:49:2215-16赛季CBA联赛之广东
日期:2018-12-14 04:09:12
4 [报告]
发表于 2018-12-14 19:04 |只看该作者

论坛徽章:
20
程序设计版块每日发帖之星
日期:2018-12-14 06:20:00程序设计版块每日发帖之星
日期:2018-12-14 06:20:00程序设计版块每日发帖之星
日期:2018-12-14 06:20:00每日论坛发贴之星
日期:2018-12-14 06:20:00黑曼巴
日期:2018-12-14 16:00:3215-16赛季CBA联赛之江苏
日期:2018-12-14 11:05:5615-16赛季CBA联赛之上海
日期:2018-12-14 18:12:5015-16赛季CBA联赛之青岛
日期:2018-12-14 17:32:0515-16赛季CBA联赛之吉林
日期:2018-12-14 10:02:16程序设计版块每日发帖之星
日期:2018-12-14 06:20:0015-16赛季CBA联赛之江苏
日期:2018-12-14 18:37:512015亚冠之萨济拖拉机
日期:2018-12-14 12:21:08
5 [报告]
发表于 2018-12-14 11:50 |只看该作者
phrack.org, very good!

论坛徽章:
6
2015年辞旧岁徽章
日期:2018-12-14 16:13:092015年迎新春徽章
日期:2018-12-14 16:13:092015小元宵徽章
日期:2018-12-14 15:58:1815-16赛季CBA联赛之浙江
日期:2018-12-14 14:38:4115-16赛季CBA联赛之新疆
日期:2018-12-14 18:38:06
6 [报告]
发表于 2018-12-14 21:43 |只看该作者
不同的软硬件平台会有不同的重定位类型,基本的就两种:绝对定位与相对定位。如x64平台上有64位的绝对定位与32位的相对定位

论坛徽章:
0
7 [报告]
发表于 2018-12-14 00:23 |只看该作者
这篇真牛~之前研究都不懂,看这篇就懂了

论坛徽章:
0
8 [报告]
发表于 2018-12-14 22:04 |只看该作者
good summary, thanks!

论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2018-12-14 21:00:1415-16赛季CBA联赛之同曦
日期:2018-12-14 14:26:1515-16赛季CBA联赛之佛山
日期:2018-12-14 14:19:2615-16赛季CBA联赛之青岛
日期:2018-12-14 16:49:1115-16赛季CBA联赛之广夏
日期:2018-12-14 09:13:1215-16赛季CBA联赛之广东
日期:2018-12-14 22:34:3615-16赛季CBA联赛之江苏
日期:2018-12-14 12:10:2115-16赛季CBA联赛之上海
日期:2018-12-14 03:49:2215-16赛季CBA联赛之广东
日期:2018-12-14 04:09:12
9 [报告]
发表于 2018-12-14 16:29 |只看该作者
回复 1# _nosay

https://stackoverflow.com/questi ... bjdump-symbol-table



论坛徽章:
13
15-16赛季CBA联赛之八一
日期:2018-12-14 21:00:1415-16赛季CBA联赛之同曦
日期:2018-12-14 14:26:1515-16赛季CBA联赛之佛山
日期:2018-12-14 14:19:2615-16赛季CBA联赛之青岛
日期:2018-12-14 16:49:1115-16赛季CBA联赛之广夏
日期:2018-12-14 09:13:1215-16赛季CBA联赛之广东
日期:2018-12-14 22:34:3615-16赛季CBA联赛之江苏
日期:2018-12-14 12:10:2115-16赛季CBA联赛之上海
日期:2018-12-14 03:49:2215-16赛季CBA联赛之广东
日期:2018-12-14 04:09:12
10 [报告]
发表于 2018-12-14 01:22 |只看该作者
关于R_386_PC32,帖子里提了一个问题,表示当时我对这种重定位类型的理解有错误。
f2()的调用处,需要对应一个R_386_PC32重定位项,这是很容易理解的,因为它是extern的,链接的时候才知道f2()指令块的开始位置,相应的,call指令中的偏移值,也必须等链接时才可以确定。
疑惑在f1()和f3(),它们的指令块都在f.o的.text节,而链接是将各个.o文件的.text节整个搬到最终的目标文件中,不是被打碎了再搬进去的,所以f1()同f3()一样,与fun()的相对位置,在编译阶段就能确定下来,即使f1()可以被别的模块调用,也影响不了这一点,那凭什么对f3()的调用不需要设置重定位项,f1()的调用却需要?
那是因为R_386_PC32这种重定位原本只是用于extern函数调用的,而非static函数默认也有extern属性,所以就多此一举的为f1()调用处加了重定位项,将call指令中相对位移的计算推迟到了链接时,虽然不影响正确性,但是对学习的人好有干扰性,很容易让人觉得是由于static非static的区别,却又不能完全解释的通,因为本质是根据extern非extern的区别来的,直到今天才发现!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802020122
广播电视节目制作经营许可证(京) 字第1234号 中国互联网协会会员  联系我们:wangnan@it168.com
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

ChinaUnix - Archiver - WAP - TOP
  
钓鱼 明升国际 优德88 新金沙网上赌博 十三张扑克牌游戏
美高梅网上赌好运 百乐访网址导航 澳门赌博网 外围网站平台 澳门网上娱乐
澳门葡京赌场在线 24小时娱乐城线路检测 威尼斯人色站 波音赌盘 威尼斯人赌场地址
皇都赌场 万豪娱乐现金平台 21点怎么玩 pt电子官网 北京赛车官网下注