mirror of
https://github.com/rui314/mold.git
synced 2024-10-04 08:37:28 +03:00
Merge pull request #520 from tapthaker/macho-tbd-files
[Mach-O] Adds support for objc and weak symbols in TBD files
This commit is contained in:
commit
c654d42c14
@ -679,8 +679,30 @@ void DylibFile<E>::parse(Context<E> &ctx) {
|
||||
switch (get_file_type(this->mf)) {
|
||||
case FileType::TAPI: {
|
||||
TextDylib tbd = parse_tbd(ctx, this->mf);
|
||||
auto add_symbol_with_prefix = [&](std::string_view prefix,
|
||||
std::string_view sym_name) {
|
||||
std::string symbol_name = std::string(prefix);
|
||||
symbol_name.append(sym_name);
|
||||
Symbol<E> *sym = get_symbol(ctx, save_string(ctx, symbol_name));
|
||||
this->syms.push_back(sym);
|
||||
};
|
||||
|
||||
for (std::string_view sym : tbd.exports)
|
||||
this->syms.push_back(get_symbol(ctx, sym));
|
||||
for (std::string_view weak_sym : tbd.weak_exports) {
|
||||
Symbol<E> *sym = get_symbol(ctx, weak_sym);
|
||||
sym->is_weak_def = true;
|
||||
this->syms.push_back(sym);
|
||||
}
|
||||
for (std::string_view objc_class : tbd.objc_classes) {
|
||||
add_symbol_with_prefix(OBJC2_CLASS_NAME_PREFIX, objc_class);
|
||||
add_symbol_with_prefix(OBJC2_METACLASS_NAME_PREFIX, objc_class);
|
||||
}
|
||||
for (std::string_view eh_type : tbd.objc_eh_types)
|
||||
add_symbol_with_prefix(OBJC2_EHTYPE_PREFIX, eh_type);
|
||||
for (std::string_view ivar : tbd.objc_ivars)
|
||||
add_symbol_with_prefix(OBJC2_IVAR_PREFIX, ivar);
|
||||
|
||||
install_name = tbd.install_name;
|
||||
break;
|
||||
}
|
||||
|
10
macho/mold.h
10
macho/mold.h
@ -702,6 +702,12 @@ parse_yaml(std::string_view str);
|
||||
// tapi.cc
|
||||
//
|
||||
|
||||
static const std::string_view OBJC2_CLASS_NAME_PREFIX = "_OBJC_CLASS_$_";
|
||||
static const std::string_view OBJC2_METACLASS_NAME_PREFIX =
|
||||
"_OBJC_METACLASS_$_";
|
||||
static const std::string_view OBJC2_EHTYPE_PREFIX = "_OBJC_EHTYPE_$_";
|
||||
static const std::string_view OBJC2_IVAR_PREFIX = "_OBJC_IVAR_$_";
|
||||
|
||||
struct TextDylib {
|
||||
std::string_view uuid;
|
||||
std::string_view install_name;
|
||||
@ -709,6 +715,10 @@ struct TextDylib {
|
||||
std::string_view parent_umbrella;
|
||||
std::vector<std::string_view> reexported_libs;
|
||||
std::vector<std::string_view> exports;
|
||||
std::vector<std::string_view> weak_exports;
|
||||
std::vector<std::string_view> objc_classes;
|
||||
std::vector<std::string_view> objc_eh_types;
|
||||
std::vector<std::string_view> objc_ivars;
|
||||
};
|
||||
|
||||
template <typename E>
|
||||
|
@ -72,10 +72,23 @@ static std::optional<TextDylib> to_tbd(YamlNode &node, std::string_view arch) {
|
||||
|
||||
for (std::string_view key : {"exports", "reexports"})
|
||||
for (YamlNode &mem : get_vector(node, key))
|
||||
if (contains(get_vector(mem, "targets"), arch))
|
||||
if (contains(get_vector(mem, "targets"), arch)) {
|
||||
for (YamlNode &mem : get_vector(mem, "symbols"))
|
||||
if (auto *sym = std::get_if<std::string_view>(&mem.data))
|
||||
tbd.exports.push_back(*sym);
|
||||
for (YamlNode &mem : get_vector(mem, "weak-symbols"))
|
||||
if (auto *sym = std::get_if<std::string_view>(&mem.data))
|
||||
tbd.weak_exports.push_back(*sym);
|
||||
for (YamlNode &mem : get_vector(mem, "objc-classes"))
|
||||
if (auto *clazz = std::get_if<std::string_view>(&mem.data))
|
||||
tbd.objc_classes.push_back(*clazz);
|
||||
for (YamlNode &mem : get_vector(mem, "objc-eh-types"))
|
||||
if (auto *eh_type = std::get_if<std::string_view>(&mem.data))
|
||||
tbd.objc_eh_types.push_back(*eh_type);
|
||||
for (YamlNode &mem : get_vector(mem, "objc-ivars"))
|
||||
if (auto *ivar = std::get_if<std::string_view>(&mem.data))
|
||||
tbd.objc_ivars.push_back(*ivar);
|
||||
}
|
||||
|
||||
return tbd;
|
||||
}
|
||||
|
85
test/macho/tbd.sh
Executable file
85
test/macho/tbd.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
export LC_ALL=C
|
||||
set -e
|
||||
CC="${TEST_CC:-cc}"
|
||||
CXX="${TEST_CXX:-c++}"
|
||||
GCC="${TEST_GCC:-gcc}"
|
||||
GXX="${TEST_GXX:-g++}"
|
||||
OBJDUMP="${OBJDUMP:-objdump}"
|
||||
MACHINE="${MACHINE:-$(uname -m)}"
|
||||
testname=$(basename "$0" .sh)
|
||||
echo -n "Testing $testname ... "
|
||||
cd "$(dirname "$0")"/../..
|
||||
t=out/test/macho/$testname
|
||||
mkdir -p $t
|
||||
|
||||
some_fw=$t/SF/SomeFramework.framework/
|
||||
mkdir -p $some_fw
|
||||
|
||||
cat > $some_fw/SomeFramework.tbd <<EOF
|
||||
--- !tapi-tbd
|
||||
tbd-version: 4
|
||||
targets: [ x86_64-macos, arm64-macos ]
|
||||
uuids:
|
||||
- target: x86_64-macos
|
||||
value: 00000000-0000-0000-0000-000000000000
|
||||
- target: arm64-macos
|
||||
value: 00000000-0000-0000-0000-000000000000
|
||||
install-name: '/usr/frameworks/SomeFramework.framework/SomeFramework'
|
||||
current-version: 0000
|
||||
compatibility-version: 150
|
||||
reexported-libraries:
|
||||
- targets: [ x86_64-macos, arm64-macos ]
|
||||
libraries: [ ]
|
||||
exports:
|
||||
- targets: [ x86_64-macos, arm64-macos ]
|
||||
symbols: [ _some_framework_print ]
|
||||
objc-classes: [ SomeObjectiveC ]
|
||||
weak-symbols: [ _weak_some_framework_print ]
|
||||
...
|
||||
EOF
|
||||
|
||||
|
||||
cat <<EOF | clang -o $t/TestTBDFiles.o -c -xobjective-c -
|
||||
#include <stdio.h>
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
// Interface Declaration for SomeFramework.framework
|
||||
|
||||
@interface SomeObjectiveC: NSObject
|
||||
|
||||
@end
|
||||
|
||||
void some_framework_print(char*);
|
||||
void weak_some_framework_print(char*) __attribute__((weak));;
|
||||
|
||||
// End Interface Declaration for SomeFramework.framework
|
||||
|
||||
@interface TestTBDFiles: SomeObjectiveC
|
||||
@end
|
||||
|
||||
@implementation TestTBDFiles
|
||||
|
||||
-(void) helloWorld {
|
||||
some_framework_print("Hello World");
|
||||
weak_some_framework_print("Hello World");
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, const char * argv[]) {
|
||||
@autoreleasepool {
|
||||
TestTBDFiles *tbd = [[TestTBDFiles alloc]init];
|
||||
[tbd helloWorld];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
clang --ld-path=./ld64 -F$t/SF/ -Wl,-framework,SomeFramework \
|
||||
-Wl,-framework,CoreFoundation -lobjc -o $t/exe $t/TestTBDFiles.o
|
||||
otool -L $t/exe > $t/install_paths.log
|
||||
grep -q '/usr/frameworks/SomeFramework.framework/SomeFramework' $t/install_paths.log
|
||||
|
||||
echo OK
|
Loading…
Reference in New Issue
Block a user