Skip to content

[lld-macho] Make relative method lists work on x86-64 #103905

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 4 additions & 26 deletions lld/MachO/ObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,28 +186,6 @@ ObjcCategoryChecker::ObjcCategoryChecker()
roClassLayout(target->wordSize), listHeaderLayout(target->wordSize),
methodLayout(target->wordSize) {}

// \p r must point to an offset within a CStringInputSection or a
// ConcatInputSection
static StringRef getReferentString(const Reloc &r) {
if (auto *isec = r.referent.dyn_cast<InputSection *>())
return cast<CStringInputSection>(isec)->getStringRefAtOffset(r.addend);

auto *sym = cast<Defined>(r.referent.get<Symbol *>());
auto *symIsec = sym->isec();
auto symOffset = sym->value + r.addend;

if (auto *s = dyn_cast_or_null<CStringInputSection>(symIsec))
return s->getStringRefAtOffset(symOffset);

if (isa<ConcatInputSection>(symIsec)) {
auto strData = symIsec->data.slice(symOffset);
const char *pszData = reinterpret_cast<const char *>(strData.data());
return StringRef(pszData, strnlen(pszData, strData.size()));
}

llvm_unreachable("unknown reference section in getReferentString");
}

void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
const Symbol *methodContainerSym,
const ConcatInputSection *containerIsec,
Expand All @@ -219,7 +197,7 @@ void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
methodLayout.nameOffset)
continue;

CachedHashStringRef methodName(getReferentString(r));
CachedHashStringRef methodName(r.getReferentString());
// +load methods are special: all implementations are called by the runtime
// even if they are part of the same class. Thus there is no need to check
// for duplicates.
Expand Down Expand Up @@ -251,14 +229,14 @@ void ObjcCategoryChecker::parseMethods(const ConcatInputSection *methodsIsec,
->getReferentInputSection();
nameReloc = roIsec->getRelocAt(roClassLayout.nameOffset);
}
StringRef containerName = getReferentString(*nameReloc);
StringRef containerName = nameReloc->getReferentString();
StringRef methPrefix = mKind == MK_Instance ? "-" : "+";

// We should only ever encounter collisions when parsing category methods
// (since the Class struct is parsed before any of its categories).
assert(mcKind == MCK_Category);
StringRef newCatName =
getReferentString(*containerIsec->getRelocAt(catLayout.nameOffset));
containerIsec->getRelocAt(catLayout.nameOffset)->getReferentString();

auto formatObjAndSrcFileName = [](const InputSection *section) {
lld::macho::InputFile *inputFile = section->getFile();
Expand Down Expand Up @@ -809,7 +787,7 @@ void ObjcCategoryMerger::parseCatInfoToExtInfo(const InfoInputCategory &catInfo,
assert(extInfo.objFileForMergeData &&
"Expected to already have valid objextInfo.objFileForMergeData");

StringRef catName = getReferentString(*catNameReloc);
StringRef catName = catNameReloc->getReferentString();
extInfo.mergedContainerName += catName.str();

// Parse base class
Expand Down
25 changes: 25 additions & 0 deletions lld/MachO/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,31 @@ InputSection *Reloc::getReferentInputSection() const {
}
}

StringRef Reloc::getReferentString() const {
if (auto *isec = referent.dyn_cast<InputSection *>()) {
const auto *cisec = dyn_cast<CStringInputSection>(isec);
assert(cisec && "referent must be a CStringInputSection");
return cisec->getStringRefAtOffset(addend);
}

auto *sym = dyn_cast<Defined>(referent.get<Symbol *>());
assert(sym && "referent must be a Defined symbol");

auto *symIsec = sym->isec();
auto symOffset = sym->value + addend;

if (auto *s = dyn_cast_or_null<CStringInputSection>(symIsec))
return s->getStringRefAtOffset(symOffset);

if (isa<ConcatInputSection>(symIsec)) {
auto strData = symIsec->data.slice(symOffset);
const char *pszData = reinterpret_cast<const char *>(strData.data());
return StringRef(pszData, strnlen(pszData, strData.size()));
}

llvm_unreachable("unknown reference section in getReferentString");
}

bool macho::validateSymbolRelocation(const Symbol *sym,
const InputSection *isec, const Reloc &r) {
const RelocAttrs &relocAttrs = target->getRelocAttrs(r.type);
Expand Down
4 changes: 4 additions & 0 deletions lld/MachO/Relocations.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ struct Reloc {
addend(addend), referent(referent) {}

InputSection *getReferentInputSection() const;

// Must point to an offset within a CStringInputSection or a
// ConcatInputSection.
llvm::StringRef getReferentString() const;
};

bool validateSymbolRelocation(const Symbol *, const InputSection *,
Expand Down
21 changes: 11 additions & 10 deletions lld/MachO/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2010,11 +2010,8 @@ void ObjCMethListSection::setUp() {
while (methodNameOff < isec->data.size()) {
const Reloc *reloc = isec->getRelocAt(methodNameOff);
assert(reloc && "Relocation expected at method list name slot");
auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
assert(def && "Expected valid Defined at method list name slot");
auto *cisec = cast<CStringInputSection>(def->isec());
assert(cisec && "Expected method name to be in a CStringInputSection");
auto methname = cisec->getStringRefAtOffset(def->value);

StringRef methname = reloc->getReferentString();
if (!ObjCSelRefsHelper::getSelRef(methname))
ObjCSelRefsHelper::makeSelRef(methname);

Expand Down Expand Up @@ -2114,19 +2111,23 @@ void ObjCMethListSection::writeRelativeOffsetForIsec(
uint32_t &outSecOff, bool useSelRef) const {
const Reloc *reloc = isec->getRelocAt(inSecOff);
assert(reloc && "Relocation expected at __objc_methlist Offset");
auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
assert(def && "Expected all syms in __objc_methlist to be defined");
uint32_t symVA = def->getVA();

uint32_t symVA = 0;
if (useSelRef) {
auto *cisec = cast<CStringInputSection>(def->isec());
auto methname = cisec->getStringRefAtOffset(def->value);
StringRef methname = reloc->getReferentString();
ConcatInputSection *selRef = ObjCSelRefsHelper::getSelRef(methname);
assert(selRef && "Expected all selector names to already be already be "
"present in __objc_selrefs");
symVA = selRef->getVA();
assert(selRef->data.size() == sizeof(target->wordSize) &&
"Expected one selref per ConcatInputSection");
} else if (reloc->referent.is<Symbol *>()) {
auto *def = dyn_cast_or_null<Defined>(reloc->referent.get<Symbol *>());
assert(def && "Expected all syms in __objc_methlist to be defined");
symVA = def->getVA();
} else {
auto *isec = reloc->referent.get<InputSection *>();
symVA = isec->getVA(reloc->addend);
}

uint32_t currentVA = isec->getVA() + outSecOff;
Expand Down
Loading
Loading