mirror of
https://github.com/rui314/mold.git
synced 2024-09-11 13:06:59 +03:00
Compare commits
7 Commits
b0b015bc2e
...
b78f237a68
Author | SHA1 | Date | |
---|---|---|---|
|
b78f237a68 | ||
|
1582b720d5 | ||
|
710127977e | ||
|
8e07496e08 | ||
|
163f5db0d1 | ||
|
be2e1b17cd | ||
|
5f5e73360b |
@ -50,6 +50,8 @@ struct UstarHeader {
|
||||
char pad[12];
|
||||
};
|
||||
|
||||
static_assert(sizeof(UstarHeader) == 512);
|
||||
|
||||
static std::string encode_path(std::string basedir, std::string path) {
|
||||
path = path_clean(basedir + "/" + path);
|
||||
|
||||
@ -81,6 +83,7 @@ void TarWriter::append(std::string path, std::string_view data) {
|
||||
|
||||
std::string attr = encode_path(basedir, path);
|
||||
snprintf(pax.size, sizeof(pax.size), "%011zo", attr.size());
|
||||
pax.name[0] = '/';
|
||||
pax.typeflag[0] = 'x';
|
||||
pax.finalize();
|
||||
fwrite(&pax, sizeof(pax), 1, out);
|
||||
|
@ -638,13 +638,13 @@ void RangeExtensionThunk<E>::copy_buf(Context<E> &ctx) {
|
||||
// It has two entry points: +0 for Thumb and +4 for ARM.
|
||||
const u8 entry[] = {
|
||||
// .thumb
|
||||
0xfc, 0x46, // mov ip, pc
|
||||
0x60, 0x47, // bx ip # jumps to the following `ldr` insn
|
||||
0x78, 0x47, // bx pc # jumps to 1f
|
||||
0xc0, 0x46, // nop
|
||||
// .arm
|
||||
0x04, 0xc0, 0x9f, 0xe5, // ldr ip, 2f
|
||||
0x0f, 0xc0, 0x8c, 0xe0, // 1: add ip, ip, pc
|
||||
0x04, 0xc0, 0x9f, 0xe5, // 1: ldr ip, 3f
|
||||
0x0f, 0xc0, 0x8c, 0xe0, // 2: add ip, ip, pc
|
||||
0x1c, 0xff, 0x2f, 0xe1, // bx ip
|
||||
0x00, 0x00, 0x00, 0x00, // 2: .word sym - 1b
|
||||
0x00, 0x00, 0x00, 0x00, // 3: .word sym - 2b
|
||||
};
|
||||
|
||||
static_assert(E::thunk_hdr_size == sizeof(hdr));
|
||||
|
@ -44,7 +44,7 @@ template <typename E>
|
||||
void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
|
||||
std::span<const ElfRel<E>> rels = get_rels(ctx);
|
||||
|
||||
ElfRel<E> *dynrel = nullptr;
|
||||
[[maybe_unused]] ElfRel<E> *dynrel = nullptr;
|
||||
if (ctx.reldyn)
|
||||
dynrel = (ElfRel<E> *)(ctx.buf + ctx.reldyn->shdr.sh_offset +
|
||||
file.reldyn_offset + this->reldyn_offset);
|
||||
@ -60,7 +60,7 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
|
||||
Symbol<E> &sym = *file.symbols[rel.r_sym];
|
||||
u8 *loc = base + rel.r_offset;
|
||||
|
||||
auto check = [&](i64 val, i64 lo, i64 hi) {
|
||||
[[maybe_unused]] auto check = [&](i64 val, i64 lo, i64 hi) {
|
||||
if (val < lo || hi <= val)
|
||||
Error(ctx) << *this << ": relocation " << rel << " against "
|
||||
<< sym << " out of range: " << val << " is not in ["
|
||||
@ -105,7 +105,6 @@ void InputSection<E>::apply_reloc_alloc(Context<E> &ctx, u8 *base) {
|
||||
|
||||
u64 S = sym.get_addr(ctx);
|
||||
u64 A = rel.r_addend;
|
||||
u64 P = get_addr() + rel.r_offset;
|
||||
|
||||
switch (rel.r_type) {
|
||||
case R_MIPS_64:
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "mold.h"
|
||||
#include "../common/cmdline.h"
|
||||
|
||||
#include <random>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
#include <sys/stat.h>
|
||||
@ -406,6 +407,7 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
bool warn_shared_textrel = false;
|
||||
std::optional<SeparateCodeKind> z_separate_code;
|
||||
std::optional<bool> z_relro;
|
||||
std::optional<u64> shuffle_sections_seed;
|
||||
std::unordered_set<std::string_view> rpaths;
|
||||
|
||||
auto add_rpath = [&](std::string_view arg) {
|
||||
@ -635,7 +637,7 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
ctx.arg.shuffle_sections = SHUFFLE_SECTIONS_SHUFFLE;
|
||||
} else if (read_eq("shuffle-sections")) {
|
||||
ctx.arg.shuffle_sections = SHUFFLE_SECTIONS_SHUFFLE;
|
||||
ctx.arg.shuffle_sections_seed = parse_number(ctx, "shuffle-sections", arg);
|
||||
shuffle_sections_seed = parse_number(ctx, "shuffle-sections", arg);
|
||||
} else if (read_flag("reverse-sections")) {
|
||||
ctx.arg.shuffle_sections = SHUFFLE_SECTIONS_REVERSE;
|
||||
} else if (read_flag("rosegment")) {
|
||||
@ -1181,6 +1183,14 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx) {
|
||||
if (ctx.arg.relocatable)
|
||||
ctx.arg.is_static = true;
|
||||
|
||||
if (ctx.arg.shuffle_sections == SHUFFLE_SECTIONS_SHUFFLE) {
|
||||
if (shuffle_sections_seed)
|
||||
ctx.arg.shuffle_sections_seed = *shuffle_sections_seed;
|
||||
else
|
||||
ctx.arg.shuffle_sections_seed =
|
||||
((u64)std::random_device()() << 32) | std::random_device()();
|
||||
}
|
||||
|
||||
// --section-order implies `-z separate-loadable-segments`
|
||||
if (z_separate_code)
|
||||
ctx.arg.z_separate_code = *z_separate_code;
|
||||
|
@ -1396,7 +1396,8 @@ SharedFile<E>::mark_live_objects(Context<E> &ctx,
|
||||
if (sym.is_traced)
|
||||
print_trace_symbol(ctx, *this, esym, sym);
|
||||
|
||||
if (esym.is_undef() && sym.file && !sym.file->is_alive.test_and_set()) {
|
||||
if (esym.is_undef() && !esym.is_weak() && sym.file &&
|
||||
!sym.file->is_alive.test_and_set()) {
|
||||
feeder(sym.file);
|
||||
|
||||
if (sym.is_traced)
|
||||
|
@ -1766,10 +1766,10 @@ struct Context {
|
||||
i64 spare_dynamic_tags = 5;
|
||||
i64 thread_count = 0;
|
||||
i64 z_stack_size = 0;
|
||||
u64 shuffle_sections_seed;
|
||||
std::string_view emulation;
|
||||
std::optional<Glob> unique;
|
||||
std::optional<u64> physical_image_base;
|
||||
std::optional<u64> shuffle_sections_seed;
|
||||
std::string Map;
|
||||
std::string chroot;
|
||||
std::string dependency_file;
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <random>
|
||||
#include <regex>
|
||||
#include <shared_mutex>
|
||||
#include <tbb/parallel_for_each.h>
|
||||
@ -1109,37 +1108,35 @@ template <typename E>
|
||||
void shuffle_sections(Context<E> &ctx) {
|
||||
Timer t(ctx, "shuffle_sections");
|
||||
|
||||
auto is_eligible = [](OutputSection<E> &osec) {
|
||||
return osec.name != ".init" && osec.name != ".fini" &&
|
||||
osec.name != ".ctors" && osec.name != ".dtors" &&
|
||||
osec.name != ".init_array" && osec.name != ".preinit_array" &&
|
||||
osec.name != ".fini_array";
|
||||
auto is_eligible = [](OutputSection<E> *osec) {
|
||||
if (osec) {
|
||||
std::string_view name = osec->name;
|
||||
return name != ".init" && name != ".fini" &&
|
||||
name != ".ctors" && name != ".dtors" &&
|
||||
name != ".init_array" && name != ".preinit_array" &&
|
||||
name != ".fini_array";
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
switch (ctx.arg.shuffle_sections) {
|
||||
case SHUFFLE_SECTIONS_NONE:
|
||||
unreachable();
|
||||
case SHUFFLE_SECTIONS_SHUFFLE: {
|
||||
u64 seed;
|
||||
if (ctx.arg.shuffle_sections_seed)
|
||||
seed = *ctx.arg.shuffle_sections_seed;
|
||||
else
|
||||
seed = ((u64)std::random_device()() << 32) | std::random_device()();
|
||||
|
||||
tbb::parallel_for_each(ctx.chunks, [&](Chunk<E> *chunk) {
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
if (is_eligible(*osec))
|
||||
shuffle(osec->members, seed + hash_string(osec->name));
|
||||
if (OutputSection<E> *osec = chunk->to_osec(); is_eligible(osec)) {
|
||||
u64 seed = ctx.arg.shuffle_sections_seed + hash_string(osec->name);
|
||||
shuffle(osec->members, seed);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case SHUFFLE_SECTIONS_REVERSE:
|
||||
tbb::parallel_for_each(ctx.chunks, [&](Chunk<E> *chunk) {
|
||||
if (OutputSection<E> *osec = chunk->to_osec())
|
||||
if (is_eligible(*osec))
|
||||
std::reverse(osec->members.begin(), osec->members.end());
|
||||
if (OutputSection<E> *osec = chunk->to_osec(); is_eligible(osec))
|
||||
std::reverse(osec->members.begin(), osec->members.end());
|
||||
});
|
||||
break;
|
||||
default:
|
||||
unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,10 @@ void-*)
|
||||
xbps-install -Sy bash make cmake openssl-devel zlib-devel gcc
|
||||
xbps-install -Sy tar diffutils util-linux
|
||||
;;
|
||||
alpine-*)
|
||||
apk update
|
||||
apk add bash make openssl-dev linux-headers cmake zlib-dev gcc g++
|
||||
;;
|
||||
*)
|
||||
echo "Error: don't know anything about build dependencies on $ID-$VERSION_ID"
|
||||
exit 1
|
||||
|
@ -22,6 +22,5 @@ $CC -B. -o $t/exe $t/a.o \
|
||||
|
||||
$OBJDUMP -dr $t/exe | grep -F -A7 '<fn1$thunk>:' > $t/log
|
||||
|
||||
grep -Eq 'mov\s+ip, pc' $t/log
|
||||
grep -Eq 'bx\s+ip' $t/log
|
||||
grep -Eq 'bx\s+pc' $t/log
|
||||
grep -Eq 'add\s+ip, ip, pc' $t/log
|
||||
|
33
test/elf/as-needed-dso2.sh
Executable file
33
test/elf/as-needed-dso2.sh
Executable file
@ -0,0 +1,33 @@
|
||||
#!/bin/bash
|
||||
. $(dirname $0)/common.inc
|
||||
|
||||
cat <<EOF | $CC -c -fPIC -o $t/a.o -xc -
|
||||
int foo() {
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
cat <<EOF | $CC -c -fPIC -o $t/b.o -xc -
|
||||
__attribute__((weak)) int foo();
|
||||
|
||||
int bar() {
|
||||
if (foo) return foo();
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
|
||||
cat <<EOF | $CC -xc -c -o $t/c.o -
|
||||
int bar();
|
||||
|
||||
int main() {
|
||||
return bar();
|
||||
}
|
||||
EOF
|
||||
|
||||
$CC -B. -shared -o $t/libfoo.so $t/a.o
|
||||
$CC -B. -shared -o $t/libbar.so $t/b.o
|
||||
$CC -B. -o $t/exe $t/c.o -L$t -Wl,--as-needed -lfoo -lbar
|
||||
|
||||
readelf --dynamic $t/exe > $t/log
|
||||
! grep libfoo.so $t/log || false
|
||||
grep -q libbar.so $t/log
|
@ -3,6 +3,9 @@
|
||||
|
||||
[ $MACHINE = ppc64 ] && skip
|
||||
|
||||
# BusyBox's grep can't handle capture groups (e.g. \1, \2 ...)
|
||||
grep --version 2>&1 | grep BusyBox && skip
|
||||
|
||||
cat <<EOF | $CC -o $t/a.o -c -xc -
|
||||
#include <stdio.h>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user