Skip to content

[lld-macho] Category Merging: Detect correct class language for classes with aliased symbols #97454

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 1 commit into from
Jul 8, 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
33 changes: 25 additions & 8 deletions lld/MachO/ObjC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,7 @@ class ObjcCategoryMerger {
Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
uint32_t offset);
Defined *getClassRo(const Defined *classSym, bool getMetaRo);
SourceLanguage getClassSymSourceLang(const Defined *classSym);
void mergeCategoriesIntoBaseClass(const Defined *baseClass,
std::vector<InfoInputCategory> &categories);
void eraseSymbolAtIsecOffset(ConcatInputSection *isec, uint32_t offset);
Expand Down Expand Up @@ -1377,21 +1378,37 @@ void objc::mergeCategories() {

void objc::doCleanup() { ObjcCategoryMerger::doCleanup(); }

ObjcCategoryMerger::SourceLanguage
ObjcCategoryMerger::getClassSymSourceLang(const Defined *classSym) {
if (classSym->getName().starts_with(objc::symbol_names::swift_objc_klass))
return SourceLanguage::Swift;

// If the symbol name matches the ObjC prefix, we don't necessarely know this
// comes from ObjC, since Swift creates ObjC-like alias symbols for some Swift
// classes. Ex:
// .globl _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass
// .private_extern _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass
// .set _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass, _$s11MyTestClassAACN
//
// So we scan for symbols with the same address and check for the Swift class
if (classSym->getName().starts_with(objc::symbol_names::klass)) {
for (auto &sym : classSym->originalIsec->symbols)
if (sym->value == classSym->value)
if (sym->getName().starts_with(objc::symbol_names::swift_objc_klass))
return SourceLanguage::Swift;
return SourceLanguage::ObjC;
}

llvm_unreachable("Unexpected class symbol name during category merging");
}
void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
const Defined *baseClass, std::vector<InfoInputCategory> &categories) {
assert(categories.size() >= 1 && "Expected at least one category to merge");

// Collect all the info from the categories
ClassExtensionInfo extInfo(catLayout);
extInfo.baseClass = baseClass;

if (baseClass->getName().starts_with(objc::symbol_names::klass))
extInfo.baseClassSourceLanguage = SourceLanguage::ObjC;
else if (baseClass->getName().starts_with(
objc::symbol_names::swift_objc_klass))
extInfo.baseClassSourceLanguage = SourceLanguage::Swift;
else
llvm_unreachable("Unexpected base class symbol name");
extInfo.baseClassSourceLanguage = getClassSymSourceLang(baseClass);

for (auto &catInfo : categories) {
parseCatInfoToExtInfo(catInfo, extInfo);
Expand Down
Loading
Loading