首页 Position_Independent_Code(PIC)_in_shared_libraries_on_x64

Position_Independent_Code(PIC)_in_shared_libraries_on_x64

举报
开通vip

Position_Independent_Code(PIC)_in_shared_libraries_on_x64 PositionPositionPositionPosition IndependentIndependentIndependentIndependent CodeCodeCodeCode (PIC)(PIC)(PIC)(PIC) inininin sharedsharedsharedshared librarieslibrarieslibrarieslibraries onononon x64x64x64x64 The previous article explained how position indep...

Position_Independent_Code(PIC)_in_shared_libraries_on_x64
PositionPositionPositionPosition IndependentIndependentIndependentIndependent CodeCodeCodeCode (PIC)(PIC)(PIC)(PIC) inininin sharedsharedsharedshared librarieslibrarieslibrarieslibraries onononon x64x64x64x64 The previous article explained how position independent code (PIC) works, with code compiled for the x86 architecture as an example. I promised to cover PIC on x64 [1] in a separate article, so here we are. This article will go into much less detail, since it assumes an understanding of how PIC works in theory. In general, the idea is similar for both platforms, but some details differ because of unique features of each architecture. 前篇文章中,我在 X86平台上通过实例向大家展示了位置无关代码是如何工作的。 之前我 承诺读者会介绍 X64平台上的位置无关代码,那么这篇文章就是了。 不过这篇文章介绍的 不会太详细,因为以前文为基础,我假设读者已经明白什么是位置无关代码了。再说,位置 无关代码这个概念在所有的平台上都是一样的,只不过具体的实现细节会因为平台的不同而 稍微有些差异。 RIP-relativeRIP-relativeRIP-relativeRIP-relative addressingaddressingaddressingaddressing On x86, while function references (with the call instruction) use relative offsets from the instruction pointer, data references (with the mov instruction) only support absolute addresses. As we’ve seen in the previous article, this makes PIC code somewhat less efficient, since PIC by its nature requires making all offsets IP-relative; absolute addresses and position independence don’t go well together. 我们知道,在 X86平台上,MATCH_ word word文档格式规范word作业纸小票打印word模板word简历模板免费word简历 _1713934750163_0的调用(使用 call指令)使用相对位移调用指令(当然是相 对指令指针(instruction pointer)),数据的访问(使用 mov指令)只支持绝对地址访问。 通过前篇文章的学习,我们知道位置无关代码(PIC)的设计思想就是利用 IP-relative来寻 找目标,这么说来 X86平台对数据的访问需要绝对地址的限制在某种程度上降低了位置无关 代码(PIC)的效率,因此绝地与位置无关代码(PIC)不应该同时存在。 x64 fixes that, with a new "RIP-relative addressing mode", which is the default for all 64-bit mov instructions that reference memory (it’s used for other instructions as well, such as lea). A quote from the "Intel Architecture Manual vol 2a": X64通过一个 RIP-relative的寻址模式修正了这个问题,这种寻址模式是所有64位平台上 mov指令默认的访问内存的方式(这种方式也适合其他的指令,例如 lea指令)。下面是摘 自"Intel Architecture Manual vol 2a"的一段: A new addressing form, RIP-relative (relative instruction-pointer) addressing, is implemented in 64-bit mode. An effective address is formed by adding displacement to the 64-bit RIP of the next instruction. RIP-relative(相对于 instruction-pointer)是在64位平台上实现的一种新的寻址方式。一个 有效的地址是通过下条指令的地址(这个地址存储在64位寄存器 RIP中)加上一个位移得 到的。 The displacement used in RIP-relative mode is 32 bits in size. Since it should be useful for both positive and negative offsets, roughly +/- 2GB is the maximal offset from RIP supported by this addressing mode. 因为在 RIP-relative寻址模式中的这个位移长度是32位的,又因为必须可以向前也可以向后 寻址,因此这种寻址方式的范围是+/-2G。 x64x64x64x64 PICPICPICPIC withwithwithwith datadatadatadata referencesreferencesreferencesreferences –––– anananan exampleexampleexampleexample For easier comparison, I will use the same C source as in the data reference example of the previous article: 为了便于比较,我使用与前文相同的 C程序来说明: int myglob = 42; int ml_func(int a, int b) { return myglob + a + b; } Let’s look at the disassembly of ml_func: 来看函数 ml_func的反汇编: 00000000000005ec <<<:>:>:>: 5ec:::: 55 pushpushpushpush rbp 5ed:::: 48 89 e5 movmovmovmov rbp,,,,rsp 5f0:::: 89 7d fc movmovmovmov DWORD PTR [[[[rbp----0x4],],],],ediediediedi 5f3:::: 89 75 f8 movmovmovmov DWORD PTR [[[[rbp----0x8],],],],esiesiesiesi 5f6:::: 48 8b 05 db 09 20 00 movmovmovmov rax,,,,QWORD PTR [[[[rip++++0x2009db]]]] 5fd:::: 8b 00 movmovmovmov eaxeaxeaxeax,,,,DWORD PTR [[[[rax]]]] 5ff:::: 03 45 fc addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x4]]]] 602:::: 03 45 f8 addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x8]]]] 605:::: c9 leaveleaveleaveleave 606:::: c3 retretretret The most interesting instruction here is at 0x5f6: it places the address of myglobal into rax, by referencing an entry in the GOT. As we can see, it uses RIP relative addressing. Since it’s relative to the address of the next instruction, what we actually get is 0x5fd + 0x2009db = 0x200fd8. So the GOT entry holding the address of myglob is at 0x200fd8. Let’s check if it makes sense: 来看地址0x5f6处的指令:将变量 myglob的地址存入寄存器 rax中,同样的这个地址是存 储在 GOT中的某一项。我们看到,这里使用的寻址方式正是RIP-relative —— 因为下条 指令的地址是 0x5fd,因此我们通过计算得出变量 myglob 的地址应该存储在 0x5fd+0x2009db =0x200fd8地址处。让我们验证一下: $ readelf -S libmlpic_dataonly.so There are 35 section headers, starting at offset 0x13a8: Section Headers: [Nr] Name Type Address Offset Size EntSize Flags Link Info Align [...] [20] .got PROGBITS 0000000000200fc8 00000fc8 0000000000000020 0000000000000008 WA 0 0 8 [...] GOT starts at 0x200fc8, so myglob is in its third entry. We can also see the relocation inserted for the GOT reference to myglob: 从输出中我们看待 GOT的起始地址为0x200fc8,因此变量 myglob是 GOT的第三个项。 我们也可以查看重定位 关于同志近三年现实表现材料材料类招标技术评分表图表与交易pdf视力表打印pdf用图表说话 pdf 中关于变量 myglob的重定位入口: $ readelf -r libmlpic_dataonly.so Relocation section '.rela.dyn' at offset 0x450 contains 5 entries: Offset Info Type Sym. Value Sym. Name + Addend [...] 000000200fd8 000500000006 R_X86_64_GLOB_DAT 0000000000201010 myglob + 0 [...] Indeed, a relocation entry for 0x200fd8 telling the dynamic linker to place the address of myglob into it once the final address of this symbol is known. 的确,地址0x200fd8处的重定位告诉链接器当得到变量 myglob的地址后,就将该地址存储 在0x200fd8处。 So it should be quite clear how the address of myglob is obtained in the code. The next instruction in the disassembly (at 0x5fd) then dereferences the address to get the value of myglob into eax [2]. 那么现在对如何得到变量 myglob的地址就很清楚了。接着0x5fd处的指令取出变量 myglob 的值并存入寄存器 eax中。 补充: (gdb) set environment LD_LIBRARY_PATH=. (gdb) set disassembly-flavor intel (gdb) break ml_func Breakpoint 1 at 0x400510 (gdb) run Starting program: /home/astrol/c/dynamic/ position_independent_code_in_shared_libraries_on_x64/driver Breakpoint 1, ml_func (a=1, b=1) at ml_func.c:4 4 return myglob + a + b; (gdb) disassemble Dump of assembler code for function ml_func: 0x00007ffff7bd859c <+0>: push rbp 0x00007ffff7bd859d <+1>: mov rbp,rsp 0x00007ffff7bd85a0 <+4>: mov DWORD PTR [rbp-0x4],edi 0x00007ffff7bd85a3 <+7>: mov DWORD PTR [rbp-0x8],esi => 0x00007ffff7bd85a6 <+10>: mov rax,QWORD PTR [rip+0x200a1b] 0x00007ffff7bd85ad <+17>: mov eax,DWORD PTR [rax] 0x00007ffff7bd85af <+19>: add eax,DWORD PTR [rbp-0x4] 0x00007ffff7bd85b2 <+22>: add eax,DWORD PTR [rbp-0x8] 0x00007ffff7bd85b5 <+25>: pop rbp 0x00007ffff7bd85b6 <+26>: ret End of assembler dump. (gdb) print/x *(long long *)(0x00007ffff7bd85ad + 0x200a1b) $1 = 0x7ffff7dd9010 (gdb) print/x &myglob $2 = 0x7ffff7dd9010 (gdb) Administrator 矩形 Administrator 矩形 x64x64x64x64 PICPICPICPIC withwithwithwith functionfunctionfunctionfunction callscallscallscalls –––– anananan exampleexampleexampleexample Now let’s see how function calls work with PIC code on x64. Once again, we’ll use the same example from the previous article: 现在让我们来看看 X64上位置无关代码(PIC)关于函数调用是如何工作的。同样的,使用 与前篇文章相同的 C程序: int myglob = 42; int ml_util_func(int a) { return a + 1; } int ml_func(int a, int b) { int c = b + ml_util_func(a); myglob += c; return b + myglob; } Disassembling ml_func, we get: 获得函数 ml_func的反汇编如下: 000000000000064b <<<:>:>:>: 64b:::: 55 pushpushpushpush rbp 64c:::: 48 89 e5 movmovmovmov rbp,,,,rsp 64f:::: 48 83 ec 20 subsubsubsub rsp,,,,0x20 653:::: 89 7d ec movmovmovmov DWORD PTR [[[[rbp----0x14],],],],ediediediedi 656:::: 89 75 e8 movmovmovmov DWORD PTR [[[[rbp----0x18],],],],esiesiesiesi 659:::: 8b 45 ec movmovmovmov eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x14]]]] 65c:::: 89 c7 movmovmovmov ediediediedi,,,,eaxeaxeaxeax 65e:::: e8 fd fe ff ff callcallcallcall 560 <<<>>> [[[[... snip more code ...]]]] The call is, as before, to ml_util_func@plt. Let’s see what’s there: 与前文一样,call指令调用的是 ml_util_func@plt,让我们看看它的 内容 财务内部控制制度的内容财务内部控制制度的内容人员招聘与配置的内容项目成本控制的内容消防安全演练内容 : 0000000000000560 <<<:>:>:>: 560:::: ff 25 a2 0a 20 00 jmpjmpjmpjmp QWORD PTR [[[[rip++++0x200aa2]]]] 566:::: 68 01 00 00 00 pushpushpushpush 0x1 56b:::: e9 d0 ff ff ff jmpjmpjmpjmp 540 <<<<_init++++0x18>>>> So, the GOT entry holding the actual address of ml_util_func is at 0x200aa2 + 0x566 = 0x201008. 因此很容易得出,0x200aa2 + 0x566 = 0x201008地址处存储是函数 ml_util_func的地址。 And there’s a relocation for it, as expected: 同样的,重定位表中有关于函数 ml_util_func的重定位入口: $ readelf -r libmlpic.so Relocation section '.rela.dyn' at offset 0x480 contains 5 entries: [...] Relocation section '.rela.plt' at offset 0x4f8 contains 2 entries: Offset Info Type Sym. Value Sym. Name + Addend [...] 000000201008 000600000007 R_X86_64_JUMP_SLO 000000000000063c ml_util_func + 0 补充: (gdb) set environment LD_LIBRARY_PATH=. (gdb) set disassembly-flavor intel (gdb) break ml_func Breakpoint 1 at 0x400500 (gdb) run Starting program: /home/astrol/c/dynamic/ position_independent_code_in_shared_libraries_on_x64/driver Breakpoint 1, ml_func (a=1, b=1) at ml_func2.c:10 10 int c = b + ml_util_func(a); (gdb) disassemble Dump of assembler code for function ml_func: 0x00007ffff7bd860b <+0>: push rbp 0x00007ffff7bd860c <+1>: mov rbp,rsp 0x00007ffff7bd860f <+4>: sub rsp,0x20 0x00007ffff7bd8613 <+8>: mov DWORD PTR [rbp-0x14],edi 0x00007ffff7bd8616 <+11>: mov DWORD PTR [rbp-0x18],esi => 0x00007ffff7bd8619 <+14>: mov eax,DWORD PTR [rbp-0x14] 0x00007ffff7bd861c <+17>: mov edi,eax 0x00007ffff7bd861e <+19>: call 0x7ffff7bd8510 0x00007ffff7bd8623 <+24>: add eax,DWORD PTR [rbp-0x18] 0x00007ffff7bd8626 <+27>: mov DWORD PTR [rbp-0x4],eax 0x00007ffff7bd8629 <+30>: mov rax,QWORD PTR [rip+0x200998] 0x00007ffff7bd8630 <+37>: mov eax,DWORD PTR [rax] 0x00007ffff7bd8632 <+39>: mov edx,eax 0x00007ffff7bd8634 <+41>: add edx,DWORD PTR [rbp-0x4] 0x00007ffff7bd8637 <+44>: mov rax,QWORD PTR [rip+0x20098a] 0x00007ffff7bd863e <+51>: mov DWORD PTR [rax],edx 0x00007ffff7bd8640 <+53>: mov rax,QWORD PTR [rip+0x200981] 0x00007ffff7bd8647 <+60>: mov eax,DWORD PTR [rax] 0x00007ffff7bd8649 <+62>: add eax,DWORD PTR [rbp-0x18] 0x00007ffff7bd864c <+65>: leave 0x00007ffff7bd864d <+66>: ret End of assembler dump. (gdb) disassemble 0x7ffff7bd8510,+0x10 Dump of assembler code from 0x7ffff7bd8510 to 0x7ffff7bd8520: 0x00007ffff7bd8510 : jmp QWORD PTR [rip+0x200aea] 0x00007ffff7bd8516 : push 0x0 0x00007ffff7bd851b : jmp 0x7ffff7bd8500 End of assembler dump. (gdb) print/x *(long long *)(0x00007ffff7bd8516 + 0x200aea) $1 = 0x7ffff7bd8516 (gdb) step ml_util_func (a=1) at ml_func2.c:5 5 return a + 1; (gdb) print/x *(long long *)(0x00007ffff7bd8516 + 0x200aea) $2 = 0x7ffff7bd85fc (gdb) print &ml_util_func $3 = (int (*)(int)) 0x7ffff7bd85fc (gdb) PerformancePerformancePerformancePerformance implicationsimplicationsimplicationsimplications In both examples, it can be seen that PIC on x64 requires less instructions than on x86. On x86, the GOT address is loaded into some base register (ebx by convention) in two steps – first the address of the instruction is obtained with a special function call, and then the offset to GOT is added. Both steps aren’t required on x64, since the relative offset to GOT is known to the linker and can simply be encoded in the instruction itself with RIP relative addressing. 通过上面的两个例子,我们可以清楚的看到位置无关代码(PIC)在 X64平台上的实现需要 更少的代码(相比较于 X86平台)。 在 X86平台上,需要通过两个步骤获得 GOT的地址并 且存入一个寄存器(惯例是 ebx寄存器):首先通过一个特殊的函数调用得到指令指针的值, Administrator 矩形 Administrator 矩形 接着在这个值上加上与 GOT中偏移值。 这两个步骤在 X64平台上都不需要,因为链接器 知道当前指令与 GOT的相对偏移值,并且很容易将这个偏移值用在 RIP-relative寻址模式 中。 When calling a function, there’s also no need to prepare the GOT address in ebx for the trampoline, as the x86 code does, since the trampoline just accesses its GOT entry directly through RIP-relative addressing. 当调用一个函数时,X64平台不再像 X86平台那样使用 ebx 实现 trampoline,因为这个 trampoline可以通过 RIP-relative寻址直接完成。 So PIC on x64 still requires extra instructions when compared to non-PIC code, but the additional cost is smaller. The indirect cost of tying down a register to use as the GOT pointer (which is painful on x86) is also gone, since no such register is needed with RIP-relative addressing [3]. All in all, x64 PIC results in a much smaller performance hit than on x86, making it much more attractive. So attractive, in fact, that it’s the default method for writing shared libraries for this architecture. 可以看到在 X64平台上的位置无关代码(PIC)相对于非位置无关代码(non-PIC)依然需 要一点额外的指令来完成,但是花费的代价变小了,并且也不再需要额外的寄存器来存储 GOT的地址(在 X86平台上必须要占用一个寄存器)。 因此,位置无关代码(PIC)在 X64 平台上的实现相对于 X86平台,性能损耗变得更少了,程序的性能最终得到了提升 —— 事 实上,位置无关代码(PIC)是 X64架构默认的创建共享库的方法。 ExtraExtraExtraExtra credit:credit:credit:credit: Non-PICNon-PICNon-PICNon-PIC codecodecodecode onononon x64x64x64x64 Not only does gcc encourage you to use PIC for shared libraries on x64, it requires it by default. For instance, if we compile the first example without -fpic [4] and then try to link it into a shared library (with -shared), we’ll get an error from the linker, something like this: GCC不仅仅推荐你在 X64上创建共享库时使用 PIC,它也将其设定为默认行为。举例来说, 前面的程序如何编译时不加-fpic选项,而仅仅使用-shared选项的话,我们就会得到链接器 的错误提示如下: /usr/bin/ld: ml_nopic_dataonly.o: relocation R_X86_64_PC32 against symbol `myglob' can not be used when making a shared object; recompile with -fPIC /usr/bin/ld: final link failed: Bad value What’s going on? Let’s look at the disassembly of ml_nopic_dataonly.o [5]: 怎么会这样呢?让我们看看目标文件 ml_nopic_dataonly.o的反汇编: 0000000000000000 <<<:>:>:>: 0:::: 55 pushpushpushpush rbp 1:::: 48 89 e5 movmovmovmov rbp,,,,rsp 4:::: 89 7d fc movmovmovmov DWORD PTR [[[[rbp----0x4],],],],ediediediedi 7:::: 89 75 f8 movmovmovmov DWORD PTR [[[[rbp----0x8],],],],esiesiesiesi a:::: 8b 05 00 00 00 00 movmovmovmov eaxeaxeaxeax,,,,DWORD PTR [[[[rip++++0x0]]]] 10:::: 03 45 fc addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x4]]]] 13:::: 03 45 f8 addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x8]]]] 16:::: c9 leaveleaveleaveleave 17:::: c3 retretretret Note how myglob is accessed here, in instruction at address 0xa. It expects the linker to patch in a relocation to the actual location of myglob into the operand of the instruction (so no GOT redirection is required): 注意地址0xa处的指令对变量 myglob是如何访问的,果然链接器最终会将变量 myglob的 真实地址写进指令码中(因此就不在需要 GOT来间接访问了)。 $ readelf -r ml_nopic_dataonly.o Relocation section '.rela.text' at offset 0xb38 contains 1 entries: Offset Info Type Sym. Value Sym. Name + Addend 00000000000c 000f00000002 R_X86_64_PC32 0000000000000000 myglob - 4 [...] Here is the R_X86_64_PC32 relocation the linker was complaining about. It just can’t link an object with such relocation into a shared library. Why? Because the displacement of the mov (the part that’s added to rip) must fit in 32 bits, and when a code gets into a shared library, we just can’t know in advance that 32 bits will be enough. After all, this is a full 64-bit architecture, with a vast address space. The symbol may eventually be found in some shared library that’s farther away from the reference than 32 bits will allow to reference. This makes R_X86_64_PC32 an invalid relocation for shared libraries on x64. 链接器之所以会报错,是因为它抱怨这里变量 myglob的重定位类型是 R_X86_64_PC32, 而目标文件中一旦含有这种重定位类型的话是不能够创建共享库的,为什么会这样呢?从上 面的汇编代码,我们可以看到 mov指令中的位移必须是32位的(这个位移会与 RIP相加), 因此如果共享库中包含有这样的代码,我们是不能确保32位是否足够大的,毕竟这是在空 间很大的64位平台上。 也许链接时发现这个符号定义在其它共享库中,而这个共享库远在 32位所能访问的空间之外,因此重定位类型 R_X86_64_PC32在 X64平台的共享库中是无 效的。 But can we still somehow create non-PIC code on x64? Yes! We should be instructing the compiler to use the "large code model", by adding the -mcmodel=large flag. The topic of code models is interesting, but explaining it would just take us too far from the real goal of this article [6]. So I’ll just say briefly that a code model is a kind of agreement between the programmer and the compiler, where the programmer makes a certain promise to the compiler about the size of offsets the program will be using. In exchange, the compiler can generate better code. 那么我们有办法在 X64平台生成非位置无关代码(non-PIC)的程序吗? 当然可以!不过 我们必须使用-mcmodel=large选项告诉编译器使用"large code model"模式来编译程序。关 于 code model的话题很有意思,但在这里讨论的话就离我们这篇文章的目的太远了。 简 单点说,code model 就是我们与编译器之间的一种 协议 离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载 ,我们告诉编译器在程序中会使用 何种程度的位移,因此编译器最终会生成我们想要的更好的代码。 It turns out that to make the compiler generate non-PIC code on x64 that actually pleases the linker, only the large code model is suitable, because it’s the least restrictive. Remember how I explained why the simple relocation isn’t good enough on x64, for fear of an offset which will get farther than 32 bits away during linking? Well, the large code model basically gives up on all offset assumptions and uses the largest 64-bit offsets for all its data references. This makes load-time relocations always safe, and enables non-PIC code generation on x64. Let’s see the disassembly of the first example compiled without -fpic and with -mcmodel=large: 结果证明,想在 X64上生成非位置无关代码(non-PIC)的程序必须得“取悦”链接器,因 为链接器是有限制条件的,因此只有 large code model可以生成非位置无关代码(non-PIC)。 想想前面解释的为什么简单的重定位类型(譬如 R_X86_64_PC32)不能满足 X64,就是 怕在链接时32位的寻址范围不足以满足需要的范围!然而,当指定 large code model时, 编译器基本上就会放弃所有的假设,取而代之的做法是对所有的数据访问都是采用 64位的 位移,这就使得装载时重定位在 X64是安全的,最终我们在 X64得到非位置无关代码 (non-PIC)。让我们查看一下生成的汇编代码(不适用-fpic选项,加上-mcmodel=large): 0000000000000000 <<<:>:>:>: 0:::: 55 pushpushpushpush rbp 1:::: 48 89 e5 movmovmovmov rbp,,,,rsp 4:::: 89 7d fc movmovmovmov DWORD PTR [[[[rbp----0x4],],],],ediediediedi 7:::: 89 75 f8 movmovmovmov DWORD PTR [[[[rbp----0x8],],],],esiesiesiesi a:::: 48 b8 00 00 00 00 00 movmovmovmov rax,,,,0x0 11:::: 00 00 00 14:::: 8b 00 movmovmovmov eaxeaxeaxeax,,,,DWORD PTR [[[[rax]]]] 16:::: 03 45 fc addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x4]]]] 19:::: 03 45 f8 addaddaddadd eaxeaxeaxeax,,,,DWORD PTR [[[[rbp----0x8]]]] 1c:::: c9 leaveleaveleaveleave 1d:::: c3 retretretret The instruction at address 0xa places the address of myglob into rax. Note that its argument is currently 0, which tells us to expect a relocation. Note also that it has a full 64-bit address argument. Moreover, the argument is absolute and not RIP-relative [7]. Note also that two instructions are actually required here to get the value of myglob into eax. This is one reason why the large code model is less efficient than the alternatives. 可以看到,地址0xa处的指令将变量 myglob的地址存入寄存器 rax。注意此时变量 myglob 的地址还不知道,所以是地址暂且是0,告诉我们这里装载时会重定位。 注意到没有,地 址是64位的,并且是与 RIP-relative无关的一个绝对值。同样的,注意到没有,这里需要两 条指令才能最终获得变量 myglob的值,这也就解释了为什么在 large code model模式下生 成的代码效率要低一些的原因。 Now let’s see the relocations: 现在让我们重定位: $ readelf -r ml_nopic_dataonly.o Relocation section '.rela.text' at offset 0xb40 contains 1 entries: Offset Info Type Sym. Value Sym. Name + Addend 00000000000c 000f00000001 R_X86_64_64 0000000000000000 myglob + 0 [...] Note the relocation type has changed to R_X86_64_64, which is an absolute relocation that can have a 64-bit value. It’s acceptable by the linker, which will now gladly agree to link this object file into a shared library. 注意到这里变量 myglob的重定位类型是 R_X86_64_64,这是一种64位值的绝对重定位类 型。链接器可以接受这种重定位类型,因此现在可以生成共享库了。 补充: (gdb) set environment LD_LIBRARY_PATH=. (gdb) set disassembly-flavor intel (gdb) break ml_func Breakpoint 1 at 0x400510 (gdb) run Starting program: /home/astrol/c/dynamic/ position_independent_code_in_shared_libraries_on_x64/driver Breakpoint 1, ml_func (a=1, b=1) at ml_func.c:4 4 return myglob + a + b; (gdb) disassemble Dump of assembler code for function ml_func: 0x00007ffff7bd859c <+0>: push rbp 0x00007ffff7bd859d <+1>: mov rbp,rsp 0x00007ffff7bd85a0 <+4>: mov DWORD PTR [rbp-0x4],edi 0x00007ffff7bd85a3 <+7>: mov DWORD PTR [rbp-0x8],esi => 0x00007ffff7bd85a6 <+10>: movabs rax,0x7ffff7dd9010 0x00007ffff7bd85b0 <+20>: mov eax,DWORD PTR [rax] 0x00007ffff7bd85b2 <+22>: add eax,DWORD PTR [rbp-0x4] 0x00007ffff7bd85b5 <+25>: add eax,DWORD PTR [rbp-0x8] 0x00007ffff7bd85b8 <+28>: pop rbp 0x00007ffff7bd85b9 <+29>: ret End of assembler dump. (gdb) print/x &myglob $1 = 0x7ffff7dd9010 (gdb) Some judgmental thinking may bring you to ponder why the compiler generated code that isn’t suitable for load-time relocation by default. The answer to this is simple. Don’t forget that code also tends to get directly linked into executables, which don’t require load-time relocations at all. Therefore, by default the compiler assumes the small code model to gen
本文档为【Position_Independent_Code(PIC)_in_shared_libraries_on_x64】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_971637
暂无简介~
格式:pdf
大小:246KB
软件:PDF阅读器
页数:0
分类:互联网
上传时间:2013-01-02
浏览量:57