Skip to content

Commit 4a01d76

Browse files
author
Alex B
committed
[llvm-macho] Category Merging: Add minimal test + fix Category naming issue
1 parent 34bb244 commit 4a01d76

File tree

3 files changed

+153
-4
lines changed

3 files changed

+153
-4
lines changed

lld/MachO/ObjC.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,8 @@ class ObjcCategoryMerger {
454454
bool emitCatListEntrySec(std::string &forCateogryName,
455455
std::string &forBaseClassName, Defined *&catListSym);
456456
bool emitCategoryBody(std::string &name, Defined *nameSym,
457-
Symbol *baseClassSym, Defined *&catBodySym);
457+
Symbol *baseClassSym, std::string &baseClassName,
458+
Defined *&catBodySym);
458459
bool emitCategoryName(std::string &name, Defined *&catNameSym);
459460
bool createSymbolReference(Defined *refFrom, Symbol *refTo, uint32_t offset,
460461
Reloc &relocTemplate);
@@ -979,6 +980,7 @@ bool ObjcCategoryMerger::emitCatListEntrySec(std::string &forCateogryName,
979980
// class/instance methods/props.
980981
bool ObjcCategoryMerger::emitCategoryBody(std::string &name, Defined *nameSym,
981982
Symbol *baseClassSym,
983+
std::string &baseClassName,
982984
Defined *&catBodySym) {
983985
generatedSectionData.push_back(SmallVector<uint8_t>(catLayout.totalSize, 0));
984986
llvm::ArrayRef<uint8_t> bodyData = generatedSectionData.back();
@@ -995,7 +997,8 @@ bool ObjcCategoryMerger::emitCategoryBody(std::string &name, Defined *nameSym,
995997

996998
newBodySec->parent = infoCategoryWriter.catBodyInfo.outputSection;
997999

998-
std::string symName = "__OBJC_$_CATEGORY_NSArray_$_(" + name + ")";
1000+
std::string symName =
1001+
"__OBJC_$_CATEGORY_" + baseClassName + "_$_(" + name + ")";
9991002
generatedNames.push_back(StringRef(symName));
10001003
catBodySym = make<Defined>(
10011004
StringRef(generatedNames.back()), /*file=*/getGenObjFile(), newBodySec,
@@ -1059,7 +1062,7 @@ bool ObjcCategoryMerger::emitCategory(ClassExtensionInfo &extInfo,
10591062
return false;
10601063

10611064
if (!emitCategoryBody(extInfo.mergedContainerName, catNameSym,
1062-
extInfo.baseClass, catBodySym))
1065+
extInfo.baseClass, extInfo.baseClassName, catBodySym))
10631066
return false;
10641067

10651068
Defined *catListSym = nullptr;

lld/test/MachO/objc-category-merging.s renamed to lld/test/MachO/objc-category-merging-complete-test.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# RUN: llvm-objdump --objc-meta-data --macho a64_file2_merge.exe | FileCheck %s --check-prefixes=MERGE_CATS
1414

1515

16-
MERGE_CATS: __OBJC_$_CATEGORY_NSArray_$_(Category02|Category03)
16+
MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category02|Category03)
1717
MERGE_CATS: instanceMethods
1818
MERGE_CATS-NEXT: 24
1919
MERGE_CATS-NEXT: 4
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# REQUIRES: aarch64
2+
# RUN: rm -rf %t; split-file %s %t && cd %t
3+
4+
## Create a dylib with a fake base class to link against
5+
# RUN: llvm-mc -filetype=obj -triple=arm64-ios-simulator -o a64_fakedylib.o a64_fakedylib.s
6+
# RUN: ld64.lld a64_fakedylib.o -o a64_fakedylib.dylib -dylib -arch arm64 -platform_version ios-simulator 14.0 15.0
7+
8+
## Create our main testing dylib - linking against the fake dylib above
9+
# RUN: llvm-mc -filetype=obj -triple=arm64-ios-simulator -o merge_cat_minimal.o merge_cat_minimal.s
10+
# RUN: ld64.lld -dylib -o merge_cat_minimal_no_merge.dylib a64_fakedylib.dylib merge_cat_minimal.o -arch arm64 -platform_version ios-simulator 14.0 15.0
11+
# RUN: ld64.lld -dylib -o merge_cat_minimal_merge.dylib -merge-objc-categories a64_fakedylib.dylib merge_cat_minimal.o -arch arm64 -platform_version ios-simulator 14.0 15.0
12+
13+
## Now verify that the flag caused category merging to happen appropriatelly
14+
# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_no_merge.dylib | FileCheck %s --check-prefixes=NO_MERGE_CATS
15+
# RUN: llvm-objdump --objc-meta-data --macho merge_cat_minimal_merge.dylib | FileCheck %s --check-prefixes=MERGE_CATS
16+
17+
#### Check merge categories enabled ###
18+
# Check that the original categories are not there
19+
MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
20+
MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
21+
22+
# Check that the merged cateogry is there, in the correct format
23+
MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02)
24+
MERGE_CATS: instanceMethods
25+
MERGE_CATS-NEXT: 24
26+
MERGE_CATS-NEXT: 2
27+
28+
#### Check merge categories disabled ###
29+
# Check that the merged category is not there
30+
NO_MERGE_CATS-NOT: __OBJC_$_CATEGORY_MyBaseClass_$_(Category01|Category02)
31+
32+
# Check that the original categories are there
33+
NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category01
34+
NO_MERGE_CATS: __OBJC_$_CATEGORY_MyBaseClass_$_Category02
35+
36+
37+
38+
#--- a64_fakedylib.s
39+
40+
.section __DATA,__objc_data
41+
.globl _OBJC_CLASS_$_MyBaseClass
42+
_OBJC_CLASS_$_MyBaseClass:
43+
.quad 0
44+
45+
#--- merge_cat_minimal.s
46+
47+
; ================== Generated from ObjC: ==================
48+
; __attribute__((objc_root_class))
49+
; @interface MyBaseClass
50+
; - (void)baseInstanceMethod;
51+
; @end
52+
;
53+
; @interface MyBaseClass(Category01)
54+
; - (void)cat01_InstanceMethod;
55+
; @end
56+
;
57+
; @implementation MyBaseClass(Category01)
58+
; - (void)cat01_InstanceMethod {}
59+
; @end
60+
;
61+
; @interface MyBaseClass(Category02)
62+
; - (void)cat02_InstanceMethod;
63+
; @end
64+
;
65+
; @implementation MyBaseClass(Category02)
66+
; - (void)cat02_InstanceMethod {}
67+
; @end
68+
; ================== Generated from ObjC: ==================
69+
70+
.section __TEXT,__text,regular,pure_instructions
71+
.ios_version_min 7, 0
72+
.p2align 2 ; -- Begin function -[MyBaseClass(Category01) cat01_InstanceMethod]
73+
"-[MyBaseClass(Category01) cat01_InstanceMethod]": ; @"\01-[MyBaseClass(Category01) cat01_InstanceMethod]"
74+
.cfi_startproc
75+
ret
76+
.cfi_endproc
77+
; -- End function
78+
.p2align 2 ; -- Begin function -[MyBaseClass(Category02) cat02_InstanceMethod]
79+
"-[MyBaseClass(Category02) cat02_InstanceMethod]": ; @"\01-[MyBaseClass(Category02) cat02_InstanceMethod]"
80+
.cfi_startproc
81+
ret
82+
.cfi_endproc
83+
; -- End function
84+
.section __TEXT,__objc_classname,cstring_literals
85+
l_OBJC_CLASS_NAME_: ; @OBJC_CLASS_NAME_
86+
.asciz "Category01"
87+
.section __TEXT,__objc_methname,cstring_literals
88+
l_OBJC_METH_VAR_NAME_: ; @OBJC_METH_VAR_NAME_
89+
.asciz "cat01_InstanceMethod"
90+
.section __TEXT,__objc_methtype,cstring_literals
91+
l_OBJC_METH_VAR_TYPE_: ; @OBJC_METH_VAR_TYPE_
92+
.asciz "v16@0:8"
93+
.section __DATA,__objc_const
94+
.p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01"
95+
__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01:
96+
.long 24 ; 0x18
97+
.long 1 ; 0x1
98+
.quad l_OBJC_METH_VAR_NAME_
99+
.quad l_OBJC_METH_VAR_TYPE_
100+
.quad "-[MyBaseClass(Category01) cat01_InstanceMethod]"
101+
.p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category01"
102+
__OBJC_$_CATEGORY_MyBaseClass_$_Category01:
103+
.quad l_OBJC_CLASS_NAME_
104+
.quad _OBJC_CLASS_$_MyBaseClass
105+
.quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category01
106+
.quad 0
107+
.quad 0
108+
.quad 0
109+
.quad 0
110+
.long 64 ; 0x40
111+
.space 4
112+
.section __TEXT,__objc_classname,cstring_literals
113+
l_OBJC_CLASS_NAME_.1: ; @OBJC_CLASS_NAME_.1
114+
.asciz "Category02"
115+
.section __TEXT,__objc_methname,cstring_literals
116+
l_OBJC_METH_VAR_NAME_.2: ; @OBJC_METH_VAR_NAME_.2
117+
.asciz "cat02_InstanceMethod"
118+
.section __DATA,__objc_const
119+
.p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02"
120+
__OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02:
121+
.long 24 ; 0x18
122+
.long 1 ; 0x1
123+
.quad l_OBJC_METH_VAR_NAME_.2
124+
.quad l_OBJC_METH_VAR_TYPE_
125+
.quad "-[MyBaseClass(Category02) cat02_InstanceMethod]"
126+
.p2align 3, 0x0 ; @"_OBJC_$_CATEGORY_MyBaseClass_$_Category02"
127+
__OBJC_$_CATEGORY_MyBaseClass_$_Category02:
128+
.quad l_OBJC_CLASS_NAME_.1
129+
.quad _OBJC_CLASS_$_MyBaseClass
130+
.quad __OBJC_$_CATEGORY_INSTANCE_METHODS_MyBaseClass_$_Category02
131+
.quad 0
132+
.quad 0
133+
.quad 0
134+
.quad 0
135+
.long 64 ; 0x40
136+
.space 4
137+
.section __DATA,__objc_catlist,regular,no_dead_strip
138+
.p2align 3, 0x0 ; @"OBJC_LABEL_CATEGORY_$"
139+
l_OBJC_LABEL_CATEGORY_$:
140+
.quad __OBJC_$_CATEGORY_MyBaseClass_$_Category01
141+
.quad __OBJC_$_CATEGORY_MyBaseClass_$_Category02
142+
.section __DATA,__objc_imageinfo,regular,no_dead_strip
143+
L_OBJC_IMAGE_INFO:
144+
.long 0
145+
.long 96
146+
.subsections_via_symbols

0 commit comments

Comments
 (0)