Skip to content

Commit 96d0875

Browse files
committed
[lld-macho][objc] Don't crash when rodata isn't statically linked
We were previously assuming that to hold, but it appears that `swiftc` may generate classes that link against `__objc_empty_cache` for their rodata pointer. This should allow us to re-land {D142916} (as a stack). Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D147229
1 parent 453102a commit 96d0875

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

lld/MachO/ObjC.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -259,12 +259,14 @@ void ObjcCategoryChecker::parseClass(const Defined *classSym) {
259259
auto getMethodsIsec =
260260
[&](const InputSection *classIsec) -> ConcatInputSection * {
261261
if (const auto *r = classIsec->getRelocAt(classLayout.roDataOffset)) {
262-
const auto *roIsec =
263-
cast<ConcatInputSection>(r->getReferentInputSection());
264-
if (const auto *r = roIsec->getRelocAt(roClassLayout.baseMethodsOffset)) {
265-
if (auto *methodsIsec =
266-
cast_or_null<ConcatInputSection>(r->getReferentInputSection()))
267-
return methodsIsec;
262+
if (const auto *roIsec =
263+
cast_or_null<ConcatInputSection>(r->getReferentInputSection())) {
264+
if (const auto *r =
265+
roIsec->getRelocAt(roClassLayout.baseMethodsOffset)) {
266+
if (auto *methodsIsec = cast_or_null<ConcatInputSection>(
267+
r->getReferentInputSection()))
268+
return methodsIsec;
269+
}
268270
}
269271
}
270272
return nullptr;

lld/test/MachO/objc-category-conflicts.s

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,17 @@
33
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
44
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
55
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o
6+
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass-with-no-rodata.s -o %t/klass-with-no-rodata.o
67
# RUN: %lld -dylib -lobjc %t/klass.o -o %t/libklass.dylib
78

89
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass.o %t/cat1.o %t/cat2.o -o \
910
# RUN: /dev/null 2>&1 | FileCheck %s --check-prefixes=CATCLS,CATCAT
1011
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/libklass.dylib %t/cat1.o \
1112
# RUN: %t/cat2.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=CATCAT
1213

14+
## Regression test: Check that we don't crash.
15+
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null
16+
1317
# CATCLS: warning: method '+s1' has conflicting definitions:
1418
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
1519
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
@@ -199,6 +203,42 @@ __OBJC_$_INSTANCE_METHODS_Foo:
199203

200204
.subsections_via_symbols
201205

206+
#--- klass-with-no-rodata.s
207+
208+
.include "objc-macros.s"
209+
210+
## swiftc generates some classes without a statically-linked rodata. Not
211+
## entirely sure what the corresponding Swift inputs are required for this to
212+
## happen; this test merely checks that we can gracefully handle this case
213+
## without crashing.
214+
## FIXME: It would be better if this test used the output of some real Swift
215+
## code.
216+
217+
.globl _$s11FooAACfD
218+
219+
.section __DATA,__objc_data
220+
_$s11FooAACfD:
221+
.quad _$s11FooAACfD
222+
.quad 0
223+
.quad __objc_empty_cache
224+
.quad 0
225+
.quad __objc_empty_cache
226+
227+
.section __DATA,__objc_catlist,regular,no_dead_strip
228+
.quad __CATEGORY_METAFoo_$_Foo20
229+
230+
.section __DATA,__objc_const
231+
__CATEGORY_METAFoo_$_Foo20:
232+
.objc_classname "Foo20"
233+
.quad _$s11FooAACfD
234+
.quad 0
235+
.quad 0
236+
.quad 0
237+
.quad 0
238+
.quad 0
239+
.long 64
240+
.space 4
241+
202242
#--- objc-macros.s
203243

204244
# Macros for taking some of the boilerplate out of defining objc structs.

0 commit comments

Comments
 (0)