@@ -116,6 +116,30 @@ void ConcatOutputSection::addInput(ConcatInputSection *input) {
116116
117117DenseMap<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