title: How to reverse R_X86_64_JUMP_SLOT relocations?
body: <p>I am building an ELF binary which needs to be able to process and reverse its own relocations at runtime. (The reversing will happen in a separate buffer, not in the original code page, obviously.) The purpose of this is so that the module contents in memory can be HMAC'd and compared against a known good value calculated from the module on disk, to ensure no corruption has occurred. I'm aware that this is somewhat unusual, but it's a requirement of a standard that we have to adhere to.</p>
  <p>I've been able to reverse all of the relocations in the binary <em>except for</em> the <code>R_X86_64_JUMP_SLOT</code> relocations which happen in the Global Offset Table. . Looking at the relocation entries in my test module's <code>.rela.plt</code> section with <code>readelf -a mylib.so</code>, I see these relocations:</p>
  <pre><code>Relocation section '.rela.plt' at offset 0x968 contains 20 entries:
    Offset          Info           Type           Sym. Value    Sym. Name + Addend
  000000005018  000100000007 R_X86_64_JUMP_SLO 0000000000000000 printf + 0
  000000005020  002000000007 R_X86_64_JUMP_SLO 0000000000001ac5 processRelocations + 0
  000000005028  000300000007 R_X86_64_JUMP_SLO 0000000000000000 memcpy + 0
  000000005030  000400000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0 
  ...
  </code></pre>
  <p>These offsets point to the global offset table (specifically <code>.got.plt</code>) so I can get more info with <code> objdump -d -s -j .plt -j .got.plt mylib.so</code>:</p>
  <pre><code>Disassembly of section .got.plt:
  
  0000000000005000 &lt;_GLOBAL_OFFSET_TABLE_&gt;:
      5000:       80 4e 00 00 00 00 00 00 00 00 00 00 00 00 00 00     .N..............
          ...
      5018:       10 10 00 00 00 00 00 00 20 10 00 00 00 00 00 00     ........ .......
      5028:       30 10 00 00 00 00 00 00 40 10 00 00 00 00 00 00     0.......@.......
  ...
  
  Disassembly of section .plt:
  
  0000000000001000 &lt;.plt&gt;:
      1000:       ff 35 02 40 00 00       pushq  0x4002(%rip)        # 5008 &lt;_GLOBAL_OFFSET_TABLE_+0x8&gt;
      1006:       f2 ff 25 03 40 00 00    bnd jmpq *0x4003(%rip)     # 5010 &lt;_GLOBAL_OFFSET_TABLE_+0x10&gt;
      100d:       0f 1f 00                nopl   (%rax)
      1010:       f3 0f 1e fa             endbr64
      1014:       68 00 00 00 00          pushq  $0x0
      1019:       f2 e9 e1 ff ff ff       bnd jmpq 1000 &lt;.plt&gt;
      101f:       90                      nop
      1020:       f3 0f 1e fa             endbr64
  </code></pre>
  <p>Note that this binary is little endian. So the offsets in <code>.got.plt</code>, i.e. <code>0x1010, 0x1020, 0x1030...</code> seem to always point to the <code>endbr64</code> instruction in the corresponding PLT entry. That's similar to the info in <a href="https://stackoverflow.com/a/61957392/108340">this answer</a> which quotes &quot;At startup time the dynamic linker fills the GOT slot with the address pointing to the second instruction of the appropriate PLT entry.&quot; However, in my case it seems to point to the fourth instruction in the PLT entry. That answer further suggests that this relocation is done by adding the module's base address to the original GOT value.</p>
  <p>However, when I run my test program and look at the actual value in memory after dynamic linking, it's not what I expect. For instance, running it now, the GOT entry for at <code>0x5020</code> for <code>processRelocations</code> ends up with the value <code>0x7FF06A0F5AC5</code>. The base address of my module in memory for that run was <code>0x7ff06a0f4000</code>. Subtracting this yields <code>0x1AC5</code>, which actually appears to be the value of the <em>symbol table entry</em> for that function:</p>
  <pre><code>Symbol table '.dynsym' contains 34 entries:
     Num:    Value          Size Type    Bind   Vis      Ndx Name
     ...
     32: 0000000000001ac5   491 FUNC    GLOBAL DEFAULT   10 processRelocations
  </code></pre>
  <p>However, the symbol table entry is not what I want; I need to get back to the original value of <code>0x1020</code>, and I don't see that value anywhere in the symbol table either.</p>
  <p>How can I reverse these relocations at runtime to find their original values?</p>