Skip to content

Commit

Permalink
[ELF] Export symbols defined by --defsym
Browse files Browse the repository at this point in the history
Previously, symbols defined by `--defsym` would never be exported
because we created a dynamic symbol table before processing `--defsym`.
  • Loading branch information
rui314 committed Aug 12, 2022
1 parent ee68d1f commit 5dd1227
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 58 deletions.
9 changes: 5 additions & 4 deletions elf/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,9 @@ static int elf_main(int argc, char **argv) {
// Apply -exclude-libs
apply_exclude_libs(ctx);

// Create a dummy file containing linker-synthesized symbols.
create_internal_file(ctx);

// Resolve symbols and fix the set of object files that are
// included to the final output.
resolve_symbols(ctx);
Expand Down Expand Up @@ -471,10 +474,8 @@ static int elf_main(int argc, char **argv) {
// Get a list of output sections.
append(ctx.chunks, collect_output_sections(ctx));

// Create a dummy file containing linker-synthesized symbols
// (e.g. `__bss_start`).
ctx.internal_obj = create_internal_file(ctx);
ctx.objs.push_back(ctx.internal_obj);
// Add synthetic symbols such as __ehdr_start or __end.
add_synthetic_symbols(ctx);

// Beyond this point, no new files will be added to ctx.objs
// or ctx.dsos.
Expand Down
15 changes: 6 additions & 9 deletions elf/mold.h
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,7 @@ std::vector<std::string> parse_nonpositional_args(Context<E> &ctx);
// passes.cc
//

template <typename E> void create_internal_file(Context<E> &);
template <typename E> void apply_exclude_libs(Context<E> &);
template <typename E> void create_synthetic_sections(Context<E> &);
template <typename E> void set_file_priority(Context<E> &);
Expand All @@ -1307,7 +1308,7 @@ template <typename E> void eliminate_comdats(Context<E> &);
template <typename E> void convert_common_symbols(Context<E> &);
template <typename E> void compute_merged_section_sizes(Context<E> &);
template <typename E> void bin_sections(Context<E> &);
template <typename E> ObjectFile<E> *create_internal_file(Context<E> &);
template <typename E> void add_synthetic_symbols(Context<E> &);
template <typename E> void check_cet_errors(Context<E> &);
template <typename E> void print_dependencies(Context<E> &);
template <typename E> void print_dependencies(Context<E> &);
Expand Down Expand Up @@ -1586,7 +1587,6 @@ struct Context {
tbb::concurrent_vector<std::unique_ptr<SharedFile<E>>> dso_pool;
tbb::concurrent_vector<std::unique_ptr<u8[]>> string_pool;
tbb::concurrent_vector<std::unique_ptr<MappedFile<Context<E>>>> mf_pool;
tbb::concurrent_vector<std::vector<ElfRel<E>>> rel_pool;

// Symbol auxiliary data
std::vector<SymbolAux> symbol_aux;
Expand All @@ -1597,7 +1597,9 @@ struct Context {
// Input files
std::vector<ObjectFile<E> *> objs;
std::vector<SharedFile<E> *> dsos;

ObjectFile<E> *internal_obj = nullptr;
std::vector<ElfSym<E>> internal_esyms;

// Output buffer
std::unique_ptr<OutputFile<Context<E>>> output_file;
Expand Down Expand Up @@ -1783,7 +1785,7 @@ class Symbol {
bool has_got(Context<E> &ctx) const;

bool is_absolute() const;
bool is_relative() const;
bool is_relative() const { return !is_absolute(); }
bool is_local() const;

InputSection<E> *get_input_section() const;
Expand Down Expand Up @@ -2487,16 +2489,11 @@ inline bool Symbol<E>::has_got(Context<E> &ctx) const {

template <typename E>
inline bool Symbol<E>::is_absolute() const {
if (file->is_dso)
if (file && file->is_dso)
return esym().is_abs();
return !is_imported && !get_frag() && shndx == 0;
}

template <typename E>
inline bool Symbol<E>::is_relative() const {
return !is_absolute();
}

template<typename E>
inline bool Symbol<E>::is_local() const {
return !is_imported && !is_exported;
Expand Down
94 changes: 49 additions & 45 deletions elf/passes.cc
Original file line number Diff line number Diff line change
Expand Up @@ -351,29 +351,55 @@ void bin_sections(Context<E> &ctx) {
// Create a dummy object file containing linker-synthesized
// symbols.
template <typename E>
ObjectFile<E> *create_internal_file(Context<E> &ctx) {
void create_internal_file(Context<E> &ctx) {
ObjectFile<E> *obj = new ObjectFile<E>;
ctx.obj_pool.emplace_back(obj);
ctx.internal_obj = obj;
ctx.objs.push_back(obj);

// Create linker-synthesized symbols.
auto *esyms = new std::vector<ElfSym<E>>(1);
ctx.internal_esyms.resize(1);

obj->symbols.push_back(new Symbol<E>);
obj->first_global = 1;
obj->is_alive = true;
obj->features = -1;
obj->priority = 1;

auto add = [&](std::string_view name, u8 st_type = STT_NOTYPE) {
// Add symbols for --defsym.
for (i64 i = 0; i < ctx.arg.defsyms.size(); i++) {
Symbol<E> *sym = ctx.arg.defsyms[i].first;
obj->symbols.push_back(sym);

ElfSym<E> esym;
memset(&esym, 0, sizeof(esym));
esym.st_type = STT_NOTYPE;
esym.st_shndx = SHN_ABS;
esym.st_bind = STB_GLOBAL;
esym.st_visibility = STV_DEFAULT;
ctx.internal_esyms.push_back(esym);
};

obj->elf_syms = ctx.internal_esyms;
obj->sym_fragments.resize(ctx.internal_esyms.size());
obj->symvers.resize(ctx.internal_esyms.size() - 1);
}

template <typename E>
void add_synthetic_symbols(Context<E> &ctx) {
ObjectFile<E> &obj = *ctx.internal_obj;

auto add = [&](std::string_view name) {
ElfSym<E> esym;
memset(&esym, 0, sizeof(esym));
esym.st_type = st_type;
esym.st_type = STT_NOTYPE;
esym.st_shndx = SHN_ABS;
esym.st_bind = STB_GLOBAL;
esym.st_visibility = STV_HIDDEN;
esyms->push_back(esym);
ctx.internal_esyms.push_back(esym);

Symbol<E> *sym = get_symbol(ctx, name);
obj->symbols.push_back(sym);
obj.symbols.push_back(sym);
return sym;
};

Expand Down Expand Up @@ -422,53 +448,30 @@ ObjectFile<E> *create_internal_file(Context<E> &ctx) {
}

for (Chunk<E> *chunk : ctx.chunks) {
if (!is_c_identifier(chunk->name))
continue;

add(save_string(ctx, "__start_" + std::string(chunk->name)));
add(save_string(ctx, "__stop_" + std::string(chunk->name)));
if (is_c_identifier(chunk->name)) {
add(save_string(ctx, "__start_" + std::string(chunk->name)));
add(save_string(ctx, "__stop_" + std::string(chunk->name)));
}
}

i64 first_defsym = obj->symbols.size();

for (i64 i = 0; i < ctx.arg.defsyms.size(); i++) {
Symbol<E> *sym = ctx.arg.defsyms[i].first;
ElfSym<E> esym;
memset(&esym, 0, sizeof(esym));
esym.st_type = STT_NOTYPE;
esym.st_shndx = SHN_ABS;
esym.st_bind = STB_GLOBAL;
esym.st_visibility = STV_DEFAULT;
esyms->push_back(esym);
obj->symbols.push_back(sym);
};

obj->elf_syms = *esyms;
obj->sym_fragments.resize(obj->elf_syms.size());
obj.elf_syms = ctx.internal_esyms;
obj.sym_fragments.resize(ctx.internal_esyms.size());
obj.symvers.resize(ctx.internal_esyms.size() - 1);

i64 num_globals = obj->elf_syms.size() - obj->first_global;
obj->symvers.resize(num_globals);
obj.resolve_symbols(ctx);

obj->resolve_symbols(ctx);

for (i64 i = obj->first_global; i < first_defsym; i++)
obj->symbols[i]->shndx = -1; // dummy value to make it a relative symbol
// Make all synthetic symbols relative ones.
for (Symbol<E> *sym : obj.symbols)
sym->shndx = -1; // dummy value to make it a relative symbol

// Make defsym symbols absolute if necessary.
for (i64 i = 0; i < ctx.arg.defsyms.size(); i++) {
Symbol<E> *sym = ctx.arg.defsyms[i].first;
std::variant<Symbol<E> *, u64> val = ctx.arg.defsyms[i].second;

if (Symbol<E> **sym2 = std::get_if<Symbol<E> *>(&val))
if ((*sym2)->is_relative())
sym->shndx = -1; // dummy value to make it a relative symbol
if (std::holds_alternative<u64>(val) ||
std::get<Symbol<E> *>(val)->is_absolute())
sym->shndx = 0;
}

ctx.on_exit.push_back([=] {
delete esyms;
delete obj->symbols[0];
});

return obj;
}

template <typename E>
Expand Down Expand Up @@ -1696,6 +1699,7 @@ void write_dependency_file(Context<E> &ctx) {
}

#define INSTANTIATE(E) \
template void create_internal_file(Context<E> &); \
template void apply_exclude_libs(Context<E> &); \
template void create_synthetic_sections(Context<E> &); \
template void resolve_symbols(Context<E> &); \
Expand All @@ -1704,7 +1708,7 @@ void write_dependency_file(Context<E> &ctx) {
template void convert_common_symbols(Context<E> &); \
template void compute_merged_section_sizes(Context<E> &); \
template void bin_sections(Context<E> &); \
template ObjectFile<E> *create_internal_file(Context<E> &); \
template void add_synthetic_symbols(Context<E> &); \
template void check_cet_errors(Context<E> &); \
template void print_dependencies(Context<E> &); \
template void print_dependencies_full(Context<E> &); \
Expand Down
1 change: 1 addition & 0 deletions test/elf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ set(MOLD_ELF_TESTS
debug-macro-section
default-symver
defsym
defsym2
demangle-rust
demangle
dependency-file
Expand Down
22 changes: 22 additions & 0 deletions test/elf/defsym2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/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 ... "
t=out/test/elf/$MACHINE/$testname
mkdir -p $t

cat <<EOF | $CC -fPIC -o $t/a.o -c -xc -
void foo() {}
EOF

$CC -B. -o $t/b.so -shared -Wl,-defsym=bar=foo $t/a.o
nm -D $t/b.so

echo OK

0 comments on commit 5dd1227

Please sign in to comment.