Skip to content

Commit 23663ce

Browse files
committed
[lld-macho] Category Merger: add support for addrsig references
1 parent ad7ee90 commit 23663ce

File tree

2 files changed

+63
-10
lines changed

2 files changed

+63
-10
lines changed

lld/MachO/ObjC.cpp

Lines changed: 60 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include "llvm/Bitcode/BitcodeReader.h"
2222
#include "llvm/Support/TimeProfiler.h"
2323

24+
#include <unordered_set>
25+
2426
using namespace llvm;
2527
using namespace llvm::MachO;
2628
using namespace lld;
@@ -431,6 +433,7 @@ class ObjcCategoryMerger {
431433
mergeCategoriesIntoSingleCategory(std::vector<InfoInputCategory> &categories);
432434

433435
void eraseISec(ConcatInputSection *isec);
436+
void removeRefsToErasedIsecs(std::unordered_set<InputSection *> erasedIsecs);
434437
void eraseMergedCategories();
435438

436439
void generateCatListForNonErasedCategories(
@@ -472,7 +475,9 @@ class ObjcCategoryMerger {
472475
Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
473476
uint32_t offset);
474477
void tryEraseDefinedAtIsecOffset(const ConcatInputSection *isec,
475-
uint32_t offset);
478+
uint32_t offset,
479+
std::unordered_set<InputSection *> &erased);
480+
void eraseSymbolAtIsecOffset(ConcatInputSection *isec, uint32_t offset);
476481

477482
// Allocate a null-terminated StringRef backed by generatedSectionData
478483
StringRef newStringData(const char *str);
@@ -533,6 +538,8 @@ void ObjcCategoryMerger::collectSectionWriteInfoFromIsec(
533538
Symbol *
534539
ObjcCategoryMerger::tryGetSymbolAtIsecOffset(const ConcatInputSection *isec,
535540
uint32_t offset) {
541+
if (!isec)
542+
return nullptr;
536543
const Reloc *reloc = isec->getRelocAt(offset);
537544

538545
if (!reloc)
@@ -551,7 +558,8 @@ ObjcCategoryMerger::tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
551558
// Given an ConcatInputSection or CStringInputSection and an offset, if there is
552559
// a symbol(Defined) at that offset, then erase the symbol (mark it not live)
553560
void ObjcCategoryMerger::tryEraseDefinedAtIsecOffset(
554-
const ConcatInputSection *isec, uint32_t offset) {
561+
const ConcatInputSection *isec, uint32_t offset,
562+
std::unordered_set<InputSection *> &erased) {
555563
const Reloc *reloc = isec->getRelocAt(offset);
556564

557565
if (!reloc)
@@ -561,9 +569,11 @@ void ObjcCategoryMerger::tryEraseDefinedAtIsecOffset(
561569
if (!sym)
562570
return;
563571

564-
if (auto *cisec = dyn_cast_or_null<ConcatInputSection>(sym->isec()))
572+
if (auto *cisec = dyn_cast_or_null<ConcatInputSection>(sym->isec())) {
565573
eraseISec(cisec);
566-
else if (auto *csisec = dyn_cast_or_null<CStringInputSection>(sym->isec())) {
574+
erased.insert(cisec);
575+
} else if (auto *csisec =
576+
dyn_cast_or_null<CStringInputSection>(sym->isec())) {
567577
uint32_t totalOffset = sym->value + reloc->addend;
568578
StringPiece &piece = csisec->getStringPiece(totalOffset);
569579
piece.live = false;
@@ -1183,26 +1193,66 @@ void ObjcCategoryMerger::eraseMergedCategories() {
11831193
// the references to the ones we merged.
11841194
generateCatListForNonErasedCategories(catListToErasedOffsets);
11851195

1196+
// We use erasedIsecs below to track erased sections so we can later remove
1197+
// references to it.
1198+
std::unordered_set<InputSection *> erasedIsecs;
1199+
erasedIsecs.reserve(categoryMap.size());
1200+
11861201
// Erase the old method lists & names of the categories that were merged
11871202
for (auto &mapEntry : categoryMap) {
11881203
for (InfoInputCategory &catInfo : mapEntry.second) {
11891204
if (!catInfo.wasMerged)
11901205
continue;
11911206

1207+
erasedIsecs.insert(catInfo.catBodyIsec);
1208+
erasedIsecs.insert(catInfo.catListIsec);
1209+
11921210
eraseISec(catInfo.catBodyIsec);
1193-
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset);
1211+
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec, catLayout.nameOffset,
1212+
erasedIsecs);
11941213
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
1195-
catLayout.instanceMethodsOffset);
1214+
catLayout.instanceMethodsOffset, erasedIsecs);
11961215
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
1197-
catLayout.classMethodsOffset);
1216+
catLayout.classMethodsOffset, erasedIsecs);
11981217
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
1199-
catLayout.protocolsOffset);
1218+
catLayout.protocolsOffset, erasedIsecs);
12001219
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
1201-
catLayout.classPropsOffset);
1220+
catLayout.classPropsOffset, erasedIsecs);
12021221
tryEraseDefinedAtIsecOffset(catInfo.catBodyIsec,
1203-
catLayout.instancePropsOffset);
1222+
catLayout.instancePropsOffset, erasedIsecs);
12041223
}
12051224
}
1225+
1226+
removeRefsToErasedIsecs(erasedIsecs);
1227+
}
1228+
1229+
// The compiler may generate references to categories inside the addrsig
1230+
// section. This function will erase these references.
1231+
void ObjcCategoryMerger::removeRefsToErasedIsecs(
1232+
std::unordered_set<InputSection *> erasedIsecs) {
1233+
for (InputSection *isec : inputSections) {
1234+
if (isec->getName() != section_names::addrSig)
1235+
continue;
1236+
1237+
auto removeRelocs = [&erasedIsecs](Reloc &r) {
1238+
ConcatInputSection *isec = nullptr;
1239+
isec = dyn_cast_or_null<ConcatInputSection>(
1240+
r.referent.dyn_cast<InputSection *>());
1241+
if (!isec) {
1242+
Defined *sym =
1243+
dyn_cast_or_null<Defined>(r.referent.dyn_cast<Symbol *>());
1244+
if (sym)
1245+
isec = dyn_cast<ConcatInputSection>(sym->isec());
1246+
}
1247+
if (!isec)
1248+
return false;
1249+
return erasedIsecs.count(isec) > 0;
1250+
};
1251+
1252+
isec->relocs.erase(
1253+
std::remove_if(isec->relocs.begin(), isec->relocs.end(), removeRelocs),
1254+
isec->relocs.end());
1255+
}
12061256
}
12071257

12081258
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)