Skip to content

Commit ac309bc

Browse files
committed
[lld-macho] Handle InputSection targets in branch range extension logic
1 parent 4564ac9 commit ac309bc

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

lld/MachO/ConcatOutputSection.cpp

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,30 @@ void ConcatOutputSection::addInput(ConcatInputSection *input) {
116116

117117
DenseMap<Symbol *, ThunkInfo> lld::macho::thunkMap;
118118

119+
// Returns the target Symbol that a relocation refers to.
120+
// A Reloc can refer to either a Symbol directly, or to an InputSection.
121+
// For InputSection referents, we return the first Symbol at offset 0.
122+
// This conversion is necessary because the thunk generation algorithm
123+
// can only handle Symbols as branch targets, not InputSections.
124+
static Symbol *getReferentSymbol(const Reloc &r) {
125+
if (auto *sym = r.referent.dyn_cast<Symbol *>()) {
126+
return sym;
127+
} else if (auto *isec = r.referent.dyn_cast<InputSection *>()) {
128+
// Use the first symbol at offset 0 in the InputSection
129+
for (Defined *sym : isec->symbols) {
130+
if (sym->value == 0) {
131+
return sym;
132+
}
133+
}
134+
// Handle absence of suitable symbol
135+
warn("Branch-range extension: No symbol at offset 0 in InputSection '" +
136+
toString(isec) + "', possible branch out of range errors may occur.");
137+
return nullptr;
138+
} else {
139+
llvm_unreachable("Unexpected referent type");
140+
}
141+
}
142+
119143
// Determine whether we need thunks, which depends on the target arch -- RISC
120144
// (i.e., ARM) generally does because it has limited-range branch/call
121145
// instructions, whereas CISC (i.e., x86) generally doesn't. RISC only needs
@@ -145,7 +169,10 @@ bool TextOutputSection::needsThunks() const {
145169
for (Reloc &r : isec->relocs) {
146170
if (!target->hasAttr(r.type, RelocAttrBits::BRANCH))
147171
continue;
148-
auto *sym = cast<Symbol *>(r.referent);
172+
// Get the Symbol that the relocation targets.
173+
Symbol *sym = getReferentSymbol(r);
174+
if (!sym)
175+
continue;
149176
// Pre-populate the thunkMap and memoize call site counts for every
150177
// InputSection and ThunkInfo. We do this for the benefit of
151178
// estimateStubsInRangeVA().
@@ -325,7 +352,10 @@ void TextOutputSection::finalize() {
325352
backwardBranchRange < callVA ? callVA - backwardBranchRange : 0;
326353
uint64_t highVA = callVA + forwardBranchRange;
327354
// Calculate our call referent address
328-
auto *funcSym = cast<Symbol *>(r.referent);
355+
Symbol *funcSym = getReferentSymbol(r);
356+
if (!funcSym)
357+
continue;
358+
329359
ThunkInfo &thunkInfo = thunkMap[funcSym];
330360
// The referent is not reachable, so we need to use a thunk ...
331361
if (funcSym->isInStubs() && callVA >= stubsInRangeVA) {

0 commit comments

Comments
 (0)