Skip to content

Commit b260061

Browse files
committed
[lld] macho: Support section branch relocations, including the 1-byte form
I noticed that we had a hardcoded value of 4 for the pcrel section relocations, which seems like an issue given that we recently added support for 1-byte branch relocations in llvm#164439. The code included an assert that the relevant relocation had the BYTE4 attribute, but that is actually not enough to use a hardcoded value of 4: we need to assert that the *other* `BYTE<n>` attributes are not set either. However, since we did not support local branch relocations, that doesn't seem to have mattered in practice. That said, local branch relocations can be emitted by compilers, and ld64 does handle the 4-byte version of them, so I've added support for it here. ld64 actually seems to reject 1-byte section relocations, so the questionable code is actually probably fine (minus the incorrect assert). So we have two options: add an equivalent check in LLD, or just support 1-byte local branch relocations. Supporting it actually requires less code, so I've gone with that option here.
1 parent 01227ab commit b260061

File tree

3 files changed

+21
-4
lines changed

3 files changed

+21
-4
lines changed

lld/MachO/Arch/X86_64.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ static constexpr std::array<RelocAttrs, 10> relocAttrsArray{{
5454
{"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE1) |
5555
B(BYTE4) | B(BYTE8)},
5656
{"SIGNED", B(PCREL) | B(EXTERN) | B(LOCAL) | B(BYTE4)},
57-
{"BRANCH", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE1) | B(BYTE4)},
57+
{"BRANCH",
58+
B(PCREL) | B(EXTERN) | B(LOCAL) | B(BRANCH) | B(BYTE1) | B(BYTE4)},
5859
{"GOT_LOAD", B(PCREL) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)},
5960
{"GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)},
6061
{"SUBTRACTOR", B(SUBTRAHEND) | B(EXTERN) | B(BYTE4) | B(BYTE8)},

lld/MachO/InputFiles.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -594,8 +594,8 @@ void ObjFile::parseRelocations(ArrayRef<SectionHeader> sectionHeaders,
594594
// FIXME This logic was written around x86_64 behavior -- ARM64 doesn't
595595
// have pcrel section relocations. We may want to factor this out into
596596
// the arch-specific .cpp file.
597-
assert(target->hasAttr(r.type, RelocAttrBits::BYTE4));
598-
referentOffset = sec.addr + relInfo.r_address + 4 + totalAddend -
597+
referentOffset = sec.addr + relInfo.r_address +
598+
(1ull << relInfo.r_length) + totalAddend -
599599
referentSecHead.addr;
600600
} else {
601601
// The addend for a non-pcrel relocation is its absolute address.

lld/test/MachO/x86-64-relocs.s

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
# RUN: llvm-objdump --no-print-imm-hex --section-headers --syms -d %t | FileCheck %s
55

66
# CHECK-LABEL: Sections:
7+
# CHECK: __branch_target {{[0-9a-z]+}} [[#%x, BRANCH_SECT:]]
78
# CHECK: __data {{[0-9a-z]+}} [[#%x, DATA_ADDR:]]
89

910
# CHECK-LABEL: SYMBOL TABLE:
@@ -12,10 +13,18 @@
1213

1314
# CHECK-LABEL: <_main>:
1415
## Test X86_64_RELOC_BRANCH
16+
## Test symbol (extern) relocations first (most common case)
1517
# CHECK: callq 0x[[#%x, F_ADDR]] <_f>
1618
# CHECK: jrcxz 0x[[#%x, F_ADDR]] <_f>
1719
# CHECK: callq 0x[[#%x, G_ADDR]] <_g>
1820
# CHECK: jrcxz 0x[[#%x, G_ADDR]] <_g>
21+
## Test section (local) BRANCH relocations
22+
# CHECK: callq 0x[[#%x, BRANCH_SECT]]
23+
## NOTE: ld64 rejects 1-byte local branch relocations as unsupported, but it
24+
## doesn't take any extra code for us to support it
25+
# CHECK: jrcxz 0x[[#%x, BRANCH_SECT]]
26+
27+
# CHECK-LABEL: <_f>:
1928
## Test extern (symbol) X86_64_RELOC_SIGNED
2029
# CHECK: leaq [[#%u, LOCAL_OFF:]](%rip), %rsi
2130
# CHECK-NEXT: [[#%x, DATA_ADDR - LOCAL_OFF]]
@@ -33,9 +42,12 @@
3342
_main:
3443
callq _f # X86_64_RELOC_BRANCH with r_length=2
3544
jrcxz _f # X86_64_RELOC_BRANCH with r_length=0
36-
# test negative addends
45+
# Test negative addends
3746
callq _f - 1
3847
jrcxz _f - 1
48+
# Test section relocations
49+
callq L_.branch_target
50+
jrcxz L_.branch_target
3951
mov $0, %rax
4052
ret
4153

@@ -48,6 +60,10 @@ _f:
4860
movq L_.ptr_1(%rip), %rsi
4961
ret
5062

63+
.section __TEXT,__branch_target
64+
L_.branch_target:
65+
ret
66+
5167
.data
5268
## References to this generate a symbol relocation
5369
_local:

0 commit comments

Comments
 (0)