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
20 changes: 20 additions & 0 deletions libwild/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4023,6 +4023,26 @@ fn create_start_end_symbol_resolution(
sec.mem_offset + sec.mem_size
}

SymbolPlacement::SectionGroupEnd(section_id) => {
let mut end = {
let sec = resources.section_layouts.get(section_id);
sec.mem_offset + sec.mem_size
};

for (id, info) in resources.output_sections.ids_with_info() {
if let SectionKind::Secondary(primary_id) = info.kind
&& primary_id == section_id
{
let sec = resources.section_layouts.get(id);
let candidate_end = sec.mem_offset + sec.mem_size;
if candidate_end > end {
end = candidate_end;
}
}
}
end
}

SymbolPlacement::DefsymAbsolute(value) => value,

SymbolPlacement::DefsymSymbol(_) => {
Expand Down
16 changes: 14 additions & 2 deletions libwild/src/layout_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ pub(crate) enum SectionRuleOutcome {
NoteGnuProperty,
Debug,
RiscVAttribute,
SortedSection(SectionOutputInfo),
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down Expand Up @@ -154,6 +155,7 @@ impl<'data> LayoutRulesBuilder<'data> {
output_sections.add_secondary_section(
primary_section_id,
replace(&mut extra_min_alignment, alignment::MIN),
None,
)
};

Expand Down Expand Up @@ -294,6 +296,16 @@ impl<'data> SectionRule<'data> {
)
}

const fn prefix_section_sort(
name: &'data [u8],
section_id: OutputSectionId,
) -> SectionRule<'data> {
Self::prefix(
name,
SectionRuleOutcome::SortedSection(SectionOutputInfo::keep(section_id)),
)
}

const fn exact(name: &'data [u8], outcome: SectionRuleOutcome) -> SectionRule<'data> {
SectionRule {
name,
Expand Down Expand Up @@ -335,12 +347,12 @@ const BUILT_IN_RULES: &[SectionRule<'static>] = &[
),
SectionRule::prefix_section(secnames::DATA_SECTION_NAME, output_section_id::DATA),
SectionRule::prefix_section(secnames::BSS_SECTION_NAME, output_section_id::BSS),
SectionRule::prefix_section_keep(
SectionRule::prefix_section_sort(
secnames::INIT_ARRAY_SECTION_NAME,
output_section_id::INIT_ARRAY,
),
SectionRule::prefix_section_keep(b".ctors", output_section_id::INIT_ARRAY),
SectionRule::prefix_section_keep(
SectionRule::prefix_section_sort(
secnames::FINI_ARRAY_SECTION_NAME,
output_section_id::FINI_ARRAY,
),
Expand Down
89 changes: 82 additions & 7 deletions libwild/src/output_section_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ pub(crate) struct CustomSectionDetails<'data> {
pub(crate) alignment: Alignment,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct InitFiniSectionDetail {
pub(crate) index: u32,
pub(crate) primary: OutputSectionId,
pub(crate) priority: u16,
pub(crate) alignment: Alignment,
}

// Single-part sections that we generate ourselves rather than copying directly from input objects.
pub(crate) const FILE_HEADER: OutputSectionId = part_id::FILE_HEADER.output_section_id();
pub(crate) const PROGRAM_HEADERS: OutputSectionId = part_id::PROGRAM_HEADERS.output_section_id();
Expand Down Expand Up @@ -136,6 +144,8 @@ pub(crate) struct OutputSections<'data> {
pub(crate) output_section_indexes: Vec<Option<u16>>,

custom_by_name: HashMap<SectionName<'data>, OutputSectionId>,

init_fini_by_priority: HashMap<(OutputSectionId, u16), OutputSectionId>,
}

/// Encodes the order of output sections and the start and end of each program segment. This struct
Expand Down Expand Up @@ -206,8 +216,25 @@ impl<'scope, 'data> OutputOrderBuilder<'scope, 'data> {

self.events.push(OrderEvent::Section(section_id));

for secondary_id in self.secondary.get(section_id) {
self.events.push(OrderEvent::Section(*secondary_id));
let secondaries: &Vec<OutputSectionId> = self.secondary.get(section_id);
// stable ordering: tie-break by original index
let mut keyed: Vec<(u16, OutputSectionId)> = secondaries
.iter()
.map(|&sid| {
// default: put non-initfini after all initfini, and keep their relative order
let key_pri = match self.output_sections.secondary_order(sid) {
Some(crate::output_section_id::SecondaryOrder::InitFini { priority }) => {
priority
}
None => u16::MAX,
};
(key_pri, sid)
})
.collect();
keyed.sort_by_key(|(pri, _sid)| *pri);

for (_pri, sid) in keyed {
self.events.push(OrderEvent::Section(sid));
}
}

Expand Down Expand Up @@ -391,6 +418,7 @@ pub(crate) struct SectionOutputInfo<'data> {
pub(crate) min_alignment: Alignment,
pub(crate) entsize: u64,
pub(crate) location: Option<linker_script::Location>,
pub(crate) secondary_order: Option<SecondaryOrder>,
}

pub(crate) struct BuiltInSectionDetails {
Expand All @@ -400,6 +428,7 @@ pub(crate) struct BuiltInSectionDetails {
pub(crate) link: &'static [OutputSectionId],
pub(crate) start_symbol_name: Option<&'static str>,
pub(crate) end_symbol_name: Option<&'static str>,
pub(crate) group_end_symbol_name: Option<&'static str>,
pub(crate) min_alignment: Alignment,
info_fn: Option<fn(&InfoInputs) -> u32>,
pub(crate) keep_if_empty: bool,
Expand All @@ -416,6 +445,7 @@ const DEFAULT_DEFS: BuiltInSectionDetails = BuiltInSectionDetails {
link: &[],
start_symbol_name: None,
end_symbol_name: None,
group_end_symbol_name: None,
min_alignment: alignment::MIN,
info_fn: None,
keep_if_empty: false,
Expand Down Expand Up @@ -654,7 +684,8 @@ const SECTION_DEFINITIONS: [BuiltInSectionDetails; NUM_BUILT_IN_SECTIONS] = [
section_flags: shf::ALLOC.with(shf::WRITE),
element_size: size_of::<u64>() as u64,
start_symbol_name: Some("__init_array_start"),
end_symbol_name: Some("__init_array_end"),
group_end_symbol_name: Some("__init_array_end"),
min_alignment: alignment::USIZE,
is_relro: true,
..DEFAULT_DEFS
},
Expand All @@ -664,7 +695,8 @@ const SECTION_DEFINITIONS: [BuiltInSectionDetails; NUM_BUILT_IN_SECTIONS] = [
section_flags: shf::ALLOC.with(shf::WRITE),
element_size: size_of::<u64>() as u64,
start_symbol_name: Some("__fini_array_start"),
end_symbol_name: Some("__fini_array_end"),
group_end_symbol_name: Some("__fini_array_end"),
min_alignment: alignment::USIZE,
is_relro: true,
..DEFAULT_DEFS
},
Expand Down Expand Up @@ -884,6 +916,11 @@ impl Debug for SectionName<'_> {
}
}

#[derive(Debug, Clone, Copy)]
pub(crate) enum SecondaryOrder {
InitFini { priority: u16 },
}

impl CustomSectionIds {
fn build_output_order_and_program_segments(
&self,
Expand Down Expand Up @@ -948,6 +985,9 @@ impl CustomSectionIds {
}

impl<'data> OutputSections<'data> {
pub(crate) fn secondary_order(&self, id: OutputSectionId) -> Option<SecondaryOrder> {
self.section_infos.get(id).secondary_order
}
pub(crate) fn add_sections(
&mut self,
custom_sections: &[CustomSectionDetails<'data>],
Expand Down Expand Up @@ -985,6 +1025,7 @@ impl<'data> OutputSections<'data> {
min_alignment,
entsize: 0,
location,
secondary_order: None,
})
})
}
Expand All @@ -993,14 +1034,19 @@ impl<'data> OutputSections<'data> {
&mut self,
primary_id: OutputSectionId,
min_alignment: Alignment,
secondary_order: Option<SecondaryOrder>,
) -> OutputSectionId {
let primary_entsize = self.section_infos.get(primary_id).entsize;
let section_flag = self.section_infos.get(primary_id).section_flags;
let ty = self.section_infos.get(primary_id).ty;
self.section_infos.add_new(SectionOutputInfo {
kind: SectionKind::Secondary(primary_id),
section_flags: SectionFlags::empty(),
ty: SectionType::from_u32(0),
section_flags: section_flag,
ty,
min_alignment,
entsize: 0,
entsize: primary_entsize,
location: None,
secondary_order,
})
}

Expand All @@ -1014,6 +1060,7 @@ impl<'data> OutputSections<'data> {
min_alignment: d.min_alignment,
entsize: d.element_size,
location: None,
secondary_order: None,
})
.collect();

Expand All @@ -1022,7 +1069,35 @@ impl<'data> OutputSections<'data> {
base_address,
custom_by_name: HashMap::new(),
output_section_indexes: Default::default(),
init_fini_by_priority: HashMap::new(),
}
}

pub(crate) fn bump_min_alignment(&mut self, sid: OutputSectionId, a: Alignment) {
let info = self.section_infos.get_mut(sid);
info.min_alignment = core::cmp::max(info.min_alignment, a);
}

pub(crate) fn get_or_create_init_fini_secondary(
&mut self,
primary: OutputSectionId,
priority: u16,
min_alignment: Alignment,
) -> OutputSectionId {
let key = (primary, priority);
if let Some(&sid) = self.init_fini_by_priority.get(&key) {
self.bump_min_alignment(sid, min_alignment);
return sid;
}

let sid = self.add_secondary_section(
primary,
min_alignment,
Some(SecondaryOrder::InitFini { priority }),
);

self.init_fini_by_priority.insert(key, sid);
sid
}

pub(crate) fn output_order(&self) -> (OutputOrder, ProgramSegments) {
Expand Down
9 changes: 9 additions & 0 deletions libwild/src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ pub(crate) enum SymbolPlacement<'data> {
/// last byte of the section.
SectionEnd(OutputSectionId),

SectionGroupEnd(OutputSectionId),

/// An undefined symbol supplied by the user, e.g. via `--undefined=symbol-name`.
ForceUndefined,

Expand Down Expand Up @@ -181,6 +183,13 @@ impl<'data> Prelude<'data> {
name.as_bytes(),
));
}

if let Some(name) = def.group_end_symbol_name {
symbol_definitions.push(InternalSymDefInfo::notype(
SymbolPlacement::SectionGroupEnd(section_id),
name.as_bytes(),
));
}
}

// We define _TLS_MODULE_BASE_ either at the start or end of the TLS segment, depending on
Expand Down
Loading
Loading