[JITLink][ELF][x86-64] Adjust addends for R_X86_64_PLT32 relocations.
authorLang Hames <lhames@gmail.com>
Sun, 5 Dec 2021 09:31:03 +0000 (20:31 +1100)
committerLang Hames <lhames@gmail.com>
Sun, 5 Dec 2021 09:37:55 +0000 (20:37 +1100)
R_X86_64_PLT32 explicitly represents the '-4' PC-adjustment in the relocation's
addend, but JITLink's x86_64::Branch32PCRel includes the PC-adjustment
implicitly. We have been zeroing the addend to account for the difference, but
this breaks for branches to non-zero offsets past labels. This patch updates the
relocation parsing code to unconditionally adjust the offset by '+4' instead.
For branches directly to labels the result is still 0, for branches to offsets
past labels the result is the correct addend for x86_64::Branch32PCRel.

llvm/lib/ExecutionEngine/JITLink/ELF_x86_64.cpp
llvm/test/ExecutionEngine/JITLink/X86/ELF_x86-64_small_pic_relocations.s

index 072ecd5..27d8833 100644 (file)
@@ -241,7 +241,9 @@ private:
     }
     case Branch32: {
       Kind = x86_64::BranchPCRel32;
-      Addend = 0;
+      // BranchPCRel32 implicitly handles the '-4' PC adjustment, so we have to
+      // adjust the addend by '+4' to compensate.
+      Addend += 4;
       break;
     }
     }
index 00c888b..59981f1 100644 (file)
@@ -39,10 +39,12 @@ named_func:
 
         .size   named_func, .-named_func
 
-# Check R_X86_64_PLT32 handling with a call to a local function. This produces a
-# Branch32 edge that is resolved like a regular PCRel32 (no PLT entry created).
+# Check R_X86_64_PLT32 handling with a call to a local function in the text
+# section. This produces a Branch32 edge that is resolved like a regular
+# PCRel32 (no PLT entry created).
 #
-# jitlink-check: decode_operand(test_call_local, 0) = named_func - next_pc(test_call_local)
+# jitlink-check: decode_operand(test_call_local, 0) = \
+# jitlink-check:   named_func - next_pc(test_call_local)
         .globl  test_call_local
         .p2align       4, 0x90
         .type   test_call_local,@function
@@ -51,6 +53,22 @@ test_call_local:
 
         .size   test_call_local, .-test_call_local
 
+# Check R_X86_64_PLT32 handling with a call to a local linkage function in a
+# different text section and at a non-zero offset. This produces a Branch32 edge
+# that is resolved like a regular PCRel32 (no PLT entry created). The non-zero
+# offset requires us to handle addends for branch relocations correctly.
+#
+# jitlink-check: decode_operand(test_call_alt_sec_at_offset, 0) = \
+# jitlink-check:   (section_addr(elf_sm_pic_reloc.o, .text.alt) + 16) - \
+# jitlink-check:   next_pc(test_call_alt_sec_at_offset)
+        .globl  test_call_alt_sec_at_offset
+        .p2align       4, 0x90
+        .type   test_call_alt_sec_at_offset,@function
+test_call_alt_sec_at_offset:
+        callq   named_func_alt_sec_at_offset
+
+        .size   test_call_alt_sec_at_offset, .-test_call_alt_sec_at_offset
+
 # Check R_X86_64_PLT32 handling with a call to an external via PLT. This
 # produces a Branch32ToStub edge, because externals are not defined locally.
 # As the target is out-of-range from the callsite, the edge keeps using its PLT
@@ -136,6 +154,17 @@ bss_variable:
        .long   0
        .size   bss_variable, 4
 
+# Named functions in a separate section.
+       .section        .text.alt,"ax",@progbits
+# .byte plus alignment of 16 should put named_func_alt_sec_at_offset at offset
+# 16 within .text.alt.
+       .byte   7
+       .p2align        4, 0x90
+       .type   named_func_alt_sec_at_offset,@function
+named_func_alt_sec_at_offset:
+       retq
+       .size   named_func_alt_sec_at_offset, .-named_func_alt_sec_at_offset
+
 # Constant pool entry with type STT_NOTYPE.
         .section        .rodata.cst8,"aM",@progbits,8
         .p2align        3