diff --git a/libwild/src/elf.rs b/libwild/src/elf.rs index 7faead799..a15b246e0 100644 --- a/libwild/src/elf.rs +++ b/libwild/src/elf.rs @@ -1830,7 +1830,7 @@ impl platform::Platform for Elf { output_kind: OutputKind, output_sections: &OutputSections<'data, Self>, secondary: &OutputSectionMap>, - ) -> (OutputOrder, ProgramSegments) { + ) -> (OutputOrder<'data>, ProgramSegments) { let mut builder = OutputOrderBuilder::::new(output_kind, output_sections, secondary); builder.add_section(output_section_id::FILE_HEADER); diff --git a/libwild/src/elf_writer.rs b/libwild/src/elf_writer.rs index 4535734ce..ab42efbe7 100644 --- a/libwild/src/elf_writer.rs +++ b/libwild/src/elf_writer.rs @@ -4447,6 +4447,17 @@ fn get_defsym_attributes( } SymbolLoc::FirstSection => 1, SymbolLoc::None => return Ok((object::elf::SHN_ABS.into(), object::elf::STT_NOTYPE)), + SymbolLoc::Expression(_, os) => { + if let Some(os) = os { + let os = layout.output_sections.primary_output_section(os); + layout + .output_sections + .output_index_of_section(os) + .unwrap_or(0) + } else { + 1 + } + } }; Ok((SymbolSection::Index(shndx), object::elf::STT_NOTYPE)) } diff --git a/libwild/src/expression_eval.rs b/libwild/src/expression_eval.rs index 71f7482e5..1cb919ac7 100644 --- a/libwild/src/expression_eval.rs +++ b/libwild/src/expression_eval.rs @@ -45,7 +45,7 @@ pub(crate) fn evaluate_assertions<'data, P: Platform>( let line = line_number(parsed.file_bytes, assertion.remainder); let result = evaluate_expression( &assertion.expression, - SymbolLoc::None, + &SymbolLoc::None, section_layouts, output_sections, &parsed.memory_regions, @@ -80,7 +80,7 @@ pub(crate) fn evaluate_assertions<'data, P: Platform>( pub(crate) fn evaluate_expression<'data, P: Platform>( expr: &Expression<'data>, - expr_loc: SymbolLoc, + expr_loc: &SymbolLoc<'data>, section_layouts: &OutputSectionMap, output_sections: &OutputSections<'data, P>, memory_regions: &[MemoryRegion<'data>], @@ -105,12 +105,13 @@ pub(crate) fn evaluate_expression<'data, P: Platform>( Expression::Number(n) => Ok(*n), Expression::LocationCounter => match expr_loc { - SymbolLoc::SectionStart(id) => Ok(section_layouts.get(id).mem_offset), + SymbolLoc::SectionStart(id) => Ok(section_layouts.get(*id).mem_offset), SymbolLoc::SectionEnd(id) => { - let layout = section_layouts.get(id); + let layout = section_layouts.get(*id); Ok(layout.mem_offset + layout.mem_size) } SymbolLoc::FirstSection | SymbolLoc::None => Ok(0), + SymbolLoc::Expression(expr, _) => eval!(expr), }, Expression::Symbol(name) => symbol_resolution_callback(name), @@ -280,7 +281,7 @@ mod tests { with_dummy_context(|layouts, sections, symbol_db| { evaluate_expression::( expr, - SymbolLoc::None, + &SymbolLoc::None, layouts, sections, &[], @@ -656,7 +657,7 @@ mod tests { let eval = |expr: &Expression<'static>| { evaluate_expression::( expr, - SymbolLoc::None, + &SymbolLoc::None, layouts, sections, ®ions, diff --git a/libwild/src/layout.rs b/libwild/src/layout.rs index 2089e1223..31d43397a 100644 --- a/libwild/src/layout.rs +++ b/libwild/src/layout.rs @@ -21,6 +21,7 @@ use crate::input_data::InputRef; use crate::input_data::PRELUDE_FILE_ID; use crate::input_section_id::SectionIdRange; use crate::layout_rules::SectionKind; +use crate::linker_script::Expression; use crate::output_section_id; use crate::output_section_id::OrderEvent; use crate::output_section_id::OutputOrder; @@ -232,13 +233,28 @@ pub fn compute<'data, P: Platform, A: Arch>( &symbol_db, ); + let memory_regions: Vec> = symbol_db + .groups + .iter() + .filter_map(|g| { + if let crate::grouping::Group::LinkerScripts(scripts) = g { + Some(scripts) + } else { + None + } + }) + .flatten() + .flat_map(|s| s.parsed.memory_regions.iter().cloned()) + .collect(); + let mut section_part_layouts = layout_section_parts::( §ion_part_sizes, &output_sections, &program_segments, &output_order, - symbol_db.args, - ); + &symbol_db, + &memory_regions, + )?; if symbol_db.args.should_relax() && A::supports_size_reduction_relaxations() { perform_iterative_relaxation::( @@ -250,7 +266,8 @@ pub fn compute<'data, P: Platform, A: Arch>( &output_order, &symbol_db, &per_symbol_flags, - ); + &memory_regions, + )?; } if let Some((record, last_part_id)) = section_part_layouts @@ -474,7 +491,7 @@ fn update_defsym_symbol_resolution<'data, P: Platform>( if let SymbolPlacement::Redirect(redirect) = &def_info.placement { let value = crate::expression_eval::evaluate_expression( &redirect.expression, - redirect.loc, + &redirect.loc, section_layouts, output_sections, memory_regions, @@ -633,7 +650,7 @@ pub struct Layout<'data, P: Platform> { pub(crate) segment_layouts: SegmentLayouts, pub(crate) output_sections: OutputSections<'data, P>, pub(crate) program_segments: ProgramSegments, - pub(crate) output_order: OutputOrder, + pub(crate) output_order: OutputOrder<'data>, pub(crate) non_addressable_counts: P::NonAddressableCounts, pub(crate) merged_strings: OutputSectionMap>, pub(crate) merged_string_start_addresses: MergedStringStartAddresses, @@ -1317,7 +1334,7 @@ pub(crate) struct FinaliseLayoutResources<'scope, 'data, P: Platform> { pub(crate) symbol_db: &'scope SymbolDb<'data, P>, pub(crate) per_symbol_flags: &'scope PerSymbolFlags, output_sections: &'scope OutputSections<'data, P>, - output_order: &'scope OutputOrder, + output_order: &'scope OutputOrder<'data>, pub(crate) section_layouts: &'scope OutputSectionMap, merged_string_start_addresses: &'scope MergedStringStartAddresses, merged_strings: &'scope OutputSectionMap>, @@ -1675,10 +1692,10 @@ fn compute_symbols_and_layouts<'data, P: Platform>( .collect() } -fn compute_segment_layout( +fn compute_segment_layout<'data, P: Platform>( section_layouts: &OutputSectionMap, output_sections: &OutputSections

, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, program_segments: &ProgramSegments, header_info: &HeaderInfo, args: &P::Args, @@ -1827,7 +1844,7 @@ fn compute_segment_layout( fn compute_total_section_part_sizes<'data, P: Platform>( group_states: &mut [GroupState<'data, P>], output_sections: &mut OutputSections

, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, program_segments: &ProgramSegments, per_symbol_flags: &mut PerSymbolFlags, must_keep_sections: OutputSectionMap, @@ -2941,7 +2958,7 @@ impl<'data, P: Platform> PreludeLayoutState<'data, P> { total_sizes: &mut OutputSectionPartMap, must_keep_sections: OutputSectionMap, output_sections: &mut OutputSections

, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, program_segments: &ProgramSegments, per_symbol_flags: &mut PerSymbolFlags, resources: &FinaliseSizesResources<'data, '_, P>, @@ -3053,7 +3070,7 @@ impl<'data, P: Platform> PreludeLayoutState<'data, P> { must_keep_sections: OutputSectionMap, output_sections: &mut OutputSections

, program_segments: &ProgramSegments, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, resources: &FinaliseSizesResources<'data, '_, P>, symbol_flags: &PerSymbolFlags, ) { @@ -4730,12 +4747,13 @@ fn perform_iterative_relaxation<'data, A: Arch>( group_states: &mut [GroupState<'data, A::Platform>], section_part_sizes: &mut OutputSectionPartMap, section_part_layouts: &mut OutputSectionPartMap, - output_sections: &OutputSections, + output_sections: &OutputSections<'data, A::Platform>, program_segments: &ProgramSegments<::ProgramSegmentDef>, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, symbol_db: &SymbolDb<'data, A::Platform>, per_symbol_flags: &PerSymbolFlags, -) { + memory_regions: &[crate::linker_script::MemoryRegion<'data>], +) -> Result { timing_phase!("Iterative relaxation"); let mut rescan_sections: Option = None; @@ -4789,18 +4807,22 @@ fn perform_iterative_relaxation<'data, A: Arch>( output_sections, program_segments, output_order, - symbol_db.args, - ); + symbol_db, + memory_regions, + )?; } + Ok(()) } -fn layout_section_parts( +fn layout_section_parts<'data, P: Platform>( sizes: &OutputSectionPartMap, - output_sections: &OutputSections

, + output_sections: &OutputSections<'data, P>, program_segments: &ProgramSegments, - output_order: &OutputOrder, - args: &P::Args, -) -> OutputSectionPartMap { + output_order: &OutputOrder<'data>, + symbol_db: &SymbolDb<'data, P>, + memory_regions: &[crate::linker_script::MemoryRegion<'data>], +) -> Result> { + let args = symbol_db.args; let segment_alignments = compute_segment_alignments::

( sizes, program_segments, @@ -4809,8 +4831,26 @@ fn layout_section_parts( output_sections, ); + // Create an empty section layout for now, until we can support using linker script + // commands. + let empty_section_layouts = OutputSectionMap::with_size(output_sections.num_sections()); + + let expression_eval = |expr: &Expression<'data>| { + crate::expression_eval::evaluate_expression( + expr, + &crate::parsing::SymbolLoc::None, + &empty_section_layouts, + output_sections, + memory_regions, + symbol_db, + &|_| { + bail!("Symbols with the set location operation are not yet supported."); + }, + ) + }; + let mut file_offset = 0; - let mut mem_offset = output_sections.base_address; + let mut mem_offset = expression_eval(&output_sections.base_address)?; let mut nonalloc_mem_offsets: OutputSectionMap = OutputSectionMap::with_size(output_sections.num_sections()); let mut reloc_alloc_mem_offsets: OutputSectionMap = @@ -4822,8 +4862,8 @@ fn layout_section_parts( for event in output_order { match event { - OrderEvent::SetLocation(location) => { - pending_location = Some(location); + OrderEvent::SetLocation(expr) => { + pending_location = Some(expr); } OrderEvent::SegmentStart(segment_id) => { if program_segments.is_load_segment(segment_id) { @@ -4831,9 +4871,9 @@ fn layout_section_parts( .get(&segment_id) .copied() .unwrap_or_else(|| args.loadable_segment_alignment()); - if let Some(location) = pending_location.take() { + if let Some(expr) = pending_location.take() { // The OrderEvent::SetLocation is ELF-specific only. - mem_offset = location.address; + mem_offset = expression_eval(&expr)?; file_offset = segment_alignment.align_modulo(mem_offset, file_offset as u64) as usize; } else { @@ -4856,8 +4896,8 @@ fn layout_section_parts( let section_info = output_sections.output_info(section_id); let part_id_range = section_id.part_id_range(); let max_alignment = sizes.max_alignment(part_id_range.clone(), output_sections); - if let Some(location) = section_info.location { - mem_offset = location.address; + if let Some(ref expr) = section_info.location { + mem_offset = expression_eval(expr)?; } records_out[part_id_range.clone()] @@ -4945,15 +4985,15 @@ fn layout_section_parts( }; } - records_out + Ok(records_out) } /// Computes the maximum alignment for each LOAD segment by examining the alignments of all sections /// that will be placed in that segment. -fn compute_segment_alignments( +fn compute_segment_alignments<'data, P: Platform>( sizes: &OutputSectionPartMap, program_segments: &ProgramSegments, - output_order: &OutputOrder, + output_order: &OutputOrder<'data>, args: &P::Args, output_sections: &OutputSections

, ) -> HashMap { @@ -5241,13 +5281,24 @@ fn test_no_disallowed_overlaps() { } let section_part_sizes = output_sections.new_part_map::().map(|_, _| 7); + let output_kind = crate::output_kind::OutputKind::StaticExecutable( + crate::args::RelocationModel::NonRelocatable, + ); + let arena = colosseum::sync::Arena::new(); + let auxiliary = crate::input_data::AuxiliaryFiles::new(&args, &arena).unwrap(); + let herd = Default::default(); + let symbol_db = + crate::symbol_db::SymbolDb::::new(&args, output_kind, &auxiliary, &herd).unwrap(); + let section_part_layouts = layout_section_parts::( §ion_part_sizes, &output_sections, &program_segments, &output_order, - &args, - ); + &symbol_db, + &[], + ) + .unwrap(); let section_layouts = layout_sections(&output_sections, §ion_part_layouts); diff --git a/libwild/src/layout_rules.rs b/libwild/src/layout_rules.rs index f8847325f..d9ff3ba70 100644 --- a/libwild/src/layout_rules.rs +++ b/libwild/src/layout_rules.rs @@ -12,8 +12,6 @@ use crate::input_data::InputLinkerScript; use crate::input_data::InputRef; use crate::linker_script; use crate::linker_script::ContentsCommand; -use crate::linker_script::Expression; -use crate::linker_script::Location; use crate::linker_script::SectionCommand; use crate::output_section_id; use crate::output_section_id::OutputSectionId; @@ -130,10 +128,10 @@ impl SectionOutputInfo { } } -fn loc_for_global_expr( - expr: &crate::linker_script::Expression<'_>, +fn loc_for_global_expr<'data>( + expr: &crate::linker_script::Expression<'data>, section_id: Option, -) -> SymbolLoc { +) -> SymbolLoc<'data> { let mut loc = SymbolLoc::None; expr.visit_expressions(&mut |e| match e { crate::linker_script::Expression::SegmentStart(..) => { @@ -161,6 +159,7 @@ impl<'data> LayoutRulesBuilder<'data> { let mut memory_regions = Vec::new(); let mut current_section_id = None; + let mut loc = SymbolLoc::FirstSection; for cmd in &input.script.commands { if let linker_script::Command::Provide(provide) = cmd { @@ -217,14 +216,9 @@ impl<'data> LayoutRulesBuilder<'data> { .max(replace(&mut extra_min_alignment, alignment::MIN)); let section_location = match &sec.start_address_expression { - Some(Expression::Number(address)) => { + Some(address) => { location.take(); - Some(Location { address: *address }) - } - Some(_) => { - return Err(crate::error!( - "Only numeric output section start expressions are currently supported" - )); + Some(address.clone()) } None => location.take(), }; @@ -235,8 +229,10 @@ impl<'data> LayoutRulesBuilder<'data> { section_location, ); current_section_id = Some(primary_section_id); + loc = SymbolLoc::SectionEnd(primary_section_id); let mut last_section_id = None; + let mut last_loc = SymbolLoc::SectionStart(primary_section_id); for contents_cmd in &sec.commands { match contents_cmd { @@ -265,17 +261,13 @@ impl<'data> LayoutRulesBuilder<'data> { } last_section_id = Some(section_id); + last_loc = SymbolLoc::SectionEnd(section_id); } ContentsCommand::SymbolAssignment(assignment) => { - let loc = if let Some(id) = last_section_id { - SymbolLoc::SectionEnd(id) - } else { - SymbolLoc::SectionStart(primary_section_id) - }; let placement = SymbolPlacement::Redirect(Redirect { kind: RedirectKind::Script, expression: assignment.expr.clone(), - loc, + loc: last_loc.clone(), }); symbol_defs.push(InternalSymDefInfo::new( placement, @@ -284,15 +276,10 @@ impl<'data> LayoutRulesBuilder<'data> { } ContentsCommand::Align(a) => extra_min_alignment = *a, ContentsCommand::Provide(provide) => { - let loc = if let Some(id) = last_section_id { - SymbolLoc::SectionEnd(id) - } else { - SymbolLoc::SectionStart(primary_section_id) - }; let placement = SymbolPlacement::Redirect(Redirect { kind: RedirectKind::Script, expression: provide.value.clone(), - loc, + loc: last_loc.clone(), }); symbol_defs.push( InternalSymDefInfo::new(placement, provide.name) @@ -302,21 +289,29 @@ impl<'data> LayoutRulesBuilder<'data> { } } } - SectionCommand::SetLocation(new_location) => location = Some(*new_location), + SectionCommand::SetLocation(new_location) => { + let section_id = match loc { + SymbolLoc::Expression(_, section_id) => section_id, + SymbolLoc::SectionStart(section_id) + | SymbolLoc::SectionEnd(section_id) => Some(section_id), + _ => None, + }; + loc = SymbolLoc::Expression(new_location.address.clone(), section_id); + if current_section_id.is_none() { + output_sections.set_base_address(new_location.address.clone()); + continue; + } + location = Some(new_location.address.clone()); + } SectionCommand::Align(a) => extra_min_alignment = *a, SectionCommand::Assert(assert_cmd) => { assertions.push(assert_cmd.clone()); } SectionCommand::Provide(provide) => { - let placement = if let Some(id) = current_section_id { - SymbolLoc::SectionEnd(id) - } else { - SymbolLoc::FirstSection - }; let placement = SymbolPlacement::Redirect(Redirect { kind: RedirectKind::Script, expression: provide.value.clone(), - loc: placement, + loc: loc.clone(), }); symbol_defs.push( InternalSymDefInfo::new(placement, provide.name) @@ -324,15 +319,10 @@ impl<'data> LayoutRulesBuilder<'data> { ); } SectionCommand::SymbolAssignment(assignment) => { - let loc = if let Some(id) = current_section_id { - SymbolLoc::SectionEnd(id) - } else { - SymbolLoc::FirstSection - }; let placement = SymbolPlacement::Redirect(Redirect { kind: RedirectKind::Script, expression: assignment.expr.clone(), - loc, + loc: loc.clone(), }); symbol_defs.push(InternalSymDefInfo::new(placement, assignment.name)); } diff --git a/libwild/src/linker_script.rs b/libwild/src/linker_script.rs index 77461bc58..12d68d48e 100644 --- a/libwild/src/linker_script.rs +++ b/libwild/src/linker_script.rs @@ -11,7 +11,6 @@ use std::path::Path; use winnow::BStr; use winnow::Parser as _; use winnow::ascii::dec_uint; -use winnow::ascii::hex_digit1; use winnow::ascii::hex_uint; use winnow::ascii::multispace0; use winnow::combinator::alt; @@ -85,16 +84,16 @@ pub(crate) struct Sections<'a> { #[derive(Debug, PartialEq, Eq)] pub(crate) enum SectionCommand<'a> { Section(Section<'a>), - SetLocation(Location), + SetLocation(Location<'a>), Align(Alignment), Assert(AssertCommand<'a>), Provide(ProvideSymbolDefinition<'a>), SymbolAssignment(SymbolAssignment<'a>), } -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub(crate) struct Location { - pub(crate) address: u64, +#[derive(Debug, PartialEq, Eq, Clone)] +pub(crate) struct Location<'a> { + pub(crate) address: Expression<'a>, } #[derive(Debug, PartialEq, Eq)] @@ -874,11 +873,8 @@ enum MulOp { Divide, } -fn parse_location(input: &mut &BStr) -> winnow::Result { - "0x".parse_next(input)?; - let hex_str = - std::str::from_utf8(hex_digit1.parse_next(input)?).map_err(|_| ContextError::new())?; - let address = u64::from_str_radix(hex_str, 16).map_err(|_| ContextError::new())?; +fn parse_location<'input>(input: &mut &'input BStr) -> winnow::Result> { + let address = parse_expression.parse_next(input)?; Ok(Location { address }) } @@ -1387,7 +1383,9 @@ mod tests { Command::Entry(b"_start"), Command::Sections(Sections { commands: vec![ - SectionCommand::SetLocation(Location { address: 0x1000000 }), + SectionCommand::SetLocation(Location { + address: Expression::Number(0x1000000), + }), SectionCommand::Align(Alignment::new(16).unwrap()), SectionCommand::Section(Section { output_section_name: b".foo", diff --git a/libwild/src/macho.rs b/libwild/src/macho.rs index 3b82e5fbb..ead03f924 100644 --- a/libwild/src/macho.rs +++ b/libwild/src/macho.rs @@ -1462,7 +1462,7 @@ impl platform::Platform for MachO { Vec, >, ) -> ( - crate::output_section_id::OutputOrder, + crate::output_section_id::OutputOrder<'data>, crate::program_segments::ProgramSegments, ) { let mut builder = OutputOrderBuilder::::new(output_kind, output_sections, secondary); diff --git a/libwild/src/output_section_id.rs b/libwild/src/output_section_id.rs index fe19fcded..fc63f35b6 100644 --- a/libwild/src/output_section_id.rs +++ b/libwild/src/output_section_id.rs @@ -17,6 +17,7 @@ use crate::alignment::Alignment; use crate::alignment::NUM_ALIGNMENTS; use crate::layout_rules::SectionKind; use crate::linker_script; +use crate::linker_script::Expression; use crate::output_kind::OutputKind; use crate::output_section_map::OutputSectionMap; use crate::output_section_part_map::OutputSectionPartMap; @@ -34,7 +35,6 @@ use core::slice; use hashbrown::HashMap; use std::fmt::Debug; use std::fmt::Display; -use std::iter::Copied; use std::ops::Range; /// Number of sections that we have built-in IDs for. @@ -154,7 +154,7 @@ pub(crate) const NUM_BUILT_IN_REGULAR_SECTIONS: usize = 16; #[derive(Debug)] pub(crate) struct OutputSections<'data, P: Platform> { /// The base address for our output binary. - pub(crate) base_address: u64, + pub(crate) base_address: Expression<'data>, pub(crate) section_infos: OutputSectionMap>, // TODO: Consider moving this to Layout. We can't populate this until we know which output @@ -171,18 +171,18 @@ pub(crate) struct OutputSections<'data, P: Platform> { /// Encodes the order of output sections and the start and end of each program segment. This struct /// is intended to be used by iterating over it. #[derive(Debug)] -pub(crate) struct OutputOrder { - events: Vec, +pub(crate) struct OutputOrder<'data> { + events: Vec>, } pub(crate) struct OutputOrderDisplay<'a, 'data, P: Platform> { - order: &'a OutputOrder, + order: &'a OutputOrder<'data>, sections: &'a OutputSections<'data, P>, program_segments: &'a ProgramSegments, } pub(crate) struct OutputOrderBuilder<'scope, 'data, P: Platform> { - events: Vec, + events: Vec>, program_segments: ProgramSegments, @@ -233,10 +233,10 @@ impl<'scope, 'data, P: Platform> OutputOrderBuilder<'scope, 'data, P> { // in a segment. Sections without ALLOC (like custom sections before their flags // are propagated) will have their location handled directly in layout_section_parts // via section_info.location. - if let Some(location) = section_info.location + if let Some(location) = §ion_info.location && section_info.section_attributes.is_alloc() { - self.events.push(OrderEvent::SetLocation(location)); + self.events.push(OrderEvent::SetLocation(location.clone())); } for segment_id in start { @@ -366,7 +366,7 @@ impl<'scope, 'data, P: Platform> OutputOrderBuilder<'scope, 'data, P> { } } - pub(crate) fn build(mut self) -> (OutputOrder, ProgramSegments) { + pub(crate) fn build(mut self) -> (OutputOrder<'data>, ProgramSegments) { for segment_id in self.active_segment_kinds.into_iter().flatten() { self.events.push(OrderEvent::SegmentEnd(segment_id)); } @@ -462,7 +462,7 @@ pub(crate) struct SectionOutputInfo<'data, P: Platform> { pub(crate) kind: SectionKind<'data>, pub(crate) section_attributes: P::SectionAttributes, pub(crate) min_alignment: Alignment, - pub(crate) location: Option, + pub(crate) location: Option>, pub(crate) secondary_order: Option, } @@ -555,12 +555,12 @@ impl OutputSectionId { } } -#[derive(Debug, Clone, Copy)] -pub(crate) enum OrderEvent { +#[derive(Debug, Clone)] +pub(crate) enum OrderEvent<'data> { SegmentStart(ProgramSegmentId), SegmentEnd(ProgramSegmentId), Section(OutputSectionId), - SetLocation(linker_script::Location), + SetLocation(linker_script::Expression<'data>), } #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -600,7 +600,7 @@ impl<'data, P: Platform> OutputSections<'data, P> { for custom in custom_sections { let location = args .start_address_for_section(custom.name) - .map(|address| linker_script::Location { address }); + .map(linker_script::Expression::Number); let section_id = self.add_named_section(custom.name, custom.alignment, location); section_part_ids[custom.index.0] = section_id.part_id_with_alignment(custom.alignment); @@ -618,7 +618,7 @@ impl<'data, P: Platform> OutputSections<'data, P> { ] { if let Some(address) = args.start_address_for_section(name) { self.section_infos.get_mut(section_id).location = - Some(linker_script::Location { address }); + Some(linker_script::Expression::Number(address)); } } } @@ -627,7 +627,7 @@ impl<'data, P: Platform> OutputSections<'data, P> { &mut self, name: SectionName<'data>, min_alignment: Alignment, - location: Option, + location: Option>, ) -> OutputSectionId { *self.custom_by_name.entry(name).or_insert_with(|| { self.section_infos.add_new(SectionOutputInfo { @@ -660,6 +660,7 @@ impl<'data, P: Platform> OutputSections<'data, P> { pub(crate) fn with_base_address(base_address: u64) -> Self { let section_infos = P::built_in_section_infos(); + let base_address = Expression::Number(base_address); Self { section_infos: OutputSectionMap::from_values(section_infos), @@ -700,7 +701,7 @@ impl<'data, P: Platform> OutputSections<'data, P> { pub(crate) fn output_order( &self, output_kind: OutputKind, - ) -> (OutputOrder, ProgramSegments) { + ) -> (OutputOrder<'data>, ProgramSegments) { timing_phase!("Compute output order"); let mut custom = CustomSectionIds::default(); @@ -841,6 +842,10 @@ impl<'data, P: Platform> OutputSections<'data, P> { P::will_emit_section_symbol_for_partial_objects(self, section_id) } + pub(crate) fn set_base_address(&mut self, base_address: Expression<'data>) { + self.base_address = base_address; + } + #[cfg(test)] pub(crate) fn for_testing() -> OutputSections<'static, crate::elf::Elf> { use crate::elf::Elf; @@ -873,18 +878,18 @@ impl std::fmt::Display for OutputSectionId { } } -impl<'a> IntoIterator for &'a OutputOrder { - type Item = OrderEvent; +impl<'data, 'a> IntoIterator for &'a OutputOrder<'data> { + type Item = OrderEvent<'data>; - type IntoIter = Copied>; + type IntoIter = std::iter::Cloned>>; fn into_iter(self) -> Self::IntoIter { - self.events.iter().copied() + self.events.iter().cloned() } } -impl OutputOrder { - pub(crate) fn display<'a, 'data, P: Platform>( +impl<'data> OutputOrder<'data> { + pub(crate) fn display<'a, P: Platform>( &'a self, sections: &'a OutputSections<'data, P>, program_segments: &'a ProgramSegments, @@ -918,9 +923,7 @@ impl<'data, P: Platform> Display for OutputOrderDisplay<'_, 'data, P> { OrderEvent::Section(output_section_id) => { writeln!(f, " {}", self.sections.display_name(*output_section_id))?; } - OrderEvent::SetLocation(location) => { - writeln!(f, "SET_LOCATION(0x{:x})", location.address)?; - } + OrderEvent::SetLocation(expr) => writeln!(f, "SET_LOCATION({expr:?})")?, } } diff --git a/libwild/src/parsing.rs b/libwild/src/parsing.rs index 0a3ee667c..1333ccf93 100644 --- a/libwild/src/parsing.rs +++ b/libwild/src/parsing.rs @@ -96,11 +96,12 @@ pub(crate) enum SymbolPlacement<'data> { LoadBaseAddress, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub(crate) enum SymbolLoc { +#[derive(Clone, PartialEq, Eq, Debug)] +pub(crate) enum SymbolLoc<'data> { SectionStart(OutputSectionId), SectionEnd(OutputSectionId), FirstSection, + Expression(Expression<'data>, Option), None, } @@ -108,7 +109,7 @@ pub(crate) enum SymbolLoc { pub(crate) struct Redirect<'data> { pub(crate) kind: RedirectKind, pub(crate) expression: Expression<'data>, - pub(crate) loc: SymbolLoc, + pub(crate) loc: SymbolLoc<'data>, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] diff --git a/libwild/src/platform.rs b/libwild/src/platform.rs index c6f95e559..d457cf4e9 100644 --- a/libwild/src/platform.rs +++ b/libwild/src/platform.rs @@ -448,7 +448,7 @@ pub(crate) trait Platform: /// what we did wrong. Can optionally return a more helpful error. fn verify_resolution_allocation( _output_sections: &OutputSections, - _output_order: &OutputOrder, + _output_order: &OutputOrder<'_>, _output_kind: OutputKind, _mem_sizes: &OutputSectionPartMap, _resolution: &layout::Resolution, @@ -700,7 +700,7 @@ pub(crate) trait Platform: output_kind: OutputKind, output_sections: &OutputSections<'data, Self>, secondary: &OutputSectionMap>, - ) -> (OutputOrder, ProgramSegments); + ) -> (OutputOrder<'data>, ProgramSegments); fn will_emit_section_symbol_for_partial_objects( _output_sections: &OutputSections, diff --git a/libwild/src/wasm.rs b/libwild/src/wasm.rs index 567ae3a92..55cb54395 100644 --- a/libwild/src/wasm.rs +++ b/libwild/src/wasm.rs @@ -1574,7 +1574,7 @@ impl platform::Platform for Wasm { Vec, >, ) -> ( - crate::output_section_id::OutputOrder, + crate::output_section_id::OutputOrder<'data>, crate::program_segments::ProgramSegments, ) { use crate::output_section_id as osid; diff --git a/wild/tests/sources/elf/linker-script-executable/linker-script-executable.c b/wild/tests/sources/elf/linker-script-executable/linker-script-executable.c index b2d48c27c..b3571442d 100644 --- a/wild/tests/sources/elf/linker-script-executable/linker-script-executable.c +++ b/wild/tests/sources/elf/linker-script-executable/linker-script-executable.c @@ -9,12 +9,12 @@ #include "../common/runtime.h" int value = 42; -extern const char start_of_text; +extern const char start_of_sections; extern const char start_of_data; extern const char start_of_512; void begin_here(void) { - if ((size_t)&start_of_text != 0x600000) { + if ((size_t)&start_of_sections != 0x600000) { exit_syscall(10); } diff --git a/wild/tests/sources/elf/linker-script-executable/linker-script-executable.ld b/wild/tests/sources/elf/linker-script-executable/linker-script-executable.ld index d5ed6057c..f1e96fc49 100644 --- a/wild/tests/sources/elf/linker-script-executable/linker-script-executable.ld +++ b/wild/tests/sources/elf/linker-script-executable/linker-script-executable.ld @@ -2,9 +2,9 @@ ENTRY(begin_here) SECTIONS { - . = 0x600000; + . = 0x300000 * 2; + start_of_sections = .; .text : { - start_of_text = .; *(.text) } . = 0x800000;