diff --git a/libwild/src/elf.rs b/libwild/src/elf.rs index 864d6ffc6..a0a4b767b 100644 --- a/libwild/src/elf.rs +++ b/libwild/src/elf.rs @@ -108,7 +108,6 @@ use linker_utils::elf::secnames; use linker_utils::elf::secnames::*; use linker_utils::elf::shf; use linker_utils::elf::sht; -use linker_utils::elf::stt; use linker_utils::relaxation::RelocationModifier; use linker_utils::utils::read_string; use linker_utils::utils::read_u32; @@ -166,7 +165,7 @@ pub(crate) type NoteHeader = object::elf::NoteHeader64; type SectionTable<'data> = object::read::elf::SectionTable<'data, FileHeader>; type SymbolTable<'data> = object::read::elf::SymbolTable<'data, FileHeader>; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default)] pub(crate) struct Elf; #[derive(derive_more::Debug)] @@ -808,7 +807,7 @@ impl platform::Platform for Elf { } fn create_linker_defined_symbols( - symbols: &mut crate::parsing::InternalSymbolsBuilder, + symbols: &mut crate::parsing::InternalSymbolsBuilder, output_kind: OutputKind, args: &ElfArgs, ) { @@ -908,6 +907,8 @@ impl platform::Platform for Elf { // We define _TLS_MODULE_BASE_ either at the start or end of the TLS segment, depending on // whether we're building a shared object or an executable. This symbol is used for TLSDESC. // See https://www.fsfla.org/~lxoliva/writeups/TLS/RFC-TLSDESC-x86.txt for more details. + let mut elf_symbol = SymtabEntry::default(); + elf_symbol.set_st_info(object::elf::STB_GLOBAL, object::elf::STT_TLS); symbols.add_symbol(InternalSymDefInfo { placement: if output_kind == OutputKind::SharedObject { SymbolPlacement::SectionStart(output_section_id::TDATA) @@ -915,8 +916,7 @@ impl platform::Platform for Elf { SymbolPlacement::SectionEnd(output_section_id::TBSS) }, name: b"_TLS_MODULE_BASE_", - elf_symbol_type: stt::TLS, - is_hidden: false, + symbol: elf_symbol, }); // When `-z pack-relative-relocs` is used, Glibc requires this special version to be @@ -1498,12 +1498,12 @@ impl platform::Platform for Elf { fn allocate_internal_symbol( symbol_id: SymbolId, - def_info: &InternalSymDefInfo, + def_info: &InternalSymDefInfo, sizes: &mut OutputSectionPartMap, symbol_db: &SymbolDb, ) -> Result { // PROVIDE_HIDDEN symbols are local, others are global - let symtab_part = if def_info.is_hidden { + let symtab_part = if def_info.symbol.is_hidden() { part_id::SYMTAB_LOCAL } else { part_id::SYMTAB_GLOBAL @@ -1936,6 +1936,10 @@ impl platform::Platform for Elf { ) { *mem_offset = segment_alignment.align_modulo(*file_offset as u64, *mem_offset); } + + fn default_symtab_entry() -> Self::SymtabEntry { + Default::default() + } } impl<'data> platform::ObjectFile<'data> for File<'data> { @@ -2855,6 +2859,16 @@ impl platform::Symbol for SymtabEntry { fn is_gnu_unique(&self) -> bool { self.st_bind() == object::elf::STB_GNU_UNIQUE } + + fn with_hidden(mut self, hidden: bool) -> Self { + self.st_other &= !0x3; + self.st_other |= if hidden { + object::elf::STV_HIDDEN + } else { + object::elf::STV_DEFAULT + }; + self + } } pub(crate) fn convert_elf_visibility(st_visibility: u8) -> Visibility { diff --git a/libwild/src/elf_writer.rs b/libwild/src/elf_writer.rs index f2e3550cd..cdc2ed698 100644 --- a/libwild/src/elf_writer.rs +++ b/libwild/src/elf_writer.rs @@ -114,7 +114,6 @@ use linker_utils::elf::secnames::DYNSYM_SECTION_NAME_STR; use linker_utils::elf::secnames::NOTE_GNU_BUILD_ID_SECTION_NAME_STR; use linker_utils::elf::shf; use linker_utils::elf::sht; -use linker_utils::elf::stt; use linker_utils::loongarch64::highest_relocation_with_bias; use linker_utils::relaxation::RelocationModifier; use linker_utils::relaxation::SectionRelaxDeltas; @@ -2012,9 +2011,8 @@ fn write_symbols<'data>( } if layout.args().should_output_partial_object() { - let e = LittleEndian; for (sym_index, sym) in object.object.symbols.enumerate() { - if !sym.is_undefined(e) { + if !platform::Symbol::is_undefined(sym) { continue; } let Ok(name) = object.object.symbol_name(sym) else { @@ -3592,7 +3590,7 @@ pub(crate) struct EpilogueOffsets { } fn write_linker_script_state<'data, A: Arch>( - script: &LinkerScriptLayoutState, + script: &LinkerScriptLayoutState, table_writer: &mut TableWriter, layout: &ElfLayout<'data>, ) -> Result { @@ -3610,7 +3608,7 @@ fn write_linker_script_state<'data, A: Arch>( } fn write_synthetic_symbols<'data, A: Arch>( - syn: &SyntheticSymbolsLayout, + syn: &SyntheticSymbolsLayout, table_writer: &mut TableWriter, layout: &ElfLayout<'data>, ) -> Result { @@ -3993,7 +3991,7 @@ fn write_linker_script_dynsym( dynsym_writer: &mut SymbolTableWriter, layout: &ElfLayout, symbol_id: SymbolId, - script: &LinkerScriptLayoutState, + script: &LinkerScriptLayoutState, ) -> Result { let local_index = script .internal_symbols @@ -4074,7 +4072,7 @@ fn get_symbol_attributes(layout: &ElfLayout, symbol_id: SymbolId) -> Result<(u32 .output_index_of_section(section_id) .unwrap_or(u32::from(object::elf::SHN_ABS)) }); - Ok((shndx, def_info.elf_symbol_type.raw())) + Ok((shndx, def_info.symbol.st_type())) } crate::grouping::SequencedInput::SyntheticSymbols(_) => { // For other non-object files (e.g. epilogue), default to ABS @@ -4106,7 +4104,7 @@ fn write_internal_dynsym( dynsym_writer: &mut SymbolTableWriter, layout: &ElfLayout, symbol_id: SymbolId, - def_info: &crate::parsing::InternalSymDefInfo, + def_info: &crate::parsing::InternalSymDefInfo, ) -> Result { if matches!( def_info.placement, @@ -4145,7 +4143,7 @@ fn write_defsym_dynsym( dynsym_writer: &mut SymbolTableWriter, layout: &ElfLayout, symbol_id: SymbolId, - def_info: &crate::parsing::InternalSymDefInfo, + def_info: &crate::parsing::InternalSymDefInfo, ) -> Result { debug_assert!(matches!( def_info.placement, @@ -4303,7 +4301,7 @@ fn write_regular_object_dynamic_symbol_definition<'data>( format!("Failed to copy dynamic {}", layout.symbol_debug(symbol_id)) })?; } - } else if sym.is_common(LittleEndian) { + } else if platform::Symbol::is_common(sym) { let symbol_id = sym_def.symbol_id; let resolution = layout.local_symbol_resolution(symbol_id).with_context(|| { format!( @@ -4330,7 +4328,7 @@ fn write_regular_object_dynamic_symbol_definition<'data>( .with_context(|| { format!("Failed to copy dynamic {}", layout.symbol_debug(symbol_id)) })?; - } else if sym.is_absolute(LittleEndian) { + } else if platform::Symbol::is_absolute(sym) { dynamic_symbol_writer .copy_absolute_symbol(sym, name, ValueFlags::empty()) .with_context(|| { @@ -4353,7 +4351,7 @@ fn write_regular_object_dynamic_symbol_definition<'data>( } fn write_internal_symbols( - internal_symbols: &InternalSymbols, + internal_symbols: &InternalSymbols, layout: &ElfLayout, symbol_writer: &mut SymbolTableWriter<'_, '_>, ) -> Result { @@ -4408,7 +4406,7 @@ fn write_internal_symbols( .transpose()? .unwrap_or(u32::from(object::elf::SHN_ABS)); - (shndx, def_info.elf_symbol_type.raw()) + (shndx, def_info.symbol.st_type()) }; // Move symbols that are in our header (section 0) into the first section, otherwise they'll @@ -4419,7 +4417,7 @@ fn write_internal_symbols( let mut address = resolution.value(); - if def_info.elf_symbol_type == stt::TLS { + if platform::Symbol::is_tls(&def_info.symbol) { address -= layout.tls_start_address(); } @@ -4431,7 +4429,7 @@ fn write_internal_symbols( } // PROVIDE_HIDDEN symbols should be local, not global - let st_bind = if def_info.is_hidden { + let st_bind = if platform::Symbol::is_hidden(&def_info.symbol) { object::elf::STB_LOCAL } else { object::elf::STB_GLOBAL @@ -5061,7 +5059,7 @@ impl<'out> ProgramHeaderWriter<'out> { } fn write_internal_symbols_plt_got_entries<'data, A: Arch>( - internal_symbols: &InternalSymbols, + internal_symbols: &InternalSymbols, table_writer: &mut TableWriter, layout: &ElfLayout<'data>, ) -> Result { diff --git a/libwild/src/grouping.rs b/libwild/src/grouping.rs index 99c655146..469104cbf 100644 --- a/libwild/src/grouping.rs +++ b/libwild/src/grouping.rs @@ -20,9 +20,9 @@ use std::fmt::Display; #[derive(Debug)] pub(crate) enum Group<'data, P: Platform> { - Prelude(Prelude<'data>), + Prelude(Prelude<'data, P>), Objects(&'data [SequencedInputObject<'data, P>]), - LinkerScripts(Vec>), + LinkerScripts(Vec>), SyntheticSymbols(SyntheticSymbols), #[cfg(feature = "plugins")] LtoInputs(Vec>), @@ -36,17 +36,17 @@ pub(crate) struct SequencedInputObject<'data, P: Platform> { } #[derive(Debug)] -pub(crate) struct SequencedLinkerScript<'data> { - pub(crate) parsed: ProcessedLinkerScript<'data>, +pub(crate) struct SequencedLinkerScript<'data, P: Platform> { + pub(crate) parsed: ProcessedLinkerScript<'data, P>, pub(crate) symbol_id_range: SymbolIdRange, pub(crate) file_id: FileId, } #[derive(Debug)] pub(crate) enum SequencedInput<'db, 'data, P: Platform> { - Prelude(&'db Prelude<'data>), + Prelude(&'db Prelude<'data, P>), Object(&'data SequencedInputObject<'data, P>), - LinkerScript(&'db SequencedLinkerScript<'data>), + LinkerScript(&'db SequencedLinkerScript<'data, P>), SyntheticSymbols(&'db SyntheticSymbols), #[cfg(feature = "plugins")] LtoInput(&'db crate::linker_plugins::LtoInput<'data>), @@ -103,7 +103,7 @@ impl<'data, P: Platform> Group<'data, P> { pub(crate) fn create_groups<'data, P: Platform>( symbol_db: &mut SymbolDb<'data, P>, parsed_objects: Vec>>, - linker_scripts: Vec>, + linker_scripts: Vec>, ) { timing_phase!("Group files"); @@ -159,7 +159,7 @@ pub(crate) fn create_groups<'data, P: Platform>( } } - let linker_scripts: Vec> = linker_scripts + let linker_scripts: Vec> = linker_scripts .into_iter() .enumerate() .map(|(i, script)| { @@ -278,7 +278,7 @@ impl<'data, P: Platform> SequencedInputObject<'data, P> { } } -impl<'data> SequencedLinkerScript<'data> { +impl<'data, P: Platform> SequencedLinkerScript<'data, P> { pub(crate) fn symbol_name(&self, symbol_id: SymbolId) -> UnversionedSymbolName<'data> { let local_index = self.symbol_id_range.id_to_offset(symbol_id); UnversionedSymbolName::new(self.parsed.symbol_defs[local_index].name) diff --git a/libwild/src/layout.rs b/libwild/src/layout.rs index 2fa1e1f84..5fd54709b 100644 --- a/libwild/src/layout.rs +++ b/libwild/src/layout.rs @@ -47,8 +47,6 @@ use crate::program_segments::ProgramSegments; use crate::resolution; use crate::resolution::NotLoaded; use crate::resolution::ResolvedGroup; -use crate::resolution::ResolvedLinkerScript; -use crate::resolution::ResolvedSyntheticSymbols; use crate::resolution::SectionSlot; use crate::resolution::UnloadedSection; use crate::sharding::ShardKey; @@ -382,7 +380,7 @@ fn update_defsym_symbol_resolutions<'data, P: Platform>( fn update_defsym_symbol_resolution<'data, P: Platform>( symbol_id: SymbolId, - def_info: &InternalSymDefInfo, + def_info: &InternalSymDefInfo

, symbol_db: &SymbolDb<'data, P>, resolutions: &mut [Option>], ) -> Result { @@ -575,10 +573,10 @@ pub(crate) enum FileLayout<'data, P: Platform> { Prelude(PreludeLayout<'data, P>), Object(ObjectLayout<'data, P>), Dynamic(DynamicLayout<'data, P>), - SyntheticSymbols(SyntheticSymbolsLayout<'data>), + SyntheticSymbols(SyntheticSymbolsLayout<'data, P>), Epilogue(EpilogueLayout

), NotLoaded, - LinkerScript(LinkerScriptLayoutState<'data>), + LinkerScript(LinkerScriptLayoutState<'data, P>), } /// Address information for a symbol. @@ -633,16 +631,16 @@ pub(crate) enum FileLayoutState<'data, P: Platform> { Object(ObjectLayoutState<'data, P>), Dynamic(DynamicLayoutState<'data, P>), NotLoaded(NotLoaded), - SyntheticSymbols(SyntheticSymbolsLayoutState<'data>), + SyntheticSymbols(SyntheticSymbolsLayoutState<'data, P>), Epilogue(EpilogueLayoutState

), - LinkerScript(LinkerScriptLayoutState<'data>), + LinkerScript(LinkerScriptLayoutState<'data, P>), } /// Data that doesn't come from any input files, but needs to be written by the linker. pub(crate) struct PreludeLayoutState<'data, P: Platform> { file_id: FileId, symbol_id_range: SymbolIdRange, - internal_symbols: InternalSymbols<'data>, + internal_symbols: InternalSymbols<'data, P>, entry_symbol_id: Option, identity: String, header_info: Option, @@ -650,10 +648,10 @@ pub(crate) struct PreludeLayoutState<'data, P: Platform> { pub(crate) format_specific: P::PreludeLayoutStateExt, } -pub(crate) struct SyntheticSymbolsLayoutState<'data> { +pub(crate) struct SyntheticSymbolsLayoutState<'data, P: Platform> { file_id: FileId, symbol_id_range: SymbolIdRange, - internal_symbols: InternalSymbols<'data>, + internal_symbols: InternalSymbols<'data, P>, } pub(crate) struct EpilogueLayoutState { @@ -661,16 +659,16 @@ pub(crate) struct EpilogueLayoutState { } #[derive(Debug)] -pub(crate) struct LinkerScriptLayoutState<'data> { +pub(crate) struct LinkerScriptLayoutState<'data, P: Platform> { file_id: FileId, input: InputRef<'data>, symbol_id_range: SymbolIdRange, - pub(crate) internal_symbols: InternalSymbols<'data>, + pub(crate) internal_symbols: InternalSymbols<'data, P>, } #[derive(Debug)] -pub(crate) struct SyntheticSymbolsLayout<'data> { - pub(crate) internal_symbols: InternalSymbols<'data>, +pub(crate) struct SyntheticSymbolsLayout<'data, P: Platform> { + pub(crate) internal_symbols: InternalSymbols<'data, P>, } #[derive(Debug)] @@ -699,14 +697,14 @@ pub(crate) struct PreludeLayout<'data, P: Platform> { pub(crate) entry_symbol_id: Option, pub(crate) identity: String, pub(crate) header_info: HeaderInfo, - pub(crate) internal_symbols: InternalSymbols<'data>, + pub(crate) internal_symbols: InternalSymbols<'data, P>, pub(crate) dynamic_linker: Option, pub(crate) format_specific: P::PreludeLayoutExt, } #[derive(Debug)] -pub(crate) struct InternalSymbols<'data> { - pub(crate) symbol_definitions: Vec>, +pub(crate) struct InternalSymbols<'data, P: Platform> { + pub(crate) symbol_definitions: Vec>, pub(crate) start_symbol_id: SymbolId, } @@ -908,7 +906,7 @@ impl<'data, P: Platform> SymbolRequestHandler<'data, P> for PreludeLayoutState<' } } -impl HandlerData for LinkerScriptLayoutState<'_> { +impl HandlerData for LinkerScriptLayoutState<'_, P> { fn symbol_id_range(&self) -> SymbolIdRange { self.symbol_id_range } @@ -918,7 +916,7 @@ impl HandlerData for LinkerScriptLayoutState<'_> { } } -impl<'data, P: Platform> SymbolRequestHandler<'data, P> for LinkerScriptLayoutState<'data> { +impl<'data, P: Platform> SymbolRequestHandler<'data, P> for LinkerScriptLayoutState<'data, P> { fn load_symbol<'scope, A: Arch>( &mut self, _common: &mut CommonGroupState<'data, P>, @@ -931,7 +929,7 @@ impl<'data, P: Platform> SymbolRequestHandler<'data, P> for LinkerScriptLayoutSt } } -impl HandlerData for SyntheticSymbolsLayoutState<'_> { +impl HandlerData for SyntheticSymbolsLayoutState<'_, P> { fn file_id(&self) -> FileId { self.file_id } @@ -941,7 +939,7 @@ impl HandlerData for SyntheticSymbolsLayoutState<'_> { } } -impl<'data, P: Platform> SymbolRequestHandler<'data, P> for SyntheticSymbolsLayoutState<'data> { +impl<'data, P: Platform> SymbolRequestHandler<'data, P> for SyntheticSymbolsLayoutState<'data, P> { fn load_symbol<'scope, A: Arch>( &mut self, _common: &mut CommonGroupState<'data, P>, @@ -2433,13 +2431,13 @@ impl std::fmt::Display for EpilogueLayoutState

{ } } -impl std::fmt::Display for SyntheticSymbolsLayoutState<'_> { +impl std::fmt::Display for SyntheticSymbolsLayoutState<'_, P> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt("", f) } } -impl std::fmt::Display for LinkerScriptLayoutState<'_> { +impl std::fmt::Display for LinkerScriptLayoutState<'_, P> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.input, f) } @@ -2627,7 +2625,7 @@ pub(crate) fn resolution_flags(rel_kind: RelocationKind) -> ValueFlags { } impl<'data, P: Platform> PreludeLayoutState<'data, P> { - fn new(input_state: resolution::ResolvedPrelude<'data>, args: &P::Args) -> Self { + fn new(input_state: resolution::ResolvedPrelude<'data, P>, args: &P::Args) -> Self { Self { file_id: PRELUDE_FILE_ID, symbol_id_range: SymbolIdRange::prelude(input_state.symbol_definitions.len()), @@ -3139,8 +3137,8 @@ impl<'data, P: Platform> PreludeLayoutState<'data, P> { } } -impl<'data> InternalSymbols<'data> { - fn activate_symbols( +impl<'data, P: Platform> InternalSymbols<'data, P> { + fn activate_symbols( &self, common: &mut CommonGroupState<'data, P>, resources: &GraphResources<'data, '_, P>, @@ -3161,7 +3159,7 @@ impl<'data> InternalSymbols<'data> { } // PROVIDE_HIDDEN symbols should not be exported to dynsym. - if def_info.is_hidden { + if def_info.symbol.is_hidden() { continue; } @@ -3178,11 +3176,11 @@ impl<'data> InternalSymbols<'data> { Ok(()) } - fn allocate_symbol_table_sizes( + fn allocate_symbol_table_sizes( &self, sizes: &mut OutputSectionPartMap, symbol_db: &SymbolDb<'data, P>, - mut should_keep_symbol: impl FnMut(SymbolId, &InternalSymDefInfo) -> bool, + mut should_keep_symbol: impl FnMut(SymbolId, &InternalSymDefInfo

) -> bool, ) -> Result { // Allocate space in the symbol table for the symbols that we define. for (index, def_info) in self.symbol_definitions.iter().enumerate() { @@ -3200,7 +3198,7 @@ impl<'data> InternalSymbols<'data> { Ok(()) } - fn finalise_layout( + fn finalise_layout( &self, memory_offsets: &mut OutputSectionPartMap, resolutions_out: &mut ResolutionWriter

, @@ -3226,7 +3224,7 @@ impl<'data> InternalSymbols<'data> { fn create_start_end_symbol_resolution<'data, P: Platform>( memory_offsets: &mut OutputSectionPartMap, resources: &FinaliseLayoutResources<'_, 'data, P>, - def_info: InternalSymDefInfo, + def_info: InternalSymDefInfo

, symbol_id: SymbolId, ) -> Option> { if !resources.symbol_db.is_canonical(symbol_id) { @@ -3369,8 +3367,10 @@ fn should_emit_undefined_error( } } -impl<'data> SyntheticSymbolsLayoutState<'data> { - fn new(input_state: ResolvedSyntheticSymbols<'data>) -> SyntheticSymbolsLayoutState<'data> { +impl<'data, P: Platform> SyntheticSymbolsLayoutState<'data, P> { + fn new( + input_state: resolution::ResolvedSyntheticSymbols<'data, P>, + ) -> SyntheticSymbolsLayoutState<'data, P> { SyntheticSymbolsLayoutState { file_id: input_state.file_id, symbol_id_range: SymbolIdRange::input( @@ -3384,7 +3384,7 @@ impl<'data> SyntheticSymbolsLayoutState<'data> { } } - fn finalise_sizes( + fn finalise_sizes( &self, common: &mut CommonGroupState<'data, P>, per_symbol_flags: &AtomicPerSymbolFlags, @@ -3408,12 +3408,12 @@ impl<'data> SyntheticSymbolsLayoutState<'data> { Ok(()) } - fn finalise_layout( + fn finalise_layout( self, memory_offsets: &mut OutputSectionPartMap, resolutions_out: &mut ResolutionWriter

, resources: &FinaliseLayoutResources<'_, 'data, P>, - ) -> Result> { + ) -> Result> { self.internal_symbols .finalise_layout(memory_offsets, resolutions_out, resources)?; @@ -4861,8 +4861,8 @@ impl<'data, P: Platform> DynamicLayoutState<'data, P> { } } -impl<'data> LinkerScriptLayoutState<'data> { - fn finalise_layout( +impl<'data, P: Platform> LinkerScriptLayoutState<'data, P> { + fn finalise_layout( &self, memory_offsets: &mut OutputSectionPartMap, resolutions_out: &mut ResolutionWriter

, @@ -4872,7 +4872,7 @@ impl<'data> LinkerScriptLayoutState<'data> { .finalise_layout(memory_offsets, resolutions_out, resources) } - fn new(input: ResolvedLinkerScript<'data>) -> Self { + fn new(input: resolution::ResolvedLinkerScript<'data, P>) -> Self { Self { file_id: input.file_id, input: input.input, @@ -4884,7 +4884,7 @@ impl<'data> LinkerScriptLayoutState<'data> { } } - fn activate( + fn activate( &self, common: &mut CommonGroupState<'data, P>, resources: &GraphResources<'data, '_, P>, @@ -4892,7 +4892,7 @@ impl<'data> LinkerScriptLayoutState<'data> { self.internal_symbols.activate_symbols(common, resources) } - fn finalise_sizes( + fn finalise_sizes( &self, common: &mut CommonGroupState<'data, P>, per_symbol_flags: &AtomicPerSymbolFlags, diff --git a/libwild/src/layout_rules.rs b/libwild/src/layout_rules.rs index a33150c94..1cdcaf77d 100644 --- a/libwild/src/layout_rules.rs +++ b/libwild/src/layout_rules.rs @@ -131,7 +131,7 @@ impl<'data> LayoutRulesBuilder<'data> { &mut self, input: &InputLinkerScript<'data>, output_sections: &mut OutputSections<'data, P>, - ) -> Result> { + ) -> Result> { let mut symbol_defs = Vec::new(); let mut assertions = Vec::new(); let mut memory_regions = Vec::new(); diff --git a/libwild/src/macho.rs b/libwild/src/macho.rs index 98e6d80b5..ae08d65fd 100644 --- a/libwild/src/macho.rs +++ b/libwild/src/macho.rs @@ -25,6 +25,7 @@ use crate::output_section_id::SectionOutputInfo; use crate::part_id; use crate::platform; use crate::symbol_db::Visibility; +use gimli::LittleEndian; use object::Endian; use object::Endianness; use object::U32; @@ -45,7 +46,7 @@ use object::read::macho::Section; use object::read::macho::Segment; use std::borrow::Cow; -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Copy, Clone, Default)] pub(crate) struct MachO; const LE: Endianness = Endianness::Little; @@ -590,6 +591,15 @@ impl platform::Symbol for SymtabEntry { fn is_gnu_unique(&self) -> bool { false } + + fn with_hidden(mut self, hidden: bool) -> Self { + if hidden { + self.n_type |= N_PEXT; + } else { + self.n_type &= !N_PEXT; + } + self + } } #[derive(Debug, Copy, Clone, Default)] @@ -1007,7 +1017,7 @@ impl platform::Platform for MachO { } fn create_linker_defined_symbols( - symbols: &mut crate::parsing::InternalSymbolsBuilder, + symbols: &mut crate::parsing::InternalSymbolsBuilder, output_kind: crate::output_kind::OutputKind, args: &Self::Args, ) { @@ -1216,7 +1226,7 @@ impl platform::Platform for MachO { fn allocate_internal_symbol( symbol_id: crate::symbol_db::SymbolId, - def_info: &crate::parsing::InternalSymDefInfo, + def_info: &crate::parsing::InternalSymDefInfo, sizes: &mut crate::output_section_part_map::OutputSectionPartMap, symbol_db: &crate::symbol_db::SymbolDb, ) -> crate::error::Result { @@ -1326,6 +1336,16 @@ impl platform::Platform for MachO { _ => {} } } + + fn default_symtab_entry() -> Self::SymtabEntry { + Self::SymtabEntry { + n_strx: Default::default(), + n_type: Default::default(), + n_sect: Default::default(), + n_desc: Default::default(), + n_value: Default::default(), + } + } } const SECTION_DEFINITIONS: [BuiltInSectionDetails; NUM_BUILT_IN_SECTIONS] = { diff --git a/libwild/src/parsing.rs b/libwild/src/parsing.rs index eff99a8ec..efa222ce6 100644 --- a/libwild/src/parsing.rs +++ b/libwild/src/parsing.rs @@ -13,30 +13,29 @@ use crate::output_section_id::OutputSectionId; use crate::platform::Args; use crate::platform::ObjectFile; use crate::platform::Platform; +use crate::platform::Symbol; use crate::symbol::UnversionedSymbolName; use crate::symbol_db::SymbolId; use crate::symbol_db::SymbolIdRange; use crate::timing_phase; use crate::verbose_timing_phase; -use linker_utils::elf::SymbolType; -use linker_utils::elf::stt; pub(crate) fn process_linker_scripts<'data, P: Platform>( linker_scripts_in: &[InputLinkerScript<'data>], output_sections: &mut OutputSections<'data, P>, layout_rules_builder: &mut LayoutRulesBuilder<'data>, -) -> Result>> { +) -> Result>> { timing_phase!("Process linker scripts"); linker_scripts_in .iter() .map(|script| layout_rules_builder.process_linker_script(script, output_sections)) - .collect::>>() + .collect::>>>() } #[derive(Debug)] -pub(crate) struct Prelude<'data> { - pub(crate) symbol_definitions: Vec>, +pub(crate) struct Prelude<'data, P: Platform> { + pub(crate) symbol_definitions: Vec>, } #[derive(Debug)] @@ -47,9 +46,9 @@ pub(crate) struct ParsedInputObject<'data, P: Platform> { } #[derive(Debug)] -pub(crate) struct ProcessedLinkerScript<'data> { +pub(crate) struct ProcessedLinkerScript<'data, P: Platform> { pub(crate) input: InputRef<'data>, - pub(crate) symbol_defs: Vec>, + pub(crate) symbol_defs: Vec>, pub(crate) assertions: Vec>, /// Raw bytes of the linker script file. Used to compute line numbers from /// `AssertCommand::remainder` when reporting errors. @@ -64,13 +63,11 @@ pub(crate) struct SyntheticSymbols { } #[derive(Clone, Copy, derive_more::Debug)] -pub(crate) struct InternalSymDefInfo<'data> { +pub(crate) struct InternalSymDefInfo<'data, P: Platform> { + pub(crate) symbol: P::SymtabEntry, pub(crate) placement: SymbolPlacement<'data>, #[debug("{:?}", String::from_utf8_lossy(name))] pub(crate) name: &'data [u8], - pub(crate) elf_symbol_type: SymbolType, - /// If true, this symbol should have hidden visibility (from PROVIDE_HIDDEN). - pub(crate) is_hidden: bool, } #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -176,30 +173,29 @@ pub(crate) fn parse_number(s: &str) -> Result { } } -impl<'data> InternalSymDefInfo<'data> { +impl<'data, P: Platform> InternalSymDefInfo<'data, P> { pub(crate) fn new(placement: SymbolPlacement<'data>, name: &'data [u8]) -> Self { Self { placement, name, - elf_symbol_type: stt::NOTYPE, - is_hidden: false, + symbol: P::default_symtab_entry(), } } pub(crate) fn with_hidden(self, hidden: bool) -> Self { Self { - is_hidden: hidden, + symbol: self.symbol.with_hidden(hidden), ..self } } pub(crate) fn hide(&mut self) -> &mut Self { - self.is_hidden = true; + self.symbol = self.symbol.with_hidden(true); self } pub(crate) fn set_hidden(&mut self, hidden: bool) -> &mut Self { - self.is_hidden = hidden; + self.symbol = self.symbol.with_hidden(hidden); self } } @@ -227,8 +223,8 @@ impl<'data, P: Platform> ParsedInputObject<'data, P> { } } -impl<'data> Prelude<'data> { - pub(crate) fn new(args: &'data P::Args, output_kind: OutputKind) -> Self { +impl<'data, P: Platform> Prelude<'data, P> { + pub(crate) fn new(args: &'data P::Args, output_kind: OutputKind) -> Self { verbose_timing_phase!("Construct prelude"); let mut symbols = InternalSymbolsBuilder::default(); @@ -265,15 +261,15 @@ impl<'data> Prelude<'data> { } #[derive(Default)] -pub(crate) struct InternalSymbolsBuilder<'data> { - symbol_definitions: Vec>, +pub(crate) struct InternalSymbolsBuilder<'data, P: Platform> { + symbol_definitions: Vec>, } -impl<'data> InternalSymbolsBuilder<'data> { +impl<'data, P: Platform> InternalSymbolsBuilder<'data, P> { pub(crate) fn add_symbol( &mut self, - def: InternalSymDefInfo<'data>, - ) -> &mut InternalSymDefInfo<'data> { + def: InternalSymDefInfo<'data, P>, + ) -> &mut InternalSymDefInfo<'data, P> { let index = self.symbol_definitions.len(); self.symbol_definitions.push(def); &mut self.symbol_definitions[index] @@ -283,7 +279,7 @@ impl<'data> InternalSymbolsBuilder<'data> { &mut self, section_id: OutputSectionId, name: &'static str, - ) -> &mut InternalSymDefInfo<'data> { + ) -> &mut InternalSymDefInfo<'data, P> { self.add_symbol(InternalSymDefInfo::new( SymbolPlacement::SectionStart(section_id), name.as_bytes(), @@ -294,7 +290,7 @@ impl<'data> InternalSymbolsBuilder<'data> { &mut self, section_id: OutputSectionId, name: &'static str, - ) -> &mut InternalSymDefInfo<'data> { + ) -> &mut InternalSymDefInfo<'data, P> { self.add_symbol(InternalSymDefInfo::new( SymbolPlacement::SectionEnd(section_id), name.as_bytes(), @@ -305,7 +301,7 @@ impl<'data> InternalSymbolsBuilder<'data> { &mut self, section_id: OutputSectionId, name: &'static str, - ) -> &mut InternalSymDefInfo<'data> { + ) -> &mut InternalSymDefInfo<'data, P> { self.add_symbol(InternalSymDefInfo::new( SymbolPlacement::SectionGroupEnd(section_id), name.as_bytes(), @@ -313,7 +309,7 @@ impl<'data> InternalSymbolsBuilder<'data> { } } -impl<'data> ProcessedLinkerScript<'data> { +impl<'data, P: Platform> ProcessedLinkerScript<'data, P> { pub(crate) fn num_symbols(&self) -> usize { self.symbol_defs.len() } @@ -325,7 +321,7 @@ impl<'data, P: Platform> std::fmt::Display for ParsedInputObject<'data, P> { } } -impl std::fmt::Display for ProcessedLinkerScript<'_> { +impl<'data, P: Platform> std::fmt::Display for ProcessedLinkerScript<'data, P> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.input, f) } diff --git a/libwild/src/platform.rs b/libwild/src/platform.rs index 5646b9e2e..7e3efe1f1 100644 --- a/libwild/src/platform.rs +++ b/libwild/src/platform.rs @@ -171,7 +171,9 @@ pub(crate) struct RelaxSymbolInfo { } /// A platform for which we support writing producing linked outputs. -pub(crate) trait Platform: Copy + Send + Sync + Sized + std::fmt::Debug + 'static { +pub(crate) trait Platform: + Copy + Send + Sync + Sized + Default + std::fmt::Debug + 'static +{ type File<'data>: ObjectFile<'data, Platform = Self>; type SymtabEntry: Symbol; type SectionHeader: SectionHeader; @@ -405,7 +407,7 @@ pub(crate) trait Platform: Copy + Send + Sync + Sized + std::fmt::Debug + 'stati fn unconditional_segment_defs() -> &'static [Self::ProgramSegmentDef]; fn create_linker_defined_symbols( - symbols: &mut crate::parsing::InternalSymbolsBuilder, + symbols: &mut crate::parsing::InternalSymbolsBuilder, output_kind: OutputKind, args: &Self::Args, ); @@ -552,7 +554,7 @@ pub(crate) trait Platform: Copy + Send + Sync + Sized + std::fmt::Debug + 'stati fn allocate_internal_symbol( symbol_id: SymbolId, - def_info: &InternalSymDefInfo, + def_info: &InternalSymDefInfo, sizes: &mut OutputSectionPartMap, symbol_db: &SymbolDb, ) -> Result; @@ -628,6 +630,10 @@ pub(crate) trait Platform: Copy + Send + Sync + Sized + std::fmt::Debug + 'stati false } + /// Used when the linker needs to create a symtab entry from scratch rather than copying one + /// from an input file. + fn default_symtab_entry() -> Self::SymtabEntry; + fn lookup_for_partial_link( _section_name: &[u8], _section: &Self::SectionHeader, @@ -873,7 +879,7 @@ pub(crate) trait SectionFlags: fn is_alloc(self) -> bool; } -pub(crate) trait Symbol: std::fmt::Debug + Send + Sync + 'static { +pub(crate) trait Symbol: std::fmt::Debug + Copy + Send + Sync + 'static { /// Returns information about the symbol if it's a common symbol. Platforms that don't have /// common symbols can just return None. fn as_common(&self) -> Option; @@ -916,6 +922,8 @@ pub(crate) trait Symbol: std::fmt::Debug + Send + Sync + 'static { fn is_hidden(&self) -> bool; fn is_gnu_unique(&self) -> bool; + + fn with_hidden(self, hidden: bool) -> Self; } #[derive(Clone, Copy)] diff --git a/libwild/src/resolution.rs b/libwild/src/resolution.rs index 8df98866f..9ad589db7 100644 --- a/libwild/src/resolution.rs +++ b/libwild/src/resolution.rs @@ -560,11 +560,11 @@ pub(crate) struct ResolvedGroup<'data, P: Platform> { #[derive(Debug)] pub(crate) enum ResolvedFile<'data, P: Platform> { NotLoaded(NotLoaded), - Prelude(ResolvedPrelude<'data>), + Prelude(ResolvedPrelude<'data, P>), Object(ResolvedObject<'data, P>), Dynamic(ResolvedDynamic<'data, P>), - LinkerScript(ResolvedLinkerScript<'data>), - SyntheticSymbols(ResolvedSyntheticSymbols<'data>), + LinkerScript(ResolvedLinkerScript<'data, P>), + SyntheticSymbols(ResolvedSyntheticSymbols<'data, P>), #[cfg(feature = "plugins")] LtoInput(ResolvedLtoInput), } @@ -631,8 +631,8 @@ impl UnloadedSection { } #[derive(Debug, Clone)] -pub(crate) struct ResolvedPrelude<'data> { - pub(crate) symbol_definitions: Vec>, +pub(crate) struct ResolvedPrelude<'data, P: Platform> { + pub(crate) symbol_definitions: Vec>, } /// Resolved state common to dynamic and regular objects. @@ -666,18 +666,18 @@ pub(crate) struct ResolvedDynamic<'data, P: Platform> { } #[derive(Debug)] -pub(crate) struct ResolvedLinkerScript<'data> { +pub(crate) struct ResolvedLinkerScript<'data, P: Platform> { pub(crate) input: InputRef<'data>, pub(crate) file_id: FileId, pub(crate) symbol_id_range: SymbolIdRange, - pub(crate) symbol_definitions: Vec>, + pub(crate) symbol_definitions: Vec>, } #[derive(Debug, Clone)] -pub(crate) struct ResolvedSyntheticSymbols<'data> { +pub(crate) struct ResolvedSyntheticSymbols<'data, P: Platform> { pub(crate) file_id: FileId, pub(crate) start_symbol_id: SymbolId, - pub(crate) symbol_definitions: Vec>, + pub(crate) symbol_definitions: Vec>, } #[cfg(feature = "plugins")] @@ -786,7 +786,7 @@ struct UndefinedSymbol<'data> { } fn load_prelude<'scope, 'data, P: Platform>( - prelude: &crate::parsing::Prelude, + prelude: &crate::parsing::Prelude

, definitions_out: &mut [SymbolId], resources: &'scope ResolutionResources<'data, 'scope, P>, scope: &Scope<'scope>, @@ -841,7 +841,7 @@ fn canonicalise_undefined_symbols<'data, P: Platform>( groups: &[ResolvedGroup<'data, P>], symbol_db: &mut SymbolDb<'data, P>, per_symbol_flags: &mut PerSymbolFlags, - custom_start_stop_defs: &mut ResolvedSyntheticSymbols<'data>, + custom_start_stop_defs: &mut ResolvedSyntheticSymbols<'data, P>, ) { timing_phase!("Canonicalise undefined symbols"); @@ -965,7 +965,7 @@ fn allocate_start_stop_symbol_id<'data, P: Platform>( name: PreHashed>, symbol_db: &mut SymbolDb<'data, P>, per_symbol_flags: &mut PerSymbolFlags, - custom_start_stop_defs: &mut ResolvedSyntheticSymbols<'data>, + custom_start_stop_defs: &mut ResolvedSyntheticSymbols<'data, P>, output_sections: &OutputSections

, ) -> Option { let symbol_name_bytes = name.bytes(); @@ -1396,7 +1396,7 @@ impl<'data, P: Platform> std::fmt::Display for ResolvedDynamic<'data, P> { } } -impl<'data> std::fmt::Display for ResolvedLinkerScript<'data> { +impl<'data, P: Platform> std::fmt::Display for ResolvedLinkerScript<'data, P> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { std::fmt::Display::fmt(&self.input, f) } @@ -1460,13 +1460,13 @@ impl<'data, P: Platform> ResolvedFile<'data, P> { } } -impl ResolvedPrelude<'_> { +impl<'data, P: Platform> ResolvedPrelude<'data, P> { fn symbol_id_range(&self) -> SymbolIdRange { SymbolIdRange::input(SymbolId::undefined(), self.symbol_definitions.len()) } } -impl ResolvedSyntheticSymbols<'_> { +impl<'data, P: Platform> ResolvedSyntheticSymbols<'data, P> { fn symbol_id_range(&self) -> SymbolIdRange { SymbolIdRange::input(self.start_symbol_id, self.symbol_definitions.len()) } diff --git a/libwild/src/symbol_db.rs b/libwild/src/symbol_db.rs index 8d0e9223e..a4a2134fb 100644 --- a/libwild/src/symbol_db.rs +++ b/libwild/src/symbol_db.rs @@ -391,7 +391,7 @@ impl<'data, P: Platform> SymbolDb<'data, P> { if self.groups.is_empty() { self.groups - .push(Group::Prelude(crate::parsing::Prelude::new::

( + .push(Group::Prelude(crate::parsing::Prelude::new( self.args, self.output_kind, ))); @@ -518,7 +518,7 @@ impl<'data, P: Platform> SymbolDb<'data, P> { &mut self, per_symbol_flags: &mut PerSymbolFlags, symbol_name: PreHashed>, - syn: &ResolvedSyntheticSymbols<'data>, + syn: &ResolvedSyntheticSymbols<'data, P>, ) -> SymbolId { debug_assert_eq!(syn.file_id.group() + 1, self.groups.len()); @@ -939,7 +939,7 @@ impl<'data, P: Platform> SymbolDb<'data, P> { }) } - pub(crate) fn new_synthetic_symbols_group(&mut self) -> ResolvedSyntheticSymbols<'data> { + pub(crate) fn new_synthetic_symbols_group(&mut self) -> ResolvedSyntheticSymbols<'data, P> { let file_id = FileId::new(self.groups.len() as u32, 0); let start_symbol_id = self.next_symbol_id(); @@ -1562,7 +1562,7 @@ fn populate_symbol_db<'data>( } fn load_linker_script_symbols<'data, P: Platform>( - script: &SequencedLinkerScript<'data>, + script: &SequencedLinkerScript<'data, P>, symbols_out: &mut SymbolWriterShard<'_, '_, 'data, P>, outputs: &mut SymbolLoadOutputs<'data>, ) { @@ -1580,7 +1580,7 @@ fn load_linker_script_symbols<'data, P: Platform>( let mut flags = ValueFlags::NON_INTERPOSABLE; // PROVIDE_HIDDEN symbols have hidden visibility, which means they should be // non-interposable (already set) and not exported to dynamic symbol table. - if definition.is_hidden { + if definition.symbol.is_hidden() { flags |= ValueFlags::DOWNGRADE_TO_LOCAL; } symbols_out.set_next(flags, symbol_id, script.file_id); @@ -1989,8 +1989,8 @@ impl TryFrom for SymbolId { } } -impl<'data> Prelude<'data> { - fn load_symbols( +impl<'data, P: Platform> Prelude<'data, P> { + fn load_symbols( &self, symbols_out: &mut SymbolWriterShard<'_, '_, 'data, P>, outputs: &mut SymbolLoadOutputs<'data>, @@ -2014,7 +2014,7 @@ impl<'data> Prelude<'data> { ValueFlags::NON_INTERPOSABLE } }; - if definition.is_hidden { + if definition.symbol.is_hidden() { flags |= ValueFlags::DOWNGRADE_TO_LOCAL; } symbols_out.set_next(flags, symbol_id, PRELUDE_FILE_ID); @@ -2028,7 +2028,7 @@ impl std::fmt::Display for SymbolId { } } -impl InternalSymDefInfo<'_> { +impl InternalSymDefInfo<'_, P> { pub(crate) fn section_id(self) -> Option { match self.placement { SymbolPlacement::Undefined diff --git a/libwild/src/tidy_tests.rs b/libwild/src/tidy_tests.rs index 8c3128983..5c3fef10c 100644 --- a/libwild/src/tidy_tests.rs +++ b/libwild/src/tidy_tests.rs @@ -173,10 +173,11 @@ fn check_elf_specific_code() -> Result { // Files where we don't allow ELF-specific code. const DISALLOWED: &[&str] = &[ + "input_data.rs", "layout.rs", - "symbol_db.rs", + "parsing.rs", "resolution.rs", - "input_data.rs", + "symbol_db.rs", ]; // Patterns that we still allow. These should probably be dealt with, either by renaming these