Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions libwild/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,12 +628,24 @@ impl platform::Platform for Elf {
.section_group_end(output_section_id::FINI_ARRAY, "__fini_array_end")
.hide();

symbols.section_end(output_section_id::TEXT, "etext");
symbols.section_end(output_section_id::TEXT, "_etext");
symbols.section_end(output_section_id::TEXT, "__etext");
// GNU ld doesn't emit these symbols in shared libraries, so we hide them
let hidden = output_kind.is_shared_object();
symbols
.section_end(output_section_id::TEXT, "etext")
.set_hidden(hidden);
symbols
.section_end(output_section_id::TEXT, "_etext")
.set_hidden(hidden);
symbols
.section_end(output_section_id::TEXT, "__etext")
.set_hidden(hidden);

symbols.section_end(output_section_id::BSS, "end");
symbols.section_end(output_section_id::BSS, "_end");
symbols
.section_end(output_section_id::BSS, "end")
.set_hidden(hidden);
symbols
.section_end(output_section_id::BSS, "_end")
.set_hidden(hidden);
symbols.section_end(output_section_id::BSS, "__end").hide();

// TODO: define the symbol only on RISC-V target
Expand All @@ -642,8 +654,12 @@ impl platform::Platform for Elf {
crate::elf::GLOBAL_POINTER_SYMBOL_NAME,
);

symbols.section_end(output_section_id::DATA, "edata");
symbols.section_end(output_section_id::DATA, "_edata");
symbols
.section_end(output_section_id::DATA, "edata")
.set_hidden(hidden);
symbols
.section_end(output_section_id::DATA, "_edata")
.set_hidden(hidden);

symbols
.section_start(output_section_id::TDATA, "__tdata_start")
Expand Down
5 changes: 5 additions & 0 deletions libwild/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,11 @@ impl<'data> InternalSymDefInfo<'data> {
self.is_hidden = true;
self
}

pub(crate) fn set_hidden(&mut self, hidden: bool) -> &mut Self {
self.is_hidden = hidden;
self
}
}

impl<'data, P: Platform> ParsedInputObject<'data, P> {
Expand Down
28 changes: 28 additions & 0 deletions wild/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,9 @@
//!
//! size=N: Type: Integer. Asserts the st_size of the symbol. Useful for verifying that
//! size-changing relaxations (e.g. RISC-V call relaxation) were applied.
//!
//! binding=local|global|weak: Type: string. Asserts the binding of the symbol (STB_LOCAL,
//! STB_GLOBAL or STB_WEAK).

mod external_tests;

Expand Down Expand Up @@ -897,6 +900,8 @@ struct SymtabAssertions {
absolute_address: Option<u64>,

size: Option<u64>,

binding: Option<String>,
}

impl ExpectedSymtabEntry {
Expand Down Expand Up @@ -2987,6 +2992,28 @@ fn verify_symbol_assertions(
);
}
}

if let Some(expected_binding) = exp.assertions.binding.as_deref() {
if !matches!(expected_binding, "local" | "global" | "weak") {
bail!(
"Invalid binding value `{expected_binding}` for symbol `{name}`. \
Must be one of: local, global, weak"
);
}
let actual_binding = if sym.is_weak() {
"weak"
} else if sym.is_global() {
"global"
} else {
"local"
};
if expected_binding != actual_binding {
bail!(
"Expected symbol `{name}` to have binding `{expected_binding}`, \
but it actually had binding `{actual_binding}`"
);
}
}
}

let missing: Vec<&str> = missing.into_keys().collect();
Expand Down Expand Up @@ -3559,6 +3586,7 @@ fn integration_test(
"linker-script-executable.c",
"linker-script-provide.c",
"linker-defined-provide.c",
"linker-defined-syms-shared.c",
"libc-ifunc.c",
"libc-integration.c",
"rust-integration.rs",
Expand Down
35 changes: 35 additions & 0 deletions wild/tests/sources/linker-defined-syms-shared.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Test that linker-defined section boundary symbols are not exported to .dynsym
// in shared objects, matching GNU ld behavior.
// TODO: Once linker-defined symbol GC is implemented, add a variant that
// references these symbols and asserts they appear as GLOBAL in .dynsym.
//#LinkArgs:-shared -z now
//#RunEnabled:false
//#CompArgs:-fPIC
//#DiffEnabled:false

// These symbols should NOT appear in .dynsym for shared objects
//#NoDynSym:etext
//#NoDynSym:_etext
//#NoDynSym:__etext
//#NoDynSym:end
//#NoDynSym:_end
//#NoDynSym:edata
//#NoDynSym:_edata

// Wild keeps them in .symtab as LOCAL. GNU ld removes them entirely with
// --gc-sections, so we only assert this for Wild.
//#SkipLinker:ld
//#ExpectSym:etext binding=local
//#ExpectSym:_etext binding=local
//#ExpectSym:__etext binding=local
//#ExpectSym:end binding=local
//#ExpectSym:_end binding=local
//#ExpectSym:edata binding=local
//#ExpectSym:_edata binding=local

// data_var and bss_var ensure .data and .bss sections exist so that
// edata, _edata, end and _end symbols are emitted by Wild.
int data_var = 1;
int bss_var;

void foo(void) {}
Loading