Skip to content

Commit f1b244b

Browse files
author
Alex B
committed
[lld-macho] Category Merging: Detect correct class language for classes with aliased symbols
1 parent f80a407 commit f1b244b

File tree

2 files changed

+467
-8
lines changed

2 files changed

+467
-8
lines changed

lld/MachO/ObjC.cpp

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,7 @@ class ObjcCategoryMerger {
495495
Defined *tryGetDefinedAtIsecOffset(const ConcatInputSection *isec,
496496
uint32_t offset);
497497
Defined *getClassRo(const Defined *classSym, bool getMetaRo);
498+
SourceLanguage getClassSymSourceLang(const Defined *classSym);
498499
void mergeCategoriesIntoBaseClass(const Defined *baseClass,
499500
std::vector<InfoInputCategory> &categories);
500501
void eraseSymbolAtIsecOffset(ConcatInputSection *isec, uint32_t offset);
@@ -1377,21 +1378,37 @@ void objc::mergeCategories() {
13771378

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

1381+
ObjcCategoryMerger::SourceLanguage
1382+
ObjcCategoryMerger::getClassSymSourceLang(const Defined *classSym) {
1383+
if (classSym->getName().starts_with(objc::symbol_names::swift_objc_klass))
1384+
return SourceLanguage::Swift;
1385+
1386+
// If the symbol name matches the ObjC prefix, we don't necessarely know this
1387+
// comes from ObjC, since Swift creates ObjC-like alias symbols for some Swift
1388+
// classes. Ex:
1389+
// .globl _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass
1390+
// .private_extern _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass
1391+
// .set _OBJC_CLASS_$__TtC11MyTestClass11MyTestClass, _$s11MyTestClassAACN
1392+
//
1393+
// So we scan for symbols with the same address and check for the Swift class
1394+
if (classSym->getName().starts_with(objc::symbol_names::klass)) {
1395+
for (auto &sym : classSym->originalIsec->symbols)
1396+
if (sym->value == classSym->value)
1397+
if (sym->getName().starts_with(objc::symbol_names::swift_objc_klass))
1398+
return SourceLanguage::Swift;
1399+
return SourceLanguage::ObjC;
1400+
}
1401+
1402+
llvm_unreachable("Unexpected class symbol name during category merging");
1403+
}
13801404
void ObjcCategoryMerger::mergeCategoriesIntoBaseClass(
13811405
const Defined *baseClass, std::vector<InfoInputCategory> &categories) {
13821406
assert(categories.size() >= 1 && "Expected at least one category to merge");
13831407

13841408
// Collect all the info from the categories
13851409
ClassExtensionInfo extInfo(catLayout);
13861410
extInfo.baseClass = baseClass;
1387-
1388-
if (baseClass->getName().starts_with(objc::symbol_names::klass))
1389-
extInfo.baseClassSourceLanguage = SourceLanguage::ObjC;
1390-
else if (baseClass->getName().starts_with(
1391-
objc::symbol_names::swift_objc_klass))
1392-
extInfo.baseClassSourceLanguage = SourceLanguage::Swift;
1393-
else
1394-
llvm_unreachable("Unexpected base class symbol name");
1411+
extInfo.baseClassSourceLanguage = getClassSymSourceLang(baseClass);
13951412

13961413
for (auto &catInfo : categories) {
13971414
parseCatInfoToExtInfo(catInfo, extInfo);

0 commit comments

Comments
 (0)