Skip to content

Commit 5fa24ac

Browse files
authored
[lld-macho] Category Merger: add support for addrsig references (llvm#90903)
When generating categories, clang sometimes will generate references in the `.addrsig` section to the various category data items. Since we may erase such items after merging them, we also need to remove them from the `.addrsig` section - otherwise this will cause runtime asserts with the `.addrsig` section trying to access invalid data. Implementation wise, we use a hashset to keep track of all erased `InputSection`'s and then go through all `.addrsig` sections and remove references to any erased `InputSection`.
1 parent 52187b9 commit 5fa24ac

File tree

2 files changed

+38
-0
lines changed

2 files changed

+38
-0
lines changed

lld/MachO/ObjC.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,7 @@ class ObjcCategoryMerger {
420420
mergeCategoriesIntoSingleCategory(std::vector<InfoInputCategory> &categories);
421421

422422
void eraseISec(ConcatInputSection *isec);
423+
void removeRefsToErasedIsecs();
423424
void eraseMergedCategories();
424425

425426
void generateCatListForNonErasedCategories(
@@ -478,6 +479,8 @@ class ObjcCategoryMerger {
478479
std::vector<ConcatInputSection *> &allInputSections;
479480
// Map of base class Symbol to list of InfoInputCategory's for it
480481
DenseMap<const Symbol *, std::vector<InfoInputCategory>> categoryMap;
482+
// Set for tracking InputSection erased via eraseISec
483+
DenseSet<InputSection *> erasedIsecs;
481484

482485
// Normally, the binary data comes from the input files, but since we're
483486
// generating binary data ourselves, we use the below array to store it in.
@@ -518,6 +521,8 @@ void ObjcCategoryMerger::collectSectionWriteInfoFromIsec(
518521
Symbol *
519522
ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
520523
uint32_t offset) {
524+
if (!isec)
525+
return nullptr;
521526
const Reloc *reloc = isec->getRelocAt(offset);
522527

523528
if (!reloc)
@@ -1141,6 +1146,8 @@ void ObjcCategoryMerger::generateCatListForNonErasedCategories(
11411146
}
11421147

11431148
void ObjcCategoryMerger::eraseISec(ConcatInputSection *isec) {
1149+
erasedIsecs.insert(isec);
1150+
11441151
isec->live = false;
11451152
for (auto &sym : isec->symbols)
11461153
sym->used = false;
@@ -1175,6 +1182,7 @@ void ObjcCategoryMerger::eraseMergedCategories() {
11751182
continue;
11761183

11771184
eraseISec(catInfo.catBodyIsec);
1185+
11781186
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
11791187
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
11801188
catLayout.instanceMethodsOffset);
@@ -1188,6 +1196,33 @@ void ObjcCategoryMerger::eraseMergedCategories() {
11881196
catLayout.instancePropsOffset);
11891197
}
11901198
}
1199+
1200+
removeRefsToErasedIsecs();
1201+
}
1202+
1203+
// The compiler may generate references to categories inside the addrsig
1204+
// section. This function will erase these references.
1205+
void ObjcCategoryMerger::removeRefsToErasedIsecs() {
1206+
for (InputSection *isec : inputSections) {
1207+
if (isec->getName() != section_names::addrSig)
1208+
continue;
1209+
1210+
auto removeRelocs = [this](Reloc &r) {
1211+
auto *isec = dyn_cast_or_null<ConcatInputSection>(
1212+
r.referent.dyn_cast<InputSection *>());
1213+
if (!isec) {
1214+
Defined *sym =
1215+
dyn_cast_or_null<Defined>(r.referent.dyn_cast<Symbol *>());
1216+
if (sym)
1217+
isec = dyn_cast<ConcatInputSection>(sym->isec());
1218+
}
1219+
if (!isec)
1220+
return false;
1221+
return erasedIsecs.count(isec) > 0;
1222+
};
1223+
1224+
llvm::erase_if(isec->relocs, removeRelocs);
1225+
}
11911226
}
11921227

11931228
void ObjcCategoryMerger::doMerge() {

lld/test/MachO/objc-category-merging-extern-class-minimal.s

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,6 @@ L_OBJC_IMAGE_INFO:
153153
.long 0
154154
.long 96
155155
.subsections_via_symbols
156+
157+
.addrsig
158+
.addrsig_sym __OBJC_$_CATEGORY_MyBaseClass_$_Category01

0 commit comments

Comments
 (0)