[lld-macho] Fix bug in makeSyntheticInputSection when -dead_strip flag is specified (#86878)
Previously, `makeSyntheticInputSection` would create a new `ConcatInputSection` without setting `live` explicitly for it. Without `-dead_strip` this would be OK since `live` would default to `true`. However, with `-dead_strip`, `live` would default to false, and it would remain set to `false`. This hasn't resulted in any issues so far since no code paths that exposed this issue were present. However a recent change - ObjC relative method lists (https://github.com/llvm/llvm-project/pull/86231) exposes this issue by creating relocations to the `SyntheticInputSection`. When these relocations are attempted to be written, this ends up with a crash(assert), since the `SyntheticInputSection` they refer to is marked as dead (`live` = `false`). With this change, we set the correct behavior - `live` will always be `true`. We add a test case that before this change would trigger an assert in the linker.
This commit is contained in:
@@ -323,11 +323,7 @@ void TextOutputSection::finalize() {
|
||||
thunkInfo.isec =
|
||||
makeSyntheticInputSection(isec->getSegName(), isec->getName());
|
||||
thunkInfo.isec->parent = this;
|
||||
|
||||
// This code runs after dead code removal. Need to set the `live` bit
|
||||
// on the thunk isec so that asserts that check that only live sections
|
||||
// get written are happy.
|
||||
thunkInfo.isec->live = true;
|
||||
assert(thunkInfo.isec->live);
|
||||
|
||||
StringRef thunkName = saver().save(funcSym->getName() + ".thunk." +
|
||||
std::to_string(thunkInfo.sequence++));
|
||||
|
||||
@@ -281,6 +281,9 @@ ConcatInputSection *macho::makeSyntheticInputSection(StringRef segName,
|
||||
Section §ion =
|
||||
*make<Section>(/*file=*/nullptr, segName, sectName, flags, /*addr=*/0);
|
||||
auto isec = make<ConcatInputSection>(section, data, align);
|
||||
// Since this is an explicitly created 'fake' input section,
|
||||
// it should not be dead stripped.
|
||||
isec->live = true;
|
||||
section.subsections.push_back({0, isec});
|
||||
return isec;
|
||||
}
|
||||
|
||||
@@ -149,6 +149,7 @@ public:
|
||||
};
|
||||
|
||||
// Initialize a fake InputSection that does not belong to any InputFile.
|
||||
// The created ConcatInputSection will always have 'live=true'
|
||||
ConcatInputSection *makeSyntheticInputSection(StringRef segName,
|
||||
StringRef sectName,
|
||||
uint32_t flags = 0,
|
||||
|
||||
@@ -377,7 +377,7 @@ static void handleSectionBoundarySymbol(const Undefined &sym, StringRef segSect,
|
||||
// live. Marking the isec live ensures an OutputSection is created that the
|
||||
// start/end symbol can refer to.
|
||||
assert(sym.isLive());
|
||||
isec->live = true;
|
||||
assert(isec->live);
|
||||
|
||||
// This runs after gatherInputSections(), so need to explicitly set parent
|
||||
// and add to inputSections.
|
||||
|
||||
@@ -850,7 +850,7 @@ ConcatInputSection *ObjCSelRefsHelper::makeSelRef(StringRef methname) {
|
||||
S_LITERAL_POINTERS | S_ATTR_NO_DEAD_STRIP,
|
||||
ArrayRef<uint8_t>{selrefData, wordSize},
|
||||
/*align=*/wordSize);
|
||||
objcSelref->live = true;
|
||||
assert(objcSelref->live);
|
||||
objcSelref->relocs.push_back({/*type=*/target->unsignedRelocType,
|
||||
/*pcrel=*/false, /*length=*/3,
|
||||
/*offset=*/0,
|
||||
|
||||
@@ -1375,9 +1375,7 @@ void macho::createSyntheticSections() {
|
||||
segment_names::data, section_names::data, S_REGULAR,
|
||||
ArrayRef<uint8_t>{arr, target->wordSize},
|
||||
/*align=*/target->wordSize);
|
||||
// References from dyld are not visible to us, so ensure this section is
|
||||
// always treated as live.
|
||||
in.imageLoaderCache->live = true;
|
||||
assert(in.imageLoaderCache->live);
|
||||
}
|
||||
|
||||
OutputSection *macho::firstTLVDataSection = nullptr;
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists
|
||||
# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL
|
||||
|
||||
## Test arm64 + relative method lists + dead-strip
|
||||
# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -objc_relative_method_lists -dead_strip
|
||||
# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_REL
|
||||
|
||||
## Test arm64 + traditional method lists (no relative offsets)
|
||||
# RUN: %no-lsystem-lld a64_rel_dylib.o -o a64_rel_dylib.dylib -map a64_rel_dylib.map -dylib -arch arm64 -no_objc_relative_method_lists
|
||||
# RUN: llvm-objdump --macho --objc-meta-data a64_rel_dylib.dylib | FileCheck %s --check-prefix=CHK_NO_REL
|
||||
|
||||
Reference in New Issue
Block a user