mirror of
https://github.com/rui314/mold.git
synced 2024-10-04 08:37:28 +03:00
[Mach-O] Fix weak undef symbols
This commit is contained in:
parent
fe72463f55
commit
1524746a80
@ -20,7 +20,7 @@ void InputFile<E>::clear_symbols() {
|
||||
sym->file = nullptr;
|
||||
sym->scope = SCOPE_LOCAL;
|
||||
sym->is_imported = false;
|
||||
sym->is_weak_def = false;
|
||||
sym->is_weak = false;
|
||||
sym->subsec = nullptr;
|
||||
sym->value = 0;
|
||||
sym->is_common = false;
|
||||
@ -138,7 +138,7 @@ void ObjectFile<E>::parse_symbols(Context<E> &ctx) {
|
||||
sym.subsec = nullptr;
|
||||
sym.scope = SCOPE_LOCAL;
|
||||
sym.is_common = false;
|
||||
sym.is_weak_def = false;
|
||||
sym.is_weak = false;
|
||||
|
||||
switch (msym.type) {
|
||||
case N_UNDF:
|
||||
@ -533,7 +533,7 @@ template <typename E>
|
||||
static u64 get_rank(Symbol<E> &sym) {
|
||||
if (!sym.file)
|
||||
return 7 << 24;
|
||||
return get_rank(sym.file, sym.is_common, sym.is_weak_def);
|
||||
return get_rank(sym.file, sym.is_common, sym.is_weak);
|
||||
}
|
||||
|
||||
template <typename E>
|
||||
@ -559,14 +559,14 @@ void ObjectFile<E>::resolve_symbols(Context<E> &ctx) {
|
||||
|
||||
Symbol<E> &sym = *this->syms[i];
|
||||
std::scoped_lock lock(sym.mu);
|
||||
bool is_weak_def = (msym.desc & N_WEAK_DEF);
|
||||
bool is_weak = (msym.desc & N_WEAK_DEF);
|
||||
|
||||
sym.scope = merge_scope(sym, msym);
|
||||
|
||||
if (get_rank(this, msym.is_common(), is_weak_def) < get_rank(sym)) {
|
||||
if (get_rank(this, msym.is_common(), is_weak) < get_rank(sym)) {
|
||||
sym.file = this;
|
||||
sym.is_imported = false;
|
||||
sym.is_weak_def = is_weak_def;
|
||||
sym.is_weak = is_weak;
|
||||
|
||||
switch (msym.type) {
|
||||
case N_UNDF:
|
||||
@ -647,7 +647,7 @@ void ObjectFile<E>::convert_common_symbols(Context<E> &ctx) {
|
||||
subsections.emplace_back(subsec);
|
||||
|
||||
sym.is_imported = false;
|
||||
sym.is_weak_def = false;
|
||||
sym.is_weak = false;
|
||||
sym.subsec = subsec;
|
||||
sym.value = 0;
|
||||
sym.is_common = false;
|
||||
@ -832,7 +832,7 @@ void DylibFile<E>::resolve_symbols(Context<E> &ctx) {
|
||||
sym->file = this;
|
||||
sym->scope = SCOPE_LOCAL;
|
||||
sym->is_imported = true;
|
||||
sym->is_weak_def = this->is_weak;
|
||||
sym->is_weak = this->is_weak;
|
||||
sym->subsec = nullptr;
|
||||
sym->value = 0;
|
||||
sym->is_common = false;
|
||||
|
@ -255,9 +255,13 @@ template <typename E>
|
||||
static void claim_unresolved_symbols(Context<E> &ctx) {
|
||||
Timer t(ctx, "claim_unresolved_symbols");
|
||||
|
||||
for (std::string_view name : ctx.arg.U)
|
||||
if (Symbol<E> *sym = get_symbol(ctx, name); !sym->file)
|
||||
for (std::string_view name : ctx.arg.U) {
|
||||
Symbol<E> *sym = get_symbol(ctx, name);
|
||||
if (!sym->file) {
|
||||
sym->is_imported = true;
|
||||
sym->is_weak = true;
|
||||
}
|
||||
}
|
||||
|
||||
tbb::parallel_for_each(ctx.objs, [&](ObjectFile<E> *file) {
|
||||
for (i64 i = 0; i < file->mach_syms.size(); i++) {
|
||||
|
@ -281,7 +281,7 @@ struct Symbol {
|
||||
|
||||
u8 scope : 2 = SCOPE_LOCAL;
|
||||
bool is_common : 1 = false;
|
||||
bool is_weak_def : 1 = false;
|
||||
bool is_weak : 1 = false;
|
||||
bool is_imported : 1 = false;
|
||||
bool referenced_dynamically : 1 = false;
|
||||
|
||||
|
@ -680,7 +680,7 @@ static u32 get_dylib_idx(InputFile<E> *file) {
|
||||
template <typename E>
|
||||
void BindEncoder::add(Symbol<E> &sym, i64 seg_idx, i64 offset) {
|
||||
i64 dylib_idx = get_dylib_idx(sym.file);
|
||||
i64 flags = (sym.file->is_weak ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
|
||||
i64 flags = (sym.is_weak ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
|
||||
|
||||
if (last_dylib != dylib_idx) {
|
||||
if (dylib_idx < 16) {
|
||||
@ -767,7 +767,7 @@ void LazyBindSection<E>::add(Context<E> &ctx, Symbol<E> &sym) {
|
||||
encode_uleb(contents, dylib_idx);
|
||||
}
|
||||
|
||||
i64 flags = (sym.file->is_weak ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
|
||||
i64 flags = (sym.is_weak ? BIND_SYMBOL_FLAGS_WEAK_IMPORT : 0);
|
||||
assert(flags < 16);
|
||||
|
||||
emit(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM | flags);
|
||||
|
40
test/macho/weak-def.sh
Executable file
40
test/macho/weak-def.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
export LC_ALL=C
|
||||
set -e
|
||||
CC="${CC:-cc}"
|
||||
CXX="${CXX:-c++}"
|
||||
GCC="${GCC:-gcc}"
|
||||
GXX="${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
|
||||
|
||||
cat <<EOF | $CC -c -o $t/a.o -xc -
|
||||
#include <stdio.h>
|
||||
|
||||
int foo() __attribute__((weak));
|
||||
|
||||
int foo() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("%d\n", foo());
|
||||
}
|
||||
EOF
|
||||
|
||||
cat <<EOF | $CC -c -o $t/b.o -xc -
|
||||
int foo() { return 42; }
|
||||
EOF
|
||||
|
||||
clang --ld-path=./ld64 -o $t/exe1 $t/a.o
|
||||
$t/exe1 | grep -q '^3$'
|
||||
|
||||
clang --ld-path=./ld64 -o $t/exe1 $t/a.o $t/b.o
|
||||
$t/exe1 | grep -q '^42$'
|
||||
|
||||
echo OK
|
@ -25,10 +25,10 @@ cat <<EOF | $CC -c -o $t/b.o -xc -
|
||||
int foo() { return 42; }
|
||||
EOF
|
||||
|
||||
clang -o $t/exe1 $t/a.o -Wl,-U,_foo
|
||||
clang --ld-path=./ld64 -o $t/exe1 $t/a.o -Wl,-U,_foo
|
||||
$t/exe1 | grep -q '^5$'
|
||||
|
||||
clang -o $t/exe2 $t/a.o $t/b.o -Wl,-U,_foo
|
||||
clang --ld-path=./ld64 -o $t/exe2 $t/a.o $t/b.o -Wl,-U,_foo
|
||||
$t/exe2 | grep -q '^42$'
|
||||
|
||||
echo OK
|
||||
|
Loading…
Reference in New Issue
Block a user