Rework section alignment handling
- Honor splits.txt alignment values when writing ldscript.lcf - Add alignment values to ldscript_partial.lcf, remove hacky code from rel make - Guess alignment values in DOL loader Fixes #27
This commit is contained in:
parent
dac2dcfc9e
commit
dc7e307c44
|
@ -2,13 +2,7 @@ SECTIONS
|
||||||
{
|
{
|
||||||
GROUP:
|
GROUP:
|
||||||
{
|
{
|
||||||
.init :{}
|
$SECTIONS
|
||||||
.text :{}
|
|
||||||
.ctors :{}
|
|
||||||
.dtors :{}
|
|
||||||
.rodata :{}
|
|
||||||
.data :{ *(.data) *(extabindex) *(extab) }
|
|
||||||
.bss :{}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ use crate::{
|
||||||
cmd::dol::{ModuleConfig, ProjectConfig},
|
cmd::dol::{ModuleConfig, ProjectConfig},
|
||||||
obj::{ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol},
|
obj::{ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol},
|
||||||
util::{
|
util::{
|
||||||
config::{is_auto_symbol, read_splits_sections, SectionDef},
|
config::is_auto_symbol,
|
||||||
dol::process_dol,
|
dol::process_dol,
|
||||||
elf::{to_obj_reloc_kind, write_elf},
|
elf::{to_obj_reloc_kind, write_elf},
|
||||||
file::{buf_reader, buf_writer, map_file, process_rsp, verify_hash, FileIterator},
|
file::{buf_reader, buf_writer, map_file, process_rsp, verify_hash, FileIterator},
|
||||||
|
@ -170,12 +170,7 @@ fn load_rel(module_config: &ModuleConfig) -> Result<RelInfo> {
|
||||||
let mut reader = file.as_reader();
|
let mut reader = file.as_reader();
|
||||||
let header = process_rel_header(&mut reader)?;
|
let header = process_rel_header(&mut reader)?;
|
||||||
let sections = process_rel_sections(&mut reader, &header)?;
|
let sections = process_rel_sections(&mut reader, &header)?;
|
||||||
let section_defs = if let Some(splits_path) = &module_config.splits {
|
Ok((header, sections))
|
||||||
read_splits_sections(splits_path)?
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
};
|
|
||||||
Ok((header, sections, section_defs))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_relocations(
|
fn resolve_relocations(
|
||||||
|
@ -191,8 +186,7 @@ fn resolve_relocations(
|
||||||
if !matches!(section.name(), Ok(name) if PERMITTED_SECTIONS.contains(&name)) {
|
if !matches!(section.name(), Ok(name) if PERMITTED_SECTIONS.contains(&name)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let section_index =
|
let section_index = if let Some((_, sections)) = existing_headers.get(&(module_id as u32)) {
|
||||||
if let Some((_, sections, _)) = existing_headers.get(&(module_id as u32)) {
|
|
||||||
match_section_index(module, section.index(), sections)?
|
match_section_index(module, section.index(), sections)?
|
||||||
} else {
|
} else {
|
||||||
section.index().0
|
section.index().0
|
||||||
|
@ -223,7 +217,7 @@ fn resolve_relocations(
|
||||||
(module_id, reloc_target)
|
(module_id, reloc_target)
|
||||||
};
|
};
|
||||||
let target_section_index = target_symbol.section_index().unwrap();
|
let target_section_index = target_symbol.section_index().unwrap();
|
||||||
let target_section = if let Some((_, sections, _)) =
|
let target_section = if let Some((_, sections)) =
|
||||||
existing_headers.get(&(target_module_id as u32))
|
existing_headers.get(&(target_module_id as u32))
|
||||||
{
|
{
|
||||||
match_section_index(&modules[target_module_id].0, target_section_index, sections)?
|
match_section_index(&modules[target_module_id].0, target_section_index, sections)?
|
||||||
|
@ -246,7 +240,7 @@ fn resolve_relocations(
|
||||||
Ok(resolved)
|
Ok(resolved)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RelInfo = (RelHeader, Vec<RelSectionHeader>, Option<Vec<SectionDef>>);
|
type RelInfo = (RelHeader, Vec<RelSectionHeader>);
|
||||||
|
|
||||||
fn make(args: MakeArgs) -> Result<()> {
|
fn make(args: MakeArgs) -> Result<()> {
|
||||||
let total = Instant::now();
|
let total = Instant::now();
|
||||||
|
@ -347,17 +341,13 @@ fn make(args: MakeArgs) -> Result<()> {
|
||||||
quiet: args.no_warn,
|
quiet: args.no_warn,
|
||||||
section_align: None,
|
section_align: None,
|
||||||
};
|
};
|
||||||
if let Some((header, _, section_defs)) = existing_headers.get(&(module_id as u32)) {
|
if let Some((header, _)) = existing_headers.get(&(module_id as u32)) {
|
||||||
info.version = header.version;
|
info.version = header.version;
|
||||||
info.name_offset = Some(header.name_offset);
|
info.name_offset = Some(header.name_offset);
|
||||||
info.name_size = Some(header.name_size);
|
info.name_size = Some(header.name_size);
|
||||||
info.align = header.align;
|
info.align = header.align;
|
||||||
info.bss_align = header.bss_align;
|
info.bss_align = header.bss_align;
|
||||||
info.section_count = Some(header.num_sections as usize);
|
info.section_count = Some(header.num_sections as usize);
|
||||||
info.section_align = section_defs
|
|
||||||
.as_ref()
|
|
||||||
.map(|defs| defs.iter().map(|def| def.align).collect())
|
|
||||||
.unwrap_or_default();
|
|
||||||
}
|
}
|
||||||
let rel_path = path.with_extension("rel");
|
let rel_path = path.with_extension("rel");
|
||||||
let mut w = buf_writer(&rel_path)?;
|
let mut w = buf_writer(&rel_path)?;
|
||||||
|
|
|
@ -15,6 +15,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
alf::{AlfFile, AlfSymbol, ALF_MAGIC},
|
alf::{AlfFile, AlfSymbol, ALF_MAGIC},
|
||||||
|
align_up,
|
||||||
reader::{skip_bytes, Endian, FromReader},
|
reader::{skip_bytes, Endian, FromReader},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -555,6 +556,26 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
|
||||||
section.elf_index = idx + 1;
|
section.elf_index = idx + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Guess section alignment
|
||||||
|
let mut last_section_end = sections.first().map_or(0, |s| s.address as u32);
|
||||||
|
for section in &mut sections {
|
||||||
|
let section_start = section.address as u32;
|
||||||
|
let mut align = 4;
|
||||||
|
while align_up(last_section_end, align) < section_start {
|
||||||
|
align = (align + 1).next_power_of_two();
|
||||||
|
}
|
||||||
|
if align_up(last_section_end, align) != section_start {
|
||||||
|
bail!(
|
||||||
|
"Couldn't determine alignment for section '{}' ({:#010X} -> {:#010X})",
|
||||||
|
section.name,
|
||||||
|
last_section_end,
|
||||||
|
section_start
|
||||||
|
);
|
||||||
|
}
|
||||||
|
last_section_end = section_start + section.size as u32;
|
||||||
|
section.align = align as u64;
|
||||||
|
}
|
||||||
|
|
||||||
// Create object
|
// Create object
|
||||||
let mut obj = ObjInfo::new(
|
let mut obj = ObjInfo::new(
|
||||||
ObjKind::Executable,
|
ObjKind::Executable,
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use anyhow::{bail, Result};
|
use anyhow::Result;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use path_slash::PathBufExt;
|
use path_slash::PathBufExt;
|
||||||
|
|
||||||
use crate::{
|
use crate::obj::{ObjInfo, ObjKind};
|
||||||
obj::{ObjInfo, ObjKind},
|
|
||||||
util::align_up,
|
|
||||||
};
|
|
||||||
|
|
||||||
const LCF_TEMPLATE: &str = include_str!("../../assets/ldscript.lcf");
|
const LCF_TEMPLATE: &str = include_str!("../../assets/ldscript.lcf");
|
||||||
const LCF_PARTIAL_TEMPLATE: &str = include_str!("../../assets/ldscript_partial.lcf");
|
const LCF_PARTIAL_TEMPLATE: &str = include_str!("../../assets/ldscript_partial.lcf");
|
||||||
|
@ -27,32 +24,10 @@ pub fn generate_ldscript(
|
||||||
_ => 65535, // default
|
_ => 65535, // default
|
||||||
};
|
};
|
||||||
|
|
||||||
// Guess section alignment
|
|
||||||
let mut alignments = Vec::with_capacity(obj.sections.count());
|
|
||||||
let mut last_section_end = origin as u32;
|
|
||||||
for (_, section) in obj.sections.iter() {
|
|
||||||
let section_start = section.address as u32;
|
|
||||||
let mut align = 0x20;
|
|
||||||
while align_up(last_section_end, align) < section_start {
|
|
||||||
align = (align + 1).next_power_of_two();
|
|
||||||
}
|
|
||||||
if align_up(last_section_end, align) != section_start {
|
|
||||||
bail!(
|
|
||||||
"Couldn't determine alignment for section '{}' ({:#010X} -> {:#010X})",
|
|
||||||
section.name,
|
|
||||||
last_section_end,
|
|
||||||
section_start
|
|
||||||
);
|
|
||||||
}
|
|
||||||
last_section_end = section_start + section.size as u32;
|
|
||||||
alignments.push(align);
|
|
||||||
}
|
|
||||||
|
|
||||||
let section_defs = obj
|
let section_defs = obj
|
||||||
.sections
|
.sections
|
||||||
.iter()
|
.iter()
|
||||||
.zip(alignments)
|
.map(|(_, s)| format!("{} ALIGN({:#X}):{{}}", s.name, s.align))
|
||||||
.map(|((_, s), align)| format!("{} ALIGN({:#X}):{{}}", s.name, align))
|
|
||||||
.join("\n ");
|
.join("\n ");
|
||||||
|
|
||||||
let mut force_files = Vec::with_capacity(obj.link_order.len());
|
let mut force_files = Vec::with_capacity(obj.link_order.len());
|
||||||
|
@ -89,6 +64,15 @@ pub fn generate_ldscript_partial(
|
||||||
template: Option<&str>,
|
template: Option<&str>,
|
||||||
force_active: &[String],
|
force_active: &[String],
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
|
let section_defs = obj
|
||||||
|
.sections
|
||||||
|
.iter()
|
||||||
|
.map(|(_, s)| {
|
||||||
|
let inner = if s.name == ".data" { " *(.data) *(extabindex) *(extab) " } else { "" };
|
||||||
|
format!("{} ALIGN({:#X}):{{{}}}", s.name, s.align, inner)
|
||||||
|
})
|
||||||
|
.join("\n ");
|
||||||
|
|
||||||
let mut force_files = Vec::with_capacity(obj.link_order.len());
|
let mut force_files = Vec::with_capacity(obj.link_order.len());
|
||||||
for unit in &obj.link_order {
|
for unit in &obj.link_order {
|
||||||
let obj_path = obj_path_for_unit(&unit.name);
|
let obj_path = obj_path_for_unit(&unit.name);
|
||||||
|
@ -104,6 +88,7 @@ pub fn generate_ldscript_partial(
|
||||||
|
|
||||||
let out = template
|
let out = template
|
||||||
.unwrap_or(LCF_PARTIAL_TEMPLATE)
|
.unwrap_or(LCF_PARTIAL_TEMPLATE)
|
||||||
|
.replace("$SECTIONS", §ion_defs)
|
||||||
.replace("$FORCEACTIVE", &force_active.join("\n "));
|
.replace("$FORCEACTIVE", &force_active.join("\n "));
|
||||||
Ok(out)
|
Ok(out)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue