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
4 changes: 2 additions & 2 deletions LINKER_SCRIPT_SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ end lists the features required to link the Linux kernel.
| `OVERLAY { ... }` | ❌ | |
| Output section type specifiers (`(NOLOAD)`, `(COPY)`, etc.) | 📅 | |
| `FILL(value)` and `=fillexp` | 📅 | |
| `AT(addr)` load-address specifier on output sections | 📅 | |
| `AT(addr)` load-address specifier on output sections | | |
| Numeric address between section name and `:` (e.g. `name 0 : { ... }`) | 🧪 | Only numeric literals are currently supported |
| `SORT_BY_NAME(...)`, `SORT_BY_ALIGNMENT(...)`, `SORT_BY_INIT_PRIORITY(...)` | 📅 | |
| `EXCLUDE_FILE(...)` inside input section matchers | 📅 | |
Expand Down Expand Up @@ -115,7 +115,7 @@ see at a glance what remains before Wild can link the kernel.
| `OVERLAY { ... }` sections | ❌ | |
| Output section type specifiers (`(NOLOAD)`, `(COPY)`) | 📅 | |
| `FILL(value)` and `=fillexp` | 📅 | |
| `AT(addr)` load-address specifier on output sections | 📅 | |
| `AT(addr)` load-address specifier on output sections | | |
| `>region` and `AT>region` memory region placement | 📅 | |
| `SORT_BY_NAME(...)`, `SORT_BY_ALIGNMENT(...)`, `SORT_BY_INIT_PRIORITY(...)` | 📅 | |
| `EXCLUDE_FILE(...)` inside input section matchers | 📅 | |
Expand Down
1 change: 1 addition & 0 deletions libwild/src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,7 @@ impl platform::Platform for Elf {
kind: d.kind,
min_alignment: d.min_alignment,
location: None,
load_location: None,
secondary_order: None,
phdr_name: None,
})
Expand Down
2 changes: 1 addition & 1 deletion libwild/src/elf_writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ fn write_program_headers(
.p_offset
.set(e, segment_sizes.file_offset as u64);
segment_header.p_vaddr.set(e, segment_sizes.mem_offset);
segment_header.p_paddr.set(e, segment_sizes.mem_offset);
segment_header.p_paddr.set(e, segment_sizes.lma_offset);
segment_header
.p_filesz
.set(e, segment_sizes.file_size as u64);
Expand Down
35 changes: 35 additions & 0 deletions libwild/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1297,6 +1297,7 @@ pub(crate) struct OutputRecordLayout {
pub(crate) alignment: Alignment,
pub(crate) file_offset: usize,
pub(crate) mem_offset: u64,
pub(crate) lma_offset: u64,
}

pub(crate) struct GraphResources<'data, 'scope, P: Platform> {
Expand Down Expand Up @@ -1603,15 +1604,19 @@ fn layout_sections<P: Platform>(
let info = output_sections.section_infos.get(section_id);
let mut file_offset = usize::MAX;
let mut mem_offset = u64::MAX;
let mut lma_offset = u64::MAX;
let mut file_end = 0;
let mut mem_end = 0;
let mut lma_end = 0;
let mut alignment = info.min_alignment;

for part in layouts {
file_offset = file_offset.min(part.file_offset);
mem_offset = mem_offset.min(part.mem_offset);
lma_offset = lma_offset.min(part.lma_offset);
file_end = file_end.max(part.file_offset + part.file_size);
mem_end = mem_end.max(part.mem_offset + part.mem_size);
lma_end = lma_end.max(part.lma_offset + part.mem_size);
if part.mem_size > 0 {
alignment = alignment.max(part.alignment);
}
Expand All @@ -1622,6 +1627,7 @@ fn layout_sections<P: Platform>(
alignment,
file_offset,
mem_offset,
lma_offset,
}
})
}
Expand Down Expand Up @@ -1710,6 +1716,8 @@ fn compute_segment_layout<'data, P: Platform>(
file_end: usize,
mem_start: u64,
mem_end: u64,
lma_start: u64,
lma_end: u64,
alignment: Alignment,
}

Expand All @@ -1734,6 +1742,8 @@ fn compute_segment_layout<'data, P: Platform>(
file_end: 0,
mem_start: 0,
mem_end: args.stack_size_override().map_or(0, |size| size.get()),
lma_start: 0,
lma_end: args.stack_size_override().map_or(0, |size| size.get()),
alignment: alignment::MIN,
});
} else {
Expand All @@ -1743,6 +1753,8 @@ fn compute_segment_layout<'data, P: Platform>(
file_end: 0,
mem_start: u64::MAX,
mem_end: 0,
lma_start: u64::MAX,
lma_end: 0,
alignment: alignment::MIN,
});
}
Expand Down Expand Up @@ -1795,12 +1807,16 @@ fn compute_segment_layout<'data, P: Platform>(

rec.file_start = rec.file_start.min(section_layout.file_offset);
rec.mem_start = rec.mem_start.min(section_layout.mem_offset);
rec.lma_start = rec.lma_start.min(section_layout.lma_offset);
rec.file_end = rec
.file_end
.max(section_layout.file_offset + section_layout.file_size);
rec.mem_end = rec
.mem_end
.max(section_layout.mem_offset + section_layout.mem_size);
rec.lma_end = rec
.lma_end
.max(section_layout.lma_offset + section_layout.mem_size);
rec.alignment = rec.alignment.max(section_layout.alignment);
}
}
Expand All @@ -1826,6 +1842,7 @@ fn compute_segment_layout<'data, P: Platform>(
alignment: r.alignment,
file_offset: r.file_start,
mem_offset: r.mem_start,
lma_offset: r.lma_start,
};

if program_segments.is_tls_segment(id) {
Expand Down Expand Up @@ -4849,6 +4866,7 @@ fn layout_section_parts<'data, P: Platform>(

let mut file_offset = 0;
let mut mem_offset = expression_eval(&output_sections.base_address)?;
let mut lma_offset = mem_offset;
let mut nonalloc_mem_offsets: OutputSectionMap<u64> =
OutputSectionMap::with_size(output_sections.num_sections());
let mut reloc_alloc_mem_offsets: OutputSectionMap<u64> =
Expand All @@ -4872,6 +4890,7 @@ fn layout_section_parts<'data, P: Platform>(
if let Some(expr) = pending_location.take() {
// The OrderEvent::SetLocation is ELF-specific only.
mem_offset = expression_eval(&expr)?;
lma_offset = mem_offset;
file_offset =
segment_alignment.align_modulo(mem_offset, file_offset as u64) as usize;
} else {
Expand All @@ -4882,6 +4901,12 @@ fn layout_section_parts<'data, P: Platform>(
&mut file_offset,
&mut mem_offset,
);
P::align_load_segment_start(
segment_def,
segment_alignment,
&mut file_offset,
&mut lma_offset,
);
}
}
}
Expand All @@ -4897,6 +4922,11 @@ fn layout_section_parts<'data, P: Platform>(
if let Some(ref expr) = section_info.location {
mem_offset = expression_eval(expr)?;
}
if let Some(ref expr) = section_info.load_location {
lma_offset = expression_eval(expr)?;
} else {
lma_offset = mem_offset;
}

records_out[part_id_range.clone()]
.iter_mut()
Expand Down Expand Up @@ -4939,11 +4969,13 @@ fn layout_section_parts<'data, P: Platform>(
alignment,
file_offset,
mem_offset: part_mem_offset,
lma_offset: part_mem_offset,
};

file_offset += file_size;
} else {
mem_offset = alignment.align_up(mem_offset);
lma_offset = alignment.align_up(lma_offset);

let file_size = if output_sections.has_data_in_file(merge_target) {
mem_size as usize
Expand All @@ -4957,10 +4989,12 @@ fn layout_section_parts<'data, P: Platform>(
alignment,
file_offset,
mem_offset,
lma_offset,
};

file_offset += file_size;
mem_offset += mem_size;
lma_offset += mem_size;
}
} else {
let section_id = part_id.output_section_id();
Expand All @@ -4975,6 +5009,7 @@ fn layout_section_parts<'data, P: Platform>(
alignment,
file_offset,
mem_offset,
lma_offset: mem_offset,
};
file_offset += mem_size as usize;
}
Expand Down
1 change: 1 addition & 0 deletions libwild/src/layout_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ impl<'data> LayoutRulesBuilder<'data> {
SectionName(sec.output_section_name),
min_alignment,
section_location,
sec.at_address.clone(),
sec.phdr,
);
current_section_id = Some(primary_section_id);
Expand Down
28 changes: 27 additions & 1 deletion libwild/src/linker_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ pub(crate) struct Section<'a> {
pub(crate) alignment: Option<Alignment>,
pub(crate) start_address_expression: Option<Expression<'a>>,
pub(crate) phdr: Option<&'a [u8]>,
pub(crate) at_address: Option<Expression<'a>>,
}

#[derive(Debug, PartialEq, Eq, Clone)]
Expand Down Expand Up @@ -1063,9 +1064,14 @@ fn parse_section_command<'input>(
skip_comments_and_whitespace(input)?;

let mut alignment = None;
let mut at_address = None;

while !input.starts_with(b"{") {
alignment = Some(parse_alignment.parse_next(input)?);
if opt("AT").parse_next(input)?.is_some() {
at_address = Some(parse_at_address.parse_next(input)?);
} else {
alignment = Some(parse_alignment.parse_next(input)?);
}
}

'{'.parse_next(input)?;
Expand All @@ -1089,6 +1095,7 @@ fn parse_section_command<'input>(
alignment,
start_address_expression,
phdr,
at_address,
}))
}

Expand All @@ -1107,6 +1114,17 @@ fn parse_alignment(input: &mut &BStr) -> winnow::Result<Alignment> {
Ok(alignment)
}

fn parse_at_address<'input>(input: &mut &'input BStr) -> winnow::Result<Expression<'input>> {
skip_comments_and_whitespace(input)?;
'('.parse_next(input)?;
skip_comments_and_whitespace(input)?;
let address = parse_expression.parse_next(input)?;
skip_comments_and_whitespace(input)?;
')'.parse_next(input)?;
skip_comments_and_whitespace(input)?;
Ok(address)
}

fn parse_contents_command<'input>(
input: &mut &'input BStr,
) -> winnow::Result<ContentsCommand<'input>> {
Expand Down Expand Up @@ -1416,6 +1434,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
}),
);
}
Expand All @@ -1434,6 +1453,7 @@ mod tests {
alignment: Some(Alignment::new(8).unwrap()),
start_address_expression: Some(Expression::Number(0)),
phdr: None,
at_address: None,
}),
);
}
Expand Down Expand Up @@ -1490,6 +1510,7 @@ mod tests {
alignment: Some(Alignment::new(8).unwrap()),
start_address_expression: None,
phdr: None,
at_address: None,
}),
],
}),
Expand Down Expand Up @@ -1627,6 +1648,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
}),
);
}
Expand All @@ -1645,6 +1667,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
}),
);
}
Expand All @@ -1663,6 +1686,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
}),
);
}
Expand All @@ -1689,6 +1713,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
})],
}),
Command::Assert(AssertCommand {
Expand Down Expand Up @@ -1726,6 +1751,7 @@ mod tests {
alignment: None,
start_address_expression: None,
phdr: None,
at_address: None,
}),
SectionCommand::Assert(AssertCommand {
expression: Expression::LessThan(
Expand Down
1 change: 1 addition & 0 deletions libwild/src/macho.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,6 +1189,7 @@ impl platform::Platform for MachO {
kind: d.kind,
min_alignment: d.min_alignment,
location: None,
load_location: None,
secondary_order: None,
phdr_name: None,
})
Expand Down
12 changes: 10 additions & 2 deletions libwild/src/output_section_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,6 +503,7 @@ pub(crate) struct SectionOutputInfo<'data, P: Platform> {
pub(crate) section_attributes: P::SectionAttributes,
pub(crate) min_alignment: Alignment,
pub(crate) location: Option<linker_script::Expression<'data>>,
pub(crate) load_location: Option<linker_script::Expression<'data>>,
pub(crate) secondary_order: Option<SecondaryOrder>,
pub(crate) phdr_name: Option<&'data [u8]>,
}
Expand Down Expand Up @@ -642,7 +643,8 @@ impl<'data, P: Platform> OutputSections<'data, P> {
let location = args
.start_address_for_section(custom.name)
.map(linker_script::Expression::Number);
let section_id = self.add_named_section(custom.name, custom.alignment, location, None);
let section_id =
self.add_named_section(custom.name, custom.alignment, location, None, None);

section_part_ids[custom.index.0] = section_id.part_id_with_alignment(custom.alignment);
}
Expand All @@ -669,6 +671,7 @@ impl<'data, P: Platform> OutputSections<'data, P> {
name: SectionName<'data>,
min_alignment: Alignment,
location: Option<linker_script::Expression<'data>>,
load_location: Option<linker_script::Expression<'data>>,
phdr_name: Option<&'data [u8]>,
) -> OutputSectionId {
*self.custom_by_name.entry(name).or_insert_with(|| {
Expand All @@ -679,6 +682,7 @@ impl<'data, P: Platform> OutputSections<'data, P> {
section_attributes: Default::default(),
min_alignment,
location,
load_location,
secondary_order: None,
phdr_name,
})
Expand All @@ -691,12 +695,15 @@ impl<'data, P: Platform> OutputSections<'data, P> {
min_alignment: Alignment,
secondary_order: Option<SecondaryOrder>,
) -> OutputSectionId {
let section_attributes = self.section_infos.get(primary_id).section_attributes;
let primary_info = self.section_infos.get(primary_id);
let section_attributes = primary_info.section_attributes;
let load_location = primary_info.load_location.clone();
self.section_infos.add_new(SectionOutputInfo {
kind: SectionKind::Secondary(primary_id),
section_attributes,
min_alignment,
location: None,
load_location,
secondary_order,
phdr_name: None,
})
Expand Down Expand Up @@ -949,6 +956,7 @@ impl<'data, P: Platform> OutputSections<'data, P> {
crate::alignment::MIN,
None,
None,
None,
)
};
add_name("ro");
Expand Down
1 change: 1 addition & 0 deletions libwild/src/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,7 @@ impl platform::Platform for Wasm {
kind: d.kind,
min_alignment: crate::alignment::MIN,
location: None,
load_location: None,
secondary_order: None,
phdr_name: None,
})
Expand Down
Loading
Loading