Skip to content

Commit

Permalink
[lld-macho][objc] Don't crash when rodata isn't statically linked
Browse files Browse the repository at this point in the history
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
  • Loading branch information
int3 committed Mar 30, 2023
1 parent 453102a commit 96d0875
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 6 deletions.
14 changes: 8 additions & 6 deletions lld/MachO/ObjC.cpp
Expand Up @@ -259,12 +259,14 @@ void ObjcCategoryChecker::parseClass(const Defined *classSym) {
auto getMethodsIsec =
[&](const InputSection *classIsec) -> ConcatInputSection * {
if (const auto *r = classIsec->getRelocAt(classLayout.roDataOffset)) {
const auto *roIsec =
cast<ConcatInputSection>(r->getReferentInputSection());
if (const auto *r = roIsec->getRelocAt(roClassLayout.baseMethodsOffset)) {
if (auto *methodsIsec =
cast_or_null<ConcatInputSection>(r->getReferentInputSection()))
return methodsIsec;
if (const auto *roIsec =
cast_or_null<ConcatInputSection>(r->getReferentInputSection())) {
if (const auto *r =
roIsec->getRelocAt(roClassLayout.baseMethodsOffset)) {
if (auto *methodsIsec = cast_or_null<ConcatInputSection>(
r->getReferentInputSection()))
return methodsIsec;
}
}
}
return nullptr;
Expand Down
40 changes: 40 additions & 0 deletions lld/test/MachO/objc-category-conflicts.s
Expand Up @@ -3,13 +3,17 @@
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat1.s -o %t/cat1.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/cat2.s -o %t/cat2.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos11.0 -I %t %t/klass.s -o %t/klass.o
# 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
# RUN: %lld -dylib -lobjc %t/klass.o -o %t/libklass.dylib

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

## Regression test: Check that we don't crash.
# RUN: %no-fatal-warnings-lld -dylib -lobjc %t/klass-with-no-rodata.o -o /dev/null

# CATCLS: warning: method '+s1' has conflicting definitions:
# CATCLS-NEXT: >>> defined in category Cat1 from {{.*}}cat1.o
# CATCLS-NEXT: >>> defined in class Foo from {{.*}}klass.o
Expand Down Expand Up @@ -199,6 +203,42 @@ __OBJC_$_INSTANCE_METHODS_Foo:

.subsections_via_symbols

#--- klass-with-no-rodata.s

.include "objc-macros.s"

## swiftc generates some classes without a statically-linked rodata. Not
## entirely sure what the corresponding Swift inputs are required for this to
## happen; this test merely checks that we can gracefully handle this case
## without crashing.
## FIXME: It would be better if this test used the output of some real Swift
## code.

.globl _$s11FooAACfD

.section __DATA,__objc_data
_$s11FooAACfD:
.quad _$s11FooAACfD
.quad 0
.quad __objc_empty_cache
.quad 0
.quad __objc_empty_cache

.section __DATA,__objc_catlist,regular,no_dead_strip
.quad __CATEGORY_METAFoo_$_Foo20

.section __DATA,__objc_const
__CATEGORY_METAFoo_$_Foo20:
.objc_classname "Foo20"
.quad _$s11FooAACfD
.quad 0
.quad 0
.quad 0
.quad 0
.quad 0
.long 64
.space 4

#--- objc-macros.s

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

0 comments on commit 96d0875

Please sign in to comment.