Skip to content

Commit

Permalink
[JITLink] Fix i686 R_386_32 and other relocation values (llvm#111091)
Browse files Browse the repository at this point in the history
Fix R_386_32 and other relocations by correcting Addend computations.

(cherry picked from commit 5716f83)
  • Loading branch information
vtjnash authored and giordano committed Nov 21, 2024
1 parent df73ee6 commit 2f1ab82
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 44 deletions.
33 changes: 9 additions & 24 deletions llvm/include/llvm/ExecutionEngine/JITLink/i386.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,8 @@ enum EdgeKind_i386 : Edge::Kind {
/// Represents a data/control flow instruction using PC-relative addressing
/// to a target.
///
/// The fixup expression for this kind includes an implicit offset to account
/// for the PC (unlike the Delta edges) so that a PCRel32 with a target
/// T and addend zero is a call/branch to the start (offset zero) of T.
///
/// Fixup expression:
/// Fixup <- Target - (Fixup + 4) + Addend : int32
/// Fixup <- Target - Fixup + Addend : int32
///
/// Errors:
/// - The result of the fixup expression must fit into an int32, otherwise
Expand All @@ -68,12 +64,8 @@ enum EdgeKind_i386 : Edge::Kind {
/// Represents a data/control flow instruction using PC-relative addressing
/// to a target.
///
/// The fixup expression for this kind includes an implicit offset to account
/// for the PC (unlike the Delta edges) so that a PCRel16 with a target
/// T and addend zero is a call/branch to the start (offset zero) of T.
///
/// Fixup expression:
/// Fixup <- Target - (Fixup + 4) + Addend : int16
/// Fixup <- Target - Fixup + Addend : int16
///
/// Errors:
/// - The result of the fixup expression must fit into an int16, otherwise
Expand All @@ -86,7 +78,7 @@ enum EdgeKind_i386 : Edge::Kind {
/// Delta from the fixup to the target.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend : int64
/// Fixup <- Target - Fixup + Addend : int32
///
/// Errors:
/// - The result of the fixup expression must fit into an int32, otherwise
Expand Down Expand Up @@ -130,12 +122,8 @@ enum EdgeKind_i386 : Edge::Kind {
/// Represents a PC-relative call or branch to a target. This can be used to
/// identify, record, and/or patch call sites.
///
/// The fixup expression for this kind includes an implicit offset to account
/// for the PC (unlike the Delta edges) so that a Branch32PCRel with a target
/// T and addend zero is a call/branch to the start (offset zero) of T.
///
/// Fixup expression:
/// Fixup <- Target - (Fixup + 4) + Addend : int32
/// Fixup <- Target - Fixup + Addend : int32
///
/// Errors:
/// - The result of the fixup expression must fit into an int32, otherwise
Expand Down Expand Up @@ -164,7 +152,7 @@ enum EdgeKind_i386 : Edge::Kind {
/// target may be recorded to allow manipulation at runtime.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend - 4 : int32
/// Fixup <- Target - Fixup + Addend : int32
///
/// Errors:
/// - The result of the fixup expression must fit into an int32, otherwise
Expand All @@ -180,7 +168,7 @@ enum EdgeKind_i386 : Edge::Kind {
/// is within range of the fixup location.
///
/// Fixup expression:
/// Fixup <- Target - Fixup + Addend - 4: int32
/// Fixup <- Target - Fixup + Addend : int32
///
/// Errors:
/// - The result of the fixup expression must fit into an int32, otherwise
Expand Down Expand Up @@ -215,8 +203,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
}

case i386::PCRel32: {
int32_t Value =
E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
int32_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
*(little32_t *)FixupPtr = Value;
break;
}
Expand All @@ -231,8 +218,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
}

case i386::PCRel16: {
int32_t Value =
E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
int32_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
if (LLVM_LIKELY(isInt<16>(Value)))
*(little16_t *)FixupPtr = Value;
else
Expand All @@ -257,8 +243,7 @@ inline Error applyFixup(LinkGraph &G, Block &B, const Edge &E,
case i386::BranchPCRel32:
case i386::BranchPCRel32ToPtrJumpStub:
case i386::BranchPCRel32ToPtrJumpStubBypassable: {
int32_t Value =
E.getTarget().getAddress() - (FixupAddress + 4) + E.getAddend();
int32_t Value = E.getTarget().getAddress() - FixupAddress + E.getAddend();
*(little32_t *)FixupPtr = Value;
break;
}
Expand Down
20 changes: 17 additions & 3 deletions llvm/lib/ExecutionEngine/JITLink/ELF_i386.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,15 +186,29 @@ class ELFLinkGraphBuilder_i386 : public ELFLinkGraphBuilder<ELFT> {
int64_t Addend = 0;

switch (*Kind) {
case i386::EdgeKind_i386::Delta32: {
case i386::EdgeKind_i386::None:
break;
case i386::EdgeKind_i386::Pointer32:
case i386::EdgeKind_i386::PCRel32:
case i386::EdgeKind_i386::RequestGOTAndTransformToDelta32FromGOT:
case i386::EdgeKind_i386::Delta32:
case i386::EdgeKind_i386::Delta32FromGOT:
case i386::EdgeKind_i386::BranchPCRel32:
case i386::EdgeKind_i386::BranchPCRel32ToPtrJumpStub:
case i386::EdgeKind_i386::BranchPCRel32ToPtrJumpStubBypassable: {
const char *FixupContent = BlockToFix.getContent().data() +
(FixupAddress - BlockToFix.getAddress());
Addend = *(const support::ulittle32_t *)FixupContent;
Addend = *(const support::little32_t *)FixupContent;
break;
}
default:
case i386::EdgeKind_i386::Pointer16:
case i386::EdgeKind_i386::PCRel16: {
const char *FixupContent = BlockToFix.getContent().data() +
(FixupAddress - BlockToFix.getAddress());
Addend = *(const support::little16_t *)FixupContent;
break;
}
}

Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
Edge GE(*Kind, Offset, *GraphSymbol, Addend);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ main:
.type bar,@function
bar:
retw $external_data
.size bar, .-bar
.size bar, .-bar

# jitlink-check: decode_operand(baz, 0) = external_data + 23
.globl baz
.align 2, 0x90
.type baz,@function
baz:
retw $external_data+23
.size baz, .-baz
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,25 @@
# Test ELF 32 bit absolute relocations

.text
.globl main
.globl main
.p2align 4, 0x90
.type main,@function
main:
main:
retl
.size main, .-main

# jitlink-check: decode_operand(foo, 0) = external_data
.globl foo
.globl foo
.p2align 4, 0x90
.type foo,@function
foo:
movl external_data, %eax
.size foo, .-foo
.size foo, .-foo

# jitlink-check: decode_operand(bar, 0) = external_data + 4000
.globl bar
.p2align 4, 0x90
.type bar,@function
bar:
movl external_data + 4000, %eax
.size bar, .-bar
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,18 @@ foo:


# Tests PC relative relocation for negative offset from PC
# jitlink-check: decode_operand(baz, 0) = fooz - next_pc(baz)
# jitlink-check: decode_operand(baz, 0) = fooz - next_pc(baz) + 1
.globl fooz
.p2align 4
.type fooz,@function
fooz:
nop
retl
.size fooz, .-fooz

.globl baz
.p2align 4
.type baz,@function
baz:
calll fooz
.size baz, .-baz
calll fooz+1
.size baz, .-baz
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,29 @@ main:
# Test GOT32 handling.
#
# We want to check both the offset to the GOT entry and its contents.
# jitlink-check: decode_operand(test_got, 4) = got_addr(elf_sm_pic_reloc_got.o, named_data1) - _GLOBAL_OFFSET_TABLE_
# jitlink-check: decode_operand(test_got, 4) = got_addr(elf_sm_pic_reloc_got.o, named_data1) - _GLOBAL_OFFSET_TABLE_ + 42
# jitlink-check: *{4}(got_addr(elf_sm_pic_reloc_got.o, named_data1)) = named_data1
#
# jitlink-check: decode_operand(test_got+6, 4) = got_addr(elf_sm_pic_reloc_got.o, named_data2) - _GLOBAL_OFFSET_TABLE_
# jitlink-check: decode_operand(test_got+6, 4) = got_addr(elf_sm_pic_reloc_got.o, named_data2) - _GLOBAL_OFFSET_TABLE_ + 5
# jitlink-check: *{4}(got_addr(elf_sm_pic_reloc_got.o, named_data2)) = named_data2

.globl test_got
.p2align 4, 0x90
.type test_got,@function
test_got:
leal named_data1@GOT, %eax
leal named_data2@GOT, %eax
leal named_data1@GOT+42, %eax
leal named_data2@GOT+5, %eax
.size test_got, .-test_got



# Test GOTOFF64 handling.
# jitlink-check: decode_operand(test_gotoff, 1) = named_func - _GLOBAL_OFFSET_TABLE_
# jitlink-check: decode_operand(test_gotoff, 1) = named_func - _GLOBAL_OFFSET_TABLE_ + 99
.globl test_gotoff
.p2align 4, 0x90
.type test_gotoff,@function
test_gotoff:
mov $named_func@GOTOFF, %eax
mov $named_func@GOTOFF+99, %eax
.size test_gotoff, .-test_gotoff


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ main:
# for position independent code, first, as there may be future use-cases
# where we would want to disable the optimization.
#
# jitlink-check: decode_operand(test_call_extern_plt, 0) = external_func - next_pc(test_call_extern_plt)
# jitlink-check: decode_operand(test_call_extern_plt, 0) = external_func - next_pc(test_call_extern_plt) + 53
# jitlink-check: *{4}(got_addr(elf_sm_pic_reloc_plt.o, external_func))= external_func
.globl test_call_extern_plt
.p2align 4, 0x90
.type test_call_extern_plt,@function
test_call_extern_plt:
call external_func@plt
call external_func@plt + 53

.size test_call_extern_plt, .-test_call_extern_plt
.size test_call_extern_plt, .-test_call_extern_plt

0 comments on commit 2f1ab82

Please sign in to comment.