Skip to content

Commit c2d4697

Browse files
committed
Fix bugs found during testing
Created using spr 1.3.6-beta.1
1 parent 8155507 commit c2d4697

File tree

3 files changed

+38
-7
lines changed

3 files changed

+38
-7
lines changed

lld/ELF/Arch/TargetImpl.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,11 @@ inline void applyBranchToBranchOptImpl(
4646
[&getBranchInfo](Relocation &r,
4747
uint64_t addend) -> std::pair<Relocation *, uint64_t> {
4848
auto *target = dyn_cast_or_null<Defined>(r.sym);
49-
// We don't allow preemptible symbols (may go somewhere else),
49+
// We don't allow preemptible symbols or ifuncs (may go somewhere else),
5050
// absolute symbols (runtime behavior unknown), non-executable memory
5151
// (ditto) or non-regular sections (no section data).
52-
if (!target || target->isPreemptible || !target->section ||
52+
if (!target || target->isPreemptible || target->isGnuIFunc() ||
53+
!target->section ||
5354
!(target->section->flags & llvm::ELF::SHF_EXECINSTR) ||
5455
target->section->kind() != SectionBase::Regular)
5556
return {nullptr, 0};
@@ -65,7 +66,11 @@ inline void applyBranchToBranchOptImpl(
6566
std::pair<Relocation *, uint64_t> targetAndAddend =
6667
getRelocBranchInfo(r, *addend);
6768
if (targetAndAddend.first) {
68-
while (1) {
69+
// Avoid getting stuck in an infinite loop if we encounter a branch
70+
// that (possibly indirectly) branches to itself. It is unlikely
71+
// that more than 5 iterations will ever be needed in practice.
72+
size_t iterations = 5;
73+
while (iterations--) {
6974
std::pair<Relocation *, uint64_t> nextTargetAndAddend =
7075
getRelocBranchInfo(*targetAndAddend.first,
7176
targetAndAddend.second);

lld/ELF/Arch/X86_64.cpp

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,8 +1178,15 @@ static std::optional<uint64_t> getControlTransferAddend(InputSection &is,
11781178
// to branch into the middle of a PLT. For example, relative vtable
11791179
// relocations use PLT32 and 0 or a positive value as the addend but still are
11801180
// used to branch to the symbol.
1181-
if (r.type == R_X86_64_PLT32)
1181+
//
1182+
// STT_SECTION symbols are a special case on x86 because the LLVM assembler
1183+
// uses them for branches to local symbols which are assembled as referring to
1184+
// the section symbol with the addend equal to the symbol value - 4.
1185+
if (r.type == R_X86_64_PLT32) {
1186+
if (r.sym->isSection())
1187+
return r.addend + 4;
11821188
return 0;
1189+
}
11831190
return std::nullopt;
11841191
}
11851192

@@ -1204,11 +1211,18 @@ static std::pair<Relocation *, uint64_t> getBranchInfo(InputSection &is,
12041211

12051212
static void mergeControlTransferRelocations(Relocation &r1,
12061213
const Relocation &r2) {
1207-
r1.expr = r2.expr;
1208-
r1.sym = r2.sym;
1214+
// The isSection() check handles the STT_SECTION case described above.
1215+
// In that case the original addend is irrelevant because it referred to an
1216+
// offset within the original target section so we overwrite it.
1217+
//
12091218
// The +4 is here to compensate for r2.addend which will likely be -4,
12101219
// but may also be addend-4 in case of a PC32 branch to symbol+addend.
1211-
r1.addend += r2.addend + 4;
1220+
if (r1.sym->isSection())
1221+
r1.addend = r2.addend;
1222+
else
1223+
r1.addend += r2.addend + 4;
1224+
r1.expr = r2.expr;
1225+
r1.sym = r2.sym;
12121226
}
12131227

12141228
void X86_64::applyBranchToBranchOpt() const {

lld/test/ELF/x86-64-branch-to-branch.s

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ jmp f1
4242
# B2B-NEXT: jmp {{.*}} <f3>
4343
# NOB2B-NEXT: jmp {{.*}} <f2{{.*}}>
4444
jmp f2
45+
# This will assemble to a relocation pointing to an STT_SECTION for .text.f4
46+
# with an addend, which looks similar to the relative vtable cases above but
47+
# requires different handling of the addend so that we don't think this is
48+
# branching to the `jmp f3` at the start of the target section.
49+
# CHECK-NEXT: jmp {{.*}} <f4{{.*}}>
50+
jmp f4
4551

4652
.section .text.f1,"ax"
4753
.globl f1
@@ -58,4 +64,10 @@ jmp f3
5864
.section .text.f3,"ax"
5965
.globl f3
6066
f3:
67+
# Test that a self-branch doesn't trigger an infinite loop.
68+
jmp f3
69+
70+
.section .text.f4,"ax"
71+
jmp f3
72+
f4:
6173
ret

0 commit comments

Comments
 (0)