From dc7e307c44112a00253cffb256c65abfa8a9cc17 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Tue, 30 Apr 2024 18:04:17 -0600 Subject: [PATCH] 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 --- assets/ldscript_partial.lcf | 8 +------- src/cmd/rel.rs | 30 +++++++++------------------ src/util/dol.rs | 21 +++++++++++++++++++ src/util/lcf.rs | 41 ++++++++++++------------------------- 4 files changed, 45 insertions(+), 55 deletions(-) diff --git a/assets/ldscript_partial.lcf b/assets/ldscript_partial.lcf index bf14bcf..6070a0b 100644 --- a/assets/ldscript_partial.lcf +++ b/assets/ldscript_partial.lcf @@ -2,13 +2,7 @@ SECTIONS { GROUP: { - .init :{} - .text :{} - .ctors :{} - .dtors :{} - .rodata :{} - .data :{ *(.data) *(extabindex) *(extab) } - .bss :{} + $SECTIONS } } diff --git a/src/cmd/rel.rs b/src/cmd/rel.rs index 89ab519..cc6e58f 100644 --- a/src/cmd/rel.rs +++ b/src/cmd/rel.rs @@ -30,7 +30,7 @@ use crate::{ cmd::dol::{ModuleConfig, ProjectConfig}, obj::{ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol}, util::{ - config::{is_auto_symbol, read_splits_sections, SectionDef}, + config::is_auto_symbol, dol::process_dol, elf::{to_obj_reloc_kind, write_elf}, file::{buf_reader, buf_writer, map_file, process_rsp, verify_hash, FileIterator}, @@ -170,12 +170,7 @@ fn load_rel(module_config: &ModuleConfig) -> Result { let mut reader = file.as_reader(); let header = process_rel_header(&mut reader)?; let sections = process_rel_sections(&mut reader, &header)?; - let section_defs = if let Some(splits_path) = &module_config.splits { - read_splits_sections(splits_path)? - } else { - None - }; - Ok((header, sections, section_defs)) + Ok((header, sections)) } fn resolve_relocations( @@ -191,12 +186,11 @@ fn resolve_relocations( if !matches!(section.name(), Ok(name) if PERMITTED_SECTIONS.contains(&name)) { continue; } - let section_index = - if let Some((_, sections, _)) = existing_headers.get(&(module_id as u32)) { - match_section_index(module, section.index(), sections)? - } else { - section.index().0 - } as u8; + let section_index = if let Some((_, sections)) = existing_headers.get(&(module_id as u32)) { + match_section_index(module, section.index(), sections)? + } else { + section.index().0 + } as u8; for (address, reloc) in section.relocations() { let reloc_target = match reloc.target() { RelocationTarget::Symbol(idx) => { @@ -223,7 +217,7 @@ fn resolve_relocations( (module_id, reloc_target) }; 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)) { match_section_index(&modules[target_module_id].0, target_section_index, sections)? @@ -246,7 +240,7 @@ fn resolve_relocations( Ok(resolved) } -type RelInfo = (RelHeader, Vec, Option>); +type RelInfo = (RelHeader, Vec); fn make(args: MakeArgs) -> Result<()> { let total = Instant::now(); @@ -347,17 +341,13 @@ fn make(args: MakeArgs) -> Result<()> { quiet: args.no_warn, 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.name_offset = Some(header.name_offset); info.name_size = Some(header.name_size); info.align = header.align; info.bss_align = header.bss_align; 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 mut w = buf_writer(&rel_path)?; diff --git a/src/util/dol.rs b/src/util/dol.rs index 3d9e127..4a0577a 100644 --- a/src/util/dol.rs +++ b/src/util/dol.rs @@ -15,6 +15,7 @@ use crate::{ }, util::{ alf::{AlfFile, AlfSymbol, ALF_MAGIC}, + align_up, reader::{skip_bytes, Endian, FromReader}, }, }; @@ -555,6 +556,26 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result { 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 let mut obj = ObjInfo::new( ObjKind::Executable, diff --git a/src/util/lcf.rs b/src/util/lcf.rs index 9661537..b61c6f2 100644 --- a/src/util/lcf.rs +++ b/src/util/lcf.rs @@ -1,13 +1,10 @@ use std::path::PathBuf; -use anyhow::{bail, Result}; +use anyhow::Result; use itertools::Itertools; use path_slash::PathBufExt; -use crate::{ - obj::{ObjInfo, ObjKind}, - util::align_up, -}; +use crate::obj::{ObjInfo, ObjKind}; const LCF_TEMPLATE: &str = include_str!("../../assets/ldscript.lcf"); const LCF_PARTIAL_TEMPLATE: &str = include_str!("../../assets/ldscript_partial.lcf"); @@ -27,32 +24,10 @@ pub fn generate_ldscript( _ => 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 .sections .iter() - .zip(alignments) - .map(|((_, s), align)| format!("{} ALIGN({:#X}):{{}}", s.name, align)) + .map(|(_, s)| format!("{} ALIGN({:#X}):{{}}", s.name, s.align)) .join("\n "); let mut force_files = Vec::with_capacity(obj.link_order.len()); @@ -89,6 +64,15 @@ pub fn generate_ldscript_partial( template: Option<&str>, force_active: &[String], ) -> Result { + 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()); for unit in &obj.link_order { let obj_path = obj_path_for_unit(&unit.name); @@ -104,6 +88,7 @@ pub fn generate_ldscript_partial( let out = template .unwrap_or(LCF_PARTIAL_TEMPLATE) + .replace("$SECTIONS", §ion_defs) .replace("$FORCEACTIVE", &force_active.join("\n ")); Ok(out) }