Skip to content

Commit 30e7c4c

Browse files
alx32kbluck
authored andcommitted
[lld-macho] Category merger: handle addends when getting symbol at offset (llvm#91238)
Currently the `tryFindDefinedOnIsec` takes in an `InputSection` and an `offset` and is supposed to return the target symbol that is referenced on that `InputSection` at the given offset. However, it does not deal with the reloc `addend` and might return the incorrect symbol. Here we add support for handling the reloc's `addend`.
1 parent 54f925e commit 30e7c4c

File tree

2 files changed

+436
-3
lines changed

2 files changed

+436
-3
lines changed

lld/MachO/ObjC.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ class ObjcCategoryMerger {
490490
Defined *emitCategoryName(const std::string &name, ObjFile *objFile);
491491
void createSymbolReference(Defined *refFrom, const Symbol *refTo,
492492
uint32_t offset, const Reloc &relocTemplate);
493+
Defined *tryFindDefinedOnIsec(const InputSection *isec, uint32_t offset);
493494
Symbol *tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
494495
uint32_t offset);
495496
Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
@@ -566,7 +567,25 @@ ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
566567
if (!reloc)
567568
return nullptr;
568569

569-
return reloc->referent.get<Symbol *>();
570+
Symbol *sym = reloc->referent.get<Symbol *>();
571+
572+
if (reloc->addend) {
573+
assert(isa<Defined>(sym) && "Expected defined for non-zero addend");
574+
Defined *definedSym = cast<Defined>(sym);
575+
sym = tryFindDefinedOnIsec(definedSym->isec(),
576+
definedSym->value + reloc->addend);
577+
}
578+
579+
return sym;
580+
}
581+
582+
Defined *ObjcCategoryMerger::tryFindDefinedOnIsec(const InputSection *isec,
583+
uint32_t offset) {
584+
for (Defined *sym : isec->symbols)
585+
if ((sym->value <= offset) && (sym->value + sym->size > offset))
586+
return sym;
587+
588+
return nullptr;
570589
}
571590

572591
Defined *
@@ -1288,8 +1307,12 @@ void ObjcCategoryMerger::eraseMergedCategories() {
12881307
continue;
12891308

12901309
eraseISec(catInfo.catBodyIsec);
1291-
1292-
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
1310+
// We can't erase 'catLayout.nameOffset' for Swift categories because the
1311+
// name will be referenced for generating relative offsets
1312+
// See usages of 'l_.str.11.SimpleClass' in objc-category-merging-swift.s
1313+
// TODO: handle the above in a smarter way
1314+
if (catInfo.sourceLanguage != SourceLanguage::Swift)
1315+
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
12931316
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
12941317
catLayout.instanceMethodsOffset);
12951318
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,

0 commit comments

Comments
 (0)