mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-21 18:54:02 +00:00
[lld-macho] Use LC_LOAD_WEAK_DYLIB for dylibs with only weakrefs
Note that dylibs without *any* refs will still be loaded in the usual (strong) fashion. Reviewed By: #lld-macho, thakis Differential Revision: https://reviews.llvm.org/D93435
This commit is contained in:
parent
811444d7a1
commit
4c8276cdc1
@ -527,7 +527,7 @@ void loadReexport(StringRef path, DylibFile *umbrella) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella)
|
DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella)
|
||||||
: InputFile(DylibKind, mb) {
|
: InputFile(DylibKind, mb), refState(RefState::Unreferenced) {
|
||||||
if (umbrella == nullptr)
|
if (umbrella == nullptr)
|
||||||
umbrella = this;
|
umbrella = this;
|
||||||
|
|
||||||
@ -580,7 +580,7 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella)
|
DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella)
|
||||||
: InputFile(DylibKind, interface) {
|
: InputFile(DylibKind, interface), refState(RefState::Unreferenced) {
|
||||||
if (umbrella == nullptr)
|
if (umbrella == nullptr)
|
||||||
umbrella = this;
|
umbrella = this;
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@ namespace macho {
|
|||||||
class InputSection;
|
class InputSection;
|
||||||
class Symbol;
|
class Symbol;
|
||||||
struct Reloc;
|
struct Reloc;
|
||||||
|
enum class RefState : uint8_t;
|
||||||
|
|
||||||
// If --reproduce option is given, all input files are written
|
// If --reproduce option is given, all input files are written
|
||||||
// to this tar archive.
|
// to this tar archive.
|
||||||
@ -135,6 +136,7 @@ public:
|
|||||||
uint32_t compatibilityVersion = 0;
|
uint32_t compatibilityVersion = 0;
|
||||||
uint32_t currentVersion = 0;
|
uint32_t currentVersion = 0;
|
||||||
uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
|
uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
|
||||||
|
RefState refState;
|
||||||
bool reexport = false;
|
bool reexport = false;
|
||||||
bool forceWeakImport = false;
|
bool forceWeakImport = false;
|
||||||
};
|
};
|
||||||
|
@ -116,7 +116,11 @@ private:
|
|||||||
const bool external : 1;
|
const bool external : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Indicates whether & how a dylib symbol is referenced.
|
// This enum does double-duty: as a symbol property, it indicates whether & how
|
||||||
|
// a dylib symbol is referenced. As a DylibFile property, it indicates the kind
|
||||||
|
// of referenced symbols contained within the file. If there are both weak
|
||||||
|
// and strong references to the same file, we will count the file as
|
||||||
|
// strongly-referenced.
|
||||||
enum class RefState : uint8_t { Unreferenced = 0, Weak = 1, Strong = 2 };
|
enum class RefState : uint8_t { Unreferenced = 0, Weak = 1, Strong = 2 };
|
||||||
|
|
||||||
class Undefined : public Symbol {
|
class Undefined : public Symbol {
|
||||||
|
@ -43,6 +43,7 @@ public:
|
|||||||
Writer() : buffer(errorHandler().outputBuffer) {}
|
Writer() : buffer(errorHandler().outputBuffer) {}
|
||||||
|
|
||||||
void scanRelocations();
|
void scanRelocations();
|
||||||
|
void scanSymbols();
|
||||||
void createOutputSections();
|
void createOutputSections();
|
||||||
void createLoadCommands();
|
void createLoadCommands();
|
||||||
void assignAddresses(OutputSegment *);
|
void assignAddresses(OutputSegment *);
|
||||||
@ -424,6 +425,17 @@ void Writer::scanRelocations() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Writer::scanSymbols() {
|
||||||
|
for (const macho::Symbol *sym : symtab->getSymbols()) {
|
||||||
|
if (const auto *defined = dyn_cast<Defined>(sym)) {
|
||||||
|
if (defined->overridesWeakDef)
|
||||||
|
in.weakBinding->addNonWeakDefinition(defined);
|
||||||
|
} else if (const auto *dysym = dyn_cast<DylibSymbol>(sym)) {
|
||||||
|
dysym->file->refState = std::max(dysym->file->refState, dysym->refState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Writer::createLoadCommands() {
|
void Writer::createLoadCommands() {
|
||||||
in.header->addLoadCommand(make<LCDyldInfo>(
|
in.header->addLoadCommand(make<LCDyldInfo>(
|
||||||
in.rebase, in.binding, in.weakBinding, in.lazyBinding, in.exports));
|
in.rebase, in.binding, in.weakBinding, in.lazyBinding, in.exports));
|
||||||
@ -463,10 +475,10 @@ void Writer::createLoadCommands() {
|
|||||||
uint64_t dylibOrdinal = 1;
|
uint64_t dylibOrdinal = 1;
|
||||||
for (InputFile *file : inputFiles) {
|
for (InputFile *file : inputFiles) {
|
||||||
if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
|
if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
|
||||||
// TODO: dylibs that are only referenced by weak refs should also be
|
|
||||||
// loaded via LC_LOAD_WEAK_DYLIB.
|
|
||||||
LoadCommandType lcType =
|
LoadCommandType lcType =
|
||||||
dylibFile->forceWeakImport ? LC_LOAD_WEAK_DYLIB : LC_LOAD_DYLIB;
|
dylibFile->forceWeakImport || dylibFile->refState == RefState::Weak
|
||||||
|
? LC_LOAD_WEAK_DYLIB
|
||||||
|
: LC_LOAD_DYLIB;
|
||||||
in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->dylibName,
|
in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->dylibName,
|
||||||
dylibFile->compatibilityVersion,
|
dylibFile->compatibilityVersion,
|
||||||
dylibFile->currentVersion));
|
dylibFile->currentVersion));
|
||||||
@ -699,11 +711,7 @@ void Writer::run() {
|
|||||||
scanRelocations();
|
scanRelocations();
|
||||||
if (in.stubHelper->isNeeded())
|
if (in.stubHelper->isNeeded())
|
||||||
in.stubHelper->setup();
|
in.stubHelper->setup();
|
||||||
|
scanSymbols();
|
||||||
for (const macho::Symbol *sym : symtab->getSymbols())
|
|
||||||
if (const auto *defined = dyn_cast<Defined>(sym))
|
|
||||||
if (defined->overridesWeakDef)
|
|
||||||
in.weakBinding->addNonWeakDefinition(defined);
|
|
||||||
|
|
||||||
// Sort and assign sections to their respective segments. No more sections nor
|
// Sort and assign sections to their respective segments. No more sections nor
|
||||||
// segments may be created after these methods run.
|
// segments may be created after these methods run.
|
||||||
|
@ -1,35 +1,72 @@
|
|||||||
# REQUIRES: x86
|
# REQUIRES: x86
|
||||||
# RUN: split-file %s %t
|
# RUN: split-file %s %t
|
||||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weak-ref-only.s -o %t/weak-ref-only.o
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/weak-ref-sub-library.s -o %t/weak-ref-sub-library.o
|
||||||
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/mixed-ref.s -o %t/mixed-ref.o
|
||||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
||||||
# RUN: %lld -lSystem -dylib %t/foo.o -o %t/libfoo.dylib
|
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/bar.s -o %t/bar.o
|
||||||
|
# RUN: %lld -lSystem -dylib %t/bar.o -o %t/libbar.dylib
|
||||||
|
# RUN: %lld -lSystem -dylib %t/foo.o %t/libbar.dylib -sub_library libbar -o %t/libfoo.dylib
|
||||||
|
|
||||||
# RUN: %lld -weak-lSystem %t/test.o -weak_framework CoreFoundation -weak_library %t/libfoo.dylib -o %t/test
|
# RUN: %lld -weak-lSystem %t/test.o -weak_framework CoreFoundation -weak_library %t/libfoo.dylib -o %t/test
|
||||||
# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t
|
# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t --check-prefixes=WEAK-SYS,WEAK-FOO
|
||||||
# RUN: %lld -weak-lSystem %t/test.o \
|
# RUN: %lld -weak-lSystem %t/test.o \
|
||||||
# RUN: -framework CoreFoundation -weak_framework CoreFoundation -framework CoreFoundation \
|
# RUN: -framework CoreFoundation -weak_framework CoreFoundation -framework CoreFoundation \
|
||||||
# RUN: %t/libfoo.dylib -weak_library %t/libfoo.dylib %t/libfoo.dylib -o %t/test
|
# RUN: %t/libfoo.dylib -weak_library %t/libfoo.dylib %t/libfoo.dylib -o %t/test
|
||||||
# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t
|
# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t --check-prefixes=WEAK-SYS,WEAK-FOO
|
||||||
|
# RUN: %lld -lSystem -dylib %t/libfoo.dylib %t/weak-ref-only.o -o %t/weak-ref-only
|
||||||
|
# RUN: llvm-objdump --macho --all-headers %t/weak-ref-only | FileCheck %s -DDIR=%t --check-prefixes=SYS,WEAK-FOO
|
||||||
|
# RUN: %lld -lSystem -dylib %t/libfoo.dylib %t/weak-ref-sub-library.o -o %t/weak-ref-sub-library
|
||||||
|
# RUN: llvm-objdump --macho --all-headers %t/weak-ref-sub-library | FileCheck %s -DDIR=%t --check-prefixes=SYS,WEAK-FOO
|
||||||
|
# RUN: %lld -lSystem -dylib %t/libfoo.dylib %t/mixed-ref.o -o %t/mixed-ref
|
||||||
|
# RUN: llvm-objdump --macho --all-headers %t/mixed-ref | FileCheck %s -DDIR=%t --check-prefixes=SYS,FOO
|
||||||
|
|
||||||
# CHECK: cmd LC_LOAD_WEAK_DYLIB
|
# WEAK-SYS: cmd LC_LOAD_WEAK_DYLIB
|
||||||
# CHECK-NEXT: cmdsize
|
# WEAK-SYS-NEXT: cmdsize
|
||||||
# CHECK-NEXT: name /usr/lib/libSystem.B.dylib
|
# WEAK-SYS-NEXT: name /usr/lib/libSystem.B.dylib
|
||||||
|
|
||||||
# CHECK: cmd LC_LOAD_WEAK_DYLIB
|
# WEAK-SYS: cmd LC_LOAD_WEAK_DYLIB
|
||||||
# CHECK-NEXT: cmdsize
|
# WEAK-SYS-NEXT: cmdsize
|
||||||
# CHECK-NEXT: name /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
|
# WEAK-SYS-NEXT: name /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
|
||||||
|
|
||||||
# CHECK: cmd LC_LOAD_WEAK_DYLIB
|
# SYS: cmd LC_LOAD_DYLIB
|
||||||
# CHECK-NEXT: cmdsize
|
# SYS-NEXT: cmdsize
|
||||||
# CHECK-NEXT: name [[DIR]]/libfoo.dylib
|
# SYS-NEXT: name /usr/lib/libSystem.B.dylib
|
||||||
|
|
||||||
|
# WEAK-FOO: cmd LC_LOAD_WEAK_DYLIB
|
||||||
|
# WEAK-FOO-NEXT: cmdsize
|
||||||
|
# WEAK-FOO-NEXT: name [[DIR]]/libfoo.dylib
|
||||||
|
|
||||||
|
# FOO: cmd LC_LOAD_DYLIB
|
||||||
|
# FOO-NEXT: cmdsize
|
||||||
|
# FOO-NEXT: name [[DIR]]/libfoo.dylib
|
||||||
|
|
||||||
#--- foo.s
|
#--- foo.s
|
||||||
.globl _foo
|
.globl _foo
|
||||||
_foo:
|
_foo:
|
||||||
ret
|
|
||||||
|
#--- bar.s
|
||||||
|
.globl _bar
|
||||||
|
_bar:
|
||||||
|
|
||||||
|
#--- weak-ref-only.s
|
||||||
|
.weak_reference _foo
|
||||||
|
.data
|
||||||
|
.quad _foo
|
||||||
|
|
||||||
|
#--- weak-ref-sub-library.s
|
||||||
|
.weak_reference _bar
|
||||||
|
.data
|
||||||
|
.quad _bar
|
||||||
|
|
||||||
|
#--- mixed-ref.s
|
||||||
|
.weak_definition _foo
|
||||||
|
.data
|
||||||
|
.quad _foo
|
||||||
|
.quad _bar
|
||||||
|
|
||||||
#--- test.s
|
#--- test.s
|
||||||
.globl _main
|
.globl _main
|
||||||
.text
|
|
||||||
_main:
|
_main:
|
||||||
ret
|
ret
|
||||||
|
Loading…
x
Reference in New Issue
Block a user