1
1
mirror of https://github.com/rui314/mold.git synced 2024-09-21 01:47:11 +03:00

[Mach-O] Fix references to dyld_stub_binder

This commit is contained in:
Rui Ueyama 2022-05-18 18:20:04 +08:00
parent 7ce2c7edb5
commit 2c5582b9e9
5 changed files with 58 additions and 14 deletions

View File

@ -54,7 +54,7 @@ void StubHelperSection<ARM64>::copy_buf(Context<ARM64> &ctx) {
buf[0] |= encode_page(page(dyld_private) - page(this->hdr.addr));
buf[1] |= bits(dyld_private, 11, 0) << 10;
u64 stub_binder = get_symbol(ctx, "dyld_stub_binder")->get_addr(ctx);
u64 stub_binder = get_symbol(ctx, "dyld_stub_binder")->get_got_addr(ctx);
buf[3] |= encode_page(page(stub_binder) - page(this->hdr.addr - 12));
buf[4] |= bits(stub_binder, 11, 0) << 10;
@ -151,7 +151,8 @@ void Subsection<ARM64>::scan_relocations(Context<ARM64> &ctx) {
break;
case ARM64_RELOC_TLVP_LOAD_PAGE21:
case ARM64_RELOC_TLVP_LOAD_PAGEOFF12:
sym->flags |= NEEDS_THREAD_PTR;
if (sym->is_imported)
sym->flags |= NEEDS_THREAD_PTR;
break;
}

View File

@ -533,8 +533,9 @@ static int do_main(int argc, char **argv) {
for (ObjectFile<E> *file : ctx.objs)
file->check_duplicate_symbols(ctx);
bool has_pagezero_seg = ctx.arg.pagezero_size;
for (i64 i = 0; i < ctx.segments.size(); i++)
ctx.segments[i]->seg_idx = i + 1;
ctx.segments[i]->seg_idx = (has_pagezero_seg ? i + 1 : i);
for (ObjectFile<E> *file : ctx.objs)
for (std::unique_ptr<Subsection<E> > &subsec : file->subsections)

View File

@ -913,8 +913,13 @@ u64 Symbol<E>::get_got_addr(Context<E> &ctx) const {
template <typename E>
u64 Symbol<E>::get_tlv_addr(Context<E> &ctx) const {
assert(tlv_idx != -1);
return ctx.thread_ptrs.hdr.addr + tlv_idx * E::word_size;
if (is_imported) {
assert(tlv_idx != -1);
return ctx.thread_ptrs.hdr.addr + tlv_idx * E::word_size;
}
assert(subsec);
return subsec->get_addr(ctx) + value;
}
template <typename E>

View File

@ -209,7 +209,8 @@ static std::vector<u8> create_data_in_code_cmd(Context<E> &ctx) {
template <typename E>
static std::vector<u8> create_id_dylib_cmd(Context<E> &ctx) {
std::vector<u8> buf(sizeof(DylibCommand) + ctx.arg.final_output.size() + 1);
std::vector<u8> buf(sizeof(DylibCommand) +
align_to(ctx.arg.final_output.size() + 1, 8));
DylibCommand &cmd = *(DylibCommand *)buf.data();
cmd.cmd = LC_ID_DYLIB;
@ -664,11 +665,12 @@ void BindSection<E>::compute_size(Context<E> &ctx) {
ctx.data_const_seg->seg_idx,
sym->get_got_addr(ctx) - ctx.data_const_seg->cmd.vmaddr);
for (Symbol<E> *sym : ctx.thread_ptrs.syms)
if (sym->is_imported)
enc.add(((DylibFile<E> *)sym->file)->dylib_idx, sym->name, 0,
ctx.data_seg->seg_idx,
sym->get_tlv_addr(ctx) - ctx.data_seg->cmd.vmaddr);
for (Symbol<E> *sym : ctx.thread_ptrs.syms) {
assert(sym->is_imported);
enc.add(((DylibFile<E> *)sym->file)->dylib_idx, sym->name, 0,
ctx.data_seg->seg_idx,
sym->get_tlv_addr(ctx) - ctx.data_seg->cmd.vmaddr);
}
enc.finish();
@ -1307,9 +1309,7 @@ void ThreadPtrsSection<E>::add(Context<E> &ctx, Symbol<E> *sym) {
template <typename E>
void ThreadPtrsSection<E>::copy_buf(Context<E> &ctx) {
u64 *buf = (u64 *)(ctx.buf + this->hdr.offset);
for (i64 i = 0; i < syms.size(); i++)
if (!syms[i]->is_imported)
buf[i] = syms[i]->get_addr(ctx);
memset(buf, 0, this->hdr.size);
}
#define INSTANTIATE(E) \

37
test/macho/data-reloc.sh Executable file
View File

@ -0,0 +1,37 @@
#!/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
cat <<EOF | $CC -o $t/a.o -c -xc - -fPIC
#include <stdio.h>
int a = 5;
int *b = &a;
void print() {
printf("%d %d\n", a, *b);
}
EOF
clang --ld-path=./ld64 -shared -o $t/b.dylib $t/a.o
cat <<EOF | $CC -o $t/c.o -c -xc - -fPIC
void print();
int main() { print(); }
EOF
clang --ld-path=./ld64 -o $t/exe $t/b.dylib $t/c.o
$t/exe | grep -q '^5 5$'
echo OK