Migrate SectionIndex/SymbolIndex to u32

This halves the size of structs like SectionAddress.
This commit is contained in:
Luke Street 2024-10-04 20:40:50 -06:00
parent 1f4b452bd5
commit b184fee73f
24 changed files with 263 additions and 215 deletions

View File

@ -16,12 +16,15 @@ use crate::{
vm::{BranchTarget, GprValue, StepResult, VM},
RelocationTarget,
},
obj::{ObjInfo, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind},
obj::{
ObjInfo, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
SectionIndex,
},
};
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SectionAddress {
pub section: usize,
pub section: SectionIndex,
pub address: u32,
}
@ -38,7 +41,7 @@ impl Display for SectionAddress {
}
impl SectionAddress {
pub fn new(section: usize, address: u32) -> Self { Self { section, address } }
pub fn new(section: SectionIndex, address: u32) -> Self { Self { section, address } }
pub fn offset(self, offset: i32) -> Self {
Self { section: self.section, address: self.address.wrapping_add_signed(offset) }
@ -116,7 +119,7 @@ pub struct AnalyzerState {
pub functions: BTreeMap<SectionAddress, FunctionInfo>,
pub jump_tables: BTreeMap<SectionAddress, u32>,
pub known_symbols: BTreeMap<SectionAddress, Vec<ObjSymbol>>,
pub known_sections: BTreeMap<usize, String>,
pub known_sections: BTreeMap<SectionIndex, String>,
}
impl AnalyzerState {

View File

@ -18,7 +18,7 @@ struct VisitedAddresses {
impl VisitedAddresses {
pub fn new(obj: &ObjInfo) -> Self {
let mut inner = Vec::with_capacity(obj.sections.len());
let mut inner = Vec::with_capacity(obj.sections.len() as usize);
for (_, section) in obj.sections.iter() {
if section.kind == ObjSectionKind::Code {
let size = (section.size / 4) as usize;
@ -32,11 +32,13 @@ impl VisitedAddresses {
}
pub fn contains(&self, section_address: u32, address: SectionAddress) -> bool {
self.inner[address.section].contains(Self::bit_for(section_address, address.address))
self.inner[address.section as usize]
.contains(Self::bit_for(section_address, address.address))
}
pub fn insert(&mut self, section_address: u32, address: SectionAddress) {
self.inner[address.section].insert(Self::bit_for(section_address, address.address));
self.inner[address.section as usize]
.insert(Self::bit_for(section_address, address.address));
}
#[inline]

View File

@ -6,7 +6,9 @@ use ppc750cl::Ins;
use crate::{
analysis::cfa::SectionAddress,
array_ref,
obj::{ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbolKind},
obj::{
ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbolKind, SectionIndex,
},
};
pub mod cfa;
@ -36,11 +38,9 @@ fn read_unresolved_relocation_address(
address: u32,
reloc_kind: Option<ObjRelocKind>,
) -> Result<Option<RelocationTarget>> {
if let Some(reloc) = obj
.unresolved_relocations
.iter()
.find(|reloc| reloc.section as usize == section.elf_index && reloc.address == address)
{
if let Some(reloc) = obj.unresolved_relocations.iter().find(|reloc| {
reloc.section as SectionIndex == section.elf_index && reloc.address == address
}) {
if reloc.module_id != obj.module_id {
return Ok(Some(RelocationTarget::External));
}
@ -48,7 +48,7 @@ fn read_unresolved_relocation_address(
ensure!(reloc.kind == reloc_kind);
}
let (target_section_index, target_section) =
obj.sections.get_elf_index(reloc.target_section as usize).ok_or_else(|| {
obj.sections.get_elf_index(reloc.target_section as SectionIndex).ok_or_else(|| {
anyhow!(
"Failed to find target section {} for unresolved relocation",
reloc.target_section

View File

@ -1,7 +1,7 @@
use anyhow::Result;
use crate::{
obj::{ObjDataKind, ObjInfo, ObjSectionKind, ObjSymbolKind},
obj::{ObjDataKind, ObjInfo, ObjSectionKind, ObjSymbolKind, SymbolIndex},
util::split::is_linker_generated_label,
};
@ -64,7 +64,7 @@ pub fn detect_objects(obj: &mut ObjInfo) -> Result<()> {
}
pub fn detect_strings(obj: &mut ObjInfo) -> Result<()> {
let mut symbols_set = Vec::<(usize, ObjDataKind, usize)>::new();
let mut symbols_set = Vec::<(SymbolIndex, ObjDataKind, usize)>::new();
for (section_index, section) in obj
.sections
.iter()

View File

@ -7,7 +7,7 @@ use crate::{
analysis::cfa::{AnalyzerState, FunctionInfo, SectionAddress},
obj::{
ObjInfo, ObjKind, ObjRelocKind, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolFlags, ObjSymbolKind,
ObjSymbolFlags, ObjSymbolKind, SectionIndex,
},
};
@ -147,14 +147,14 @@ impl AnalysisPass for FindRelCtorsDtors {
// And the section ends with a null pointer
while let Some(reloc) = obj.unresolved_relocations.iter().find(|reloc| {
reloc.module_id == obj.module_id
&& reloc.section == section.elf_index as u8
&& reloc.section as SectionIndex == section.elf_index
&& reloc.address == current_address
&& reloc.kind == ObjRelocKind::Absolute
}) {
let Some((target_section_index, target_section)) = obj
.sections
.iter()
.find(|(_, section)| section.elf_index == reloc.target_section as usize)
let Some((target_section_index, target_section)) =
obj.sections.iter().find(|(_, section)| {
section.elf_index == reloc.target_section as SectionIndex
})
else {
return false;
};

View File

@ -19,7 +19,7 @@ use crate::{
},
obj::{
ObjDataKind, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind,
ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, SectionIndex, SymbolIndex,
},
};
@ -298,7 +298,7 @@ impl Tracker {
debug_assert_ne!(
value,
RelocationTarget::Address(SectionAddress::new(
usize::MAX,
SectionIndex::MAX,
0
))
);
@ -359,7 +359,7 @@ impl Tracker {
debug_assert_ne!(
address,
RelocationTarget::Address(SectionAddress::new(
usize::MAX,
SectionIndex::MAX,
0
))
);
@ -380,7 +380,7 @@ impl Tracker {
debug_assert_ne!(
address,
RelocationTarget::Address(SectionAddress::new(
usize::MAX,
SectionIndex::MAX,
0
))
);
@ -464,7 +464,7 @@ impl Tracker {
{
(addr, is_function_addr(addr))
} else {
(SectionAddress::new(usize::MAX, 0), false)
(SectionAddress::new(SectionIndex::MAX, 0), false)
};
if branch.link || !is_fn_addr {
self.relocations.insert(ins_addr, match ins.op {
@ -549,7 +549,7 @@ impl Tracker {
fn process_data(
&mut self,
obj: &ObjInfo,
section_index: usize,
section_index: SectionIndex,
section: &ObjSection,
) -> Result<()> {
let mut addr = SectionAddress::new(section_index, section.address as u32);
@ -602,7 +602,7 @@ impl Tracker {
} else {
// Check known relocations (function signature matching)
if self.known_relocations.contains(&from) {
return Some(SectionAddress::new(usize::MAX, addr));
return Some(SectionAddress::new(SectionIndex::MAX, addr));
}
// Check special symbols
if self.stack_address == Some(addr)
@ -613,7 +613,7 @@ impl Tracker {
|| self.sda2_base == Some(addr)
|| self.sda_base == Some(addr)
{
return Some(SectionAddress::new(usize::MAX, addr));
return Some(SectionAddress::new(SectionIndex::MAX, addr));
}
// Not valid
None
@ -625,7 +625,7 @@ impl Tracker {
obj: &mut ObjInfo,
addr: u32,
reloc_kind: ObjRelocKind,
) -> Option<usize> {
) -> Option<SymbolIndex> {
if !matches!(
reloc_kind,
ObjRelocKind::PpcAddr16Ha | ObjRelocKind::PpcAddr16Lo
@ -641,7 +641,7 @@ impl Tracker {
// return generate_special_symbol(obj, addr, &name).ok();
// }
// }
let mut check_symbol = |opt: Option<u32>, name: &str| -> Option<usize> {
let mut check_symbol = |opt: Option<u32>, name: &str| -> Option<SymbolIndex> {
if let Some(value) = opt {
if addr == value {
return generate_special_symbol(obj, value, name).ok();
@ -866,7 +866,7 @@ fn data_kind_from_op(op: Opcode) -> DataKind {
}
}
fn generate_special_symbol(obj: &mut ObjInfo, addr: u32, name: &str) -> Result<usize> {
fn generate_special_symbol(obj: &mut ObjInfo, addr: u32, name: &str) -> Result<SymbolIndex> {
obj.add_symbol(
ObjSymbol {
name: name.to_string(),

View File

@ -34,7 +34,7 @@ use crate::{
cmd::shasum::file_sha1_string,
obj::{
best_match_for_reloc, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSectionKind, ObjSymbol,
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope, SymbolIndex,
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope, SectionIndex, SymbolIndex,
},
util::{
asm::write_asm,
@ -402,7 +402,7 @@ pub fn run(args: Args) -> Result<()> {
fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
let rso = process_rso(&mut Cursor::new(buf))?;
for symbol in rso.symbols.iter() {
for (_, symbol) in rso.symbols.iter() {
let dol_section_index = match symbol.section {
Some(section) => section,
None => bail!(
@ -411,15 +411,17 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
symbol.address
),
};
let (section, address, section_kind) = if dol_section_index == DOL_SECTION_ABS as usize {
let (section, address, section_kind) = if dol_section_index
== DOL_SECTION_ABS as SectionIndex
{
(None, symbol.address as u32, None)
} else {
let dol_section_name = if dol_section_index == DOL_SECTION_ETI as usize {
let dol_section_name = if dol_section_index == DOL_SECTION_ETI as SectionIndex {
"extabindex"
} else {
DOL_SECTION_NAMES.get(dol_section_index).and_then(|&opt| opt).ok_or_else(|| {
anyhow!("Can't add symbol for unknown DOL section {}", dol_section_index)
})?
DOL_SECTION_NAMES.get(dol_section_index as usize).and_then(|&opt| opt).ok_or_else(
|| anyhow!("Can't add symbol for unknown DOL section {}", dol_section_index),
)?
};
let (dol_section_index, dol_section) = obj
.sections
@ -577,7 +579,7 @@ fn update_symbols(
if source_module_id == obj.module_id {
// Skip if already resolved
let (_, source_section) =
obj.sections.get_elf_index(rel_reloc.section as usize).ok_or_else(|| {
obj.sections.get_elf_index(rel_reloc.section as SectionIndex).ok_or_else(|| {
anyhow!(
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
rel_reloc.section,
@ -591,8 +593,10 @@ fn update_symbols(
}
}
let (target_section_index, target_section) =
obj.sections.get_elf_index(rel_reloc.target_section as usize).ok_or_else(|| {
let (target_section_index, target_section) = obj
.sections
.get_elf_index(rel_reloc.target_section as SectionIndex)
.ok_or_else(|| {
anyhow!(
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
rel_reloc.target_section,
@ -655,7 +659,7 @@ fn create_relocations(
for rel_reloc in take(&mut obj.unresolved_relocations) {
// Skip if already resolved
let (_, source_section) =
obj.sections.get_elf_index(rel_reloc.section as usize).ok_or_else(|| {
obj.sections.get_elf_index(rel_reloc.section as SectionIndex).ok_or_else(|| {
anyhow!(
"Failed to locate REL section {} in module ID {}: {:?}",
rel_reloc.section,
@ -683,7 +687,7 @@ fn create_relocations(
anyhow!("Failed to locate DOL section at {:#010X}", rel_reloc.addend)
})?
} else {
target_obj.sections.get_elf_index(rel_reloc.target_section as usize).ok_or_else(
target_obj.sections.get_elf_index(rel_reloc.target_section as SectionIndex).ok_or_else(
|| {
anyhow!(
"Failed to locate module {} section {}",
@ -720,7 +724,7 @@ fn create_relocations(
},
};
let (_, source_section) =
obj.sections.get_elf_index_mut(rel_reloc.section as usize).unwrap();
obj.sections.get_elf_index_mut(rel_reloc.section as SectionIndex).unwrap();
source_section.relocations.insert(rel_reloc.address, reloc)?;
}
@ -739,7 +743,7 @@ fn resolve_external_relocations(
module_id: u32,
symbol_index: SymbolIndex,
}
let mut reloc_to_symbol = HashMap::<RelocRef, usize>::new();
let mut reloc_to_symbol = HashMap::<RelocRef, SymbolIndex>::new();
for (_section_index, section) in obj.sections.iter_mut() {
for (_reloc_address, reloc) in section.relocations.iter_mut() {
@ -1572,7 +1576,7 @@ fn diff(args: DiffArgs) -> Result<()> {
let linked_obj = process_elf(&args.elf_file)?;
let common_bss = obj.sections.common_bss_start();
for orig_sym in obj.symbols.iter().filter(|s| {
for (_, orig_sym) in obj.symbols.iter().filter(|(_, s)| {
!matches!(s.kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section) && !s.flags.is_stripped()
}) {
let Some(orig_section_index) = orig_sym.section else { continue };
@ -1596,8 +1600,8 @@ fn diff(args: DiffArgs) -> Result<()> {
if linked_sym.size != orig_sym.size &&
// TODO validate common symbol sizes
// (need to account for inflation bug)
matches!(common_bss, Some((idx, addr)) if
orig_section_index == idx && orig_sym.address as u32 >= addr)
matches!(common_bss, Some(addr) if
orig_section_index == addr.section && orig_sym.address as u32 >= addr.address)
{
log::error!(
"Expected {} (type {:?}) to have size {:#X}, but found {:#X}",
@ -1656,7 +1660,7 @@ fn diff(args: DiffArgs) -> Result<()> {
}
// Data diff
for orig_sym in obj.symbols.iter().filter(|s| {
for (_, orig_sym) in obj.symbols.iter().filter(|(_, s)| {
s.size > 0 && !matches!(s.kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section)
}) {
let Some(orig_section_index) = orig_sym.section else { continue };
@ -1756,7 +1760,7 @@ fn apply(args: ApplyArgs) -> Result<()> {
let linked_obj = process_elf(&args.elf_file)?;
let mut replacements: Vec<(SymbolIndex, Option<ObjSymbol>)> = vec![];
for (orig_idx, orig_sym) in obj.symbols.iter().enumerate() {
for (orig_idx, orig_sym) in obj.symbols.iter() {
// skip ABS for now
if orig_sym.section.is_none() {
continue;
@ -1832,7 +1836,7 @@ fn apply(args: ApplyArgs) -> Result<()> {
}
// Add symbols from the linked object that aren't in the original
for linked_sym in linked_obj.symbols.iter() {
for (_, linked_sym) in linked_obj.symbols.iter() {
if matches!(linked_sym.kind, ObjSymbolKind::Section)
|| is_auto_symbol(linked_sym)
|| is_linker_generated_object(&linked_sym.name)

View File

@ -28,7 +28,10 @@ use crate::{
},
array_ref_mut,
cmd::dol::{find_object_base, ModuleConfig, ObjectBase, ProjectConfig},
obj::{ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol},
obj::{
ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
SectionIndex as ObjSectionIndex,
},
util::{
config::{is_auto_symbol, read_splits_sections, SectionDef},
dol::process_dol,
@ -499,7 +502,7 @@ fn merge(args: MergeArgs) -> Result<()> {
}
log::info!("Merging {} REL(s)", processed);
let mut section_map: BTreeMap<u32, BTreeMap<u32, u32>> = BTreeMap::new();
let mut section_map: BTreeMap<u32, BTreeMap<ObjSectionIndex, u32>> = BTreeMap::new();
let mut offset = align32(arena_lo + 0x2000);
for module in module_map.values() {
for (mod_section_index, mod_section) in module.sections.iter() {
@ -518,7 +521,7 @@ fn merge(args: MergeArgs) -> Result<()> {
section_known: mod_section.section_known,
splits: mod_section.splits.clone(),
});
section_map.nested_insert(module.module_id, mod_section.elf_index as u32, offset)?;
section_map.nested_insert(module.module_id, mod_section.elf_index, offset)?;
for (_, mod_symbol) in module.symbols.for_section(mod_section_index) {
obj.symbols.add_direct(ObjSymbol {
name: mod_symbol.name.clone(),
@ -542,7 +545,8 @@ fn merge(args: MergeArgs) -> Result<()> {
log::info!("Applying REL relocations");
for module in module_map.values() {
for rel_reloc in &module.unresolved_relocations {
let source_addr = (section_map[&module.module_id][&(rel_reloc.section as u32)]
let source_addr = (section_map[&module.module_id]
[&(rel_reloc.section as ObjSectionIndex)]
+ rel_reloc.address)
& !3;
let target_addr = if rel_reloc.module_id == 0 {

View File

@ -13,7 +13,9 @@ use std::{
use anyhow::{anyhow, bail, ensure, Result};
use objdiff_core::obj::split_meta::SplitMeta;
pub use relocations::{ObjReloc, ObjRelocKind, ObjRelocations};
pub use sections::{section_kind_for_section, ObjSection, ObjSectionKind, ObjSections};
pub use sections::{
section_kind_for_section, ObjSection, ObjSectionKind, ObjSections, SectionIndex,
};
pub use splits::{ObjSplit, ObjSplits};
pub use symbols::{
best_match_for_reloc, ObjDataKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
@ -132,7 +134,12 @@ impl ObjInfo {
self.symbols.add(in_symbol, replace)
}
pub fn add_split(&mut self, section_index: usize, address: u32, split: ObjSplit) -> Result<()> {
pub fn add_split(
&mut self,
section_index: SectionIndex,
address: u32,
split: ObjSplit,
) -> Result<()> {
let section = self
.sections
.get_mut(section_index)
@ -322,8 +329,8 @@ impl ObjInfo {
// Include common symbols
self.symbols
.iter()
.filter(|&symbol| symbol.flags.is_common())
.map(|s| s.size as u32),
.filter(|&(_, symbol)| symbol.flags.is_common())
.map(|(_, s)| s.size as u32),
)
.sum()
}

View File

@ -7,7 +7,10 @@ use std::{
use anyhow::{anyhow, bail, ensure, Result};
use itertools::Itertools;
use crate::obj::{ObjKind, ObjRelocations, ObjSplit, ObjSplits, ObjSymbol};
use crate::{
analysis::cfa::SectionAddress,
obj::{ObjKind, ObjRelocations, ObjSplit, ObjSplits, ObjSymbol},
};
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum ObjSectionKind {
@ -26,7 +29,7 @@ pub struct ObjSection {
pub data: Vec<u8>,
pub align: u64,
/// REL files reference the original ELF section indices
pub elf_index: usize,
pub elf_index: SectionIndex,
pub relocations: ObjRelocations,
pub virtual_address: Option<u64>,
pub file_offset: u64,
@ -40,38 +43,45 @@ pub struct ObjSections {
sections: Vec<ObjSection>,
}
pub type SectionIndex = u32;
impl ObjSections {
pub fn new(obj_kind: ObjKind, sections: Vec<ObjSection>) -> Self { Self { obj_kind, sections } }
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (usize, &ObjSection)> {
self.sections.iter().enumerate()
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection)> {
self.sections.iter().enumerate().map(|(i, s)| (i as SectionIndex, s))
}
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (usize, &mut ObjSection)> {
self.sections.iter_mut().enumerate()
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (SectionIndex, &mut ObjSection)> {
self.sections.iter_mut().enumerate().map(|(i, s)| (i as SectionIndex, s))
}
pub fn len(&self) -> usize { self.sections.len() }
pub fn len(&self) -> SectionIndex { self.sections.len() as SectionIndex }
pub fn is_empty(&self) -> bool { self.sections.is_empty() }
pub fn next_section_index(&self) -> usize { self.sections.len() }
pub fn next_section_index(&self) -> SectionIndex { self.sections.len() as SectionIndex }
pub fn get(&self, index: usize) -> Option<&ObjSection> { self.sections.get(index) }
pub fn get_mut(&mut self, index: usize) -> Option<&mut ObjSection> {
self.sections.get_mut(index)
pub fn get(&self, index: SectionIndex) -> Option<&ObjSection> {
self.sections.get(index as usize)
}
pub fn get_elf_index(&self, elf_index: usize) -> Option<(usize, &ObjSection)> {
pub fn get_mut(&mut self, index: SectionIndex) -> Option<&mut ObjSection> {
self.sections.get_mut(index as usize)
}
pub fn get_elf_index(&self, elf_index: SectionIndex) -> Option<(SectionIndex, &ObjSection)> {
self.iter().find(|&(_, s)| s.elf_index == elf_index)
}
pub fn get_elf_index_mut(&mut self, elf_index: usize) -> Option<(usize, &mut ObjSection)> {
pub fn get_elf_index_mut(
&mut self,
elf_index: SectionIndex,
) -> Option<(SectionIndex, &mut ObjSection)> {
self.iter_mut().find(|(_, s)| s.elf_index == elf_index)
}
pub fn at_address(&self, addr: u32) -> Result<(usize, &ObjSection)> {
pub fn at_address(&self, addr: u32) -> Result<(SectionIndex, &ObjSection)> {
ensure!(
self.obj_kind == ObjKind::Executable,
"Use of ObjSections::at_address in relocatable object"
@ -81,7 +91,7 @@ impl ObjSections {
.ok_or_else(|| anyhow!("Failed to locate section @ {:#010X}", addr))
}
pub fn at_address_mut(&mut self, addr: u32) -> Result<(usize, &mut ObjSection)> {
pub fn at_address_mut(&mut self, addr: u32) -> Result<(SectionIndex, &mut ObjSection)> {
ensure!(
self.obj_kind == ObjKind::Executable,
"Use of ObjSections::at_address_mut in relocatable object"
@ -91,7 +101,7 @@ impl ObjSections {
.ok_or_else(|| anyhow!("Failed to locate section @ {:#010X}", addr))
}
pub fn with_range(&self, range: Range<u32>) -> Result<(usize, &ObjSection)> {
pub fn with_range(&self, range: Range<u32>) -> Result<(SectionIndex, &ObjSection)> {
ensure!(
self.obj_kind == ObjKind::Executable,
"Use of ObjSections::with_range in relocatable object"
@ -104,46 +114,52 @@ impl ObjSections {
pub fn by_kind(
&self,
kind: ObjSectionKind,
) -> impl DoubleEndedIterator<Item = (usize, &ObjSection)> {
) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection)> {
self.iter().filter(move |(_, s)| s.kind == kind)
}
pub fn by_name(&self, name: &str) -> Result<Option<(usize, &ObjSection)>> {
pub fn by_name(&self, name: &str) -> Result<Option<(SectionIndex, &ObjSection)>> {
self.iter()
.filter(move |(_, s)| s.name == name)
.at_most_one()
.map_err(|_| anyhow!("Multiple sections with name {}", name))
}
pub fn push(&mut self, section: ObjSection) -> usize {
pub fn push(&mut self, section: ObjSection) -> SectionIndex {
let index = self.sections.len();
self.sections.push(section);
index
index as SectionIndex
}
pub fn all_splits(
&self,
) -> impl DoubleEndedIterator<Item = (usize, &ObjSection, u32, &ObjSplit)> {
) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection, u32, &ObjSplit)> {
self.iter()
.flat_map(|(idx, s)| s.splits.iter().map(move |(addr, split)| (idx, s, addr, split)))
}
pub fn common_bss_start(&self) -> Option<(usize, u32)> {
pub fn common_bss_start(&self) -> Option<SectionAddress> {
let Ok(Some((section_index, section))) = self.by_name(".bss") else {
return None;
};
section.splits.iter().find(|(_, split)| split.common).map(|(addr, _)| (section_index, addr))
section
.splits
.iter()
.find(|(_, split)| split.common)
.map(|(addr, _)| SectionAddress::new(section_index, addr))
}
}
impl Index<usize> for ObjSections {
impl Index<SectionIndex> for ObjSections {
type Output = ObjSection;
fn index(&self, index: usize) -> &Self::Output { &self.sections[index] }
fn index(&self, index: SectionIndex) -> &Self::Output { &self.sections[index as usize] }
}
impl IndexMut<usize> for ObjSections {
fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.sections[index] }
impl IndexMut<SectionIndex> for ObjSections {
fn index_mut(&mut self, index: SectionIndex) -> &mut Self::Output {
&mut self.sections[index as usize]
}
}
impl ObjSection {

View File

@ -4,7 +4,7 @@ use anyhow::{anyhow, Result};
use itertools::Itertools;
use crate::{
obj::{ObjInfo, ObjSection},
obj::{ObjInfo, ObjSection, SectionIndex},
util::{nested::NestedVec, split::default_section_align},
};
@ -28,7 +28,7 @@ impl ObjSplit {
pub fn alignment(
&self,
obj: &ObjInfo,
section_index: usize,
section_index: SectionIndex,
section: &ObjSection,
split_addr: u32,
) -> u32 {

View File

@ -12,7 +12,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
use crate::{
analysis::cfa::SectionAddress,
obj::{ObjKind, ObjRelocKind, ObjSections},
obj::{sections::SectionIndex, ObjKind, ObjRelocKind, ObjSections},
util::{
config::{is_auto_jump_table, is_auto_label, is_auto_symbol, parse_u32},
nested::NestedVec,
@ -187,7 +187,7 @@ pub struct ObjSymbol {
pub name: String,
pub demangled_name: Option<String>,
pub address: u64,
pub section: Option<usize>,
pub section: Option<SectionIndex>,
pub size: u64,
pub size_known: bool,
pub flags: ObjSymbolFlagSet,
@ -199,7 +199,7 @@ pub struct ObjSymbol {
pub demangled_name_hash: Option<u32>,
}
pub type SymbolIndex = usize;
pub type SymbolIndex = u32;
#[derive(Debug, Clone)]
pub struct ObjSymbols {
@ -216,8 +216,10 @@ impl ObjSymbols {
let mut symbols_by_section: Vec<BTreeMap<u32, Vec<SymbolIndex>>> = vec![];
let mut symbols_by_name = HashMap::<String, Vec<SymbolIndex>>::new();
for (idx, symbol) in symbols.iter().enumerate() {
let idx = idx as SymbolIndex;
symbols_by_address.nested_push(symbol.address as u32, idx);
if let Some(section_idx) = symbol.section {
let section_idx = section_idx as usize;
if section_idx >= symbols_by_section.len() {
symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
}
@ -312,7 +314,7 @@ impl ObjSymbols {
}
symbol_idx
} else {
let target_symbol_idx = self.symbols.len();
let target_symbol_idx = self.symbols.len() as SymbolIndex;
self.add_direct(ObjSymbol {
name: in_symbol.name,
demangled_name: in_symbol.demangled_name,
@ -333,9 +335,10 @@ impl ObjSymbols {
}
pub fn add_direct(&mut self, in_symbol: ObjSymbol) -> Result<SymbolIndex> {
let symbol_idx = self.symbols.len();
let symbol_idx = self.symbols.len() as SymbolIndex;
self.symbols_by_address.nested_push(in_symbol.address as u32, symbol_idx);
if let Some(section_idx) = in_symbol.section {
let section_idx = section_idx as usize;
if section_idx >= self.symbols_by_section.len() {
self.symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
}
@ -355,28 +358,30 @@ impl ObjSymbols {
Ok(symbol_idx)
}
pub fn iter(&self) -> impl DoubleEndedIterator<Item = &ObjSymbol> { self.symbols.iter() }
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
self.symbols.iter().enumerate().map(|(i, s)| (i as SymbolIndex, s))
}
pub fn count(&self) -> usize { self.symbols.len() }
pub fn count(&self) -> SymbolIndex { self.symbols.len() as SymbolIndex }
pub fn at_section_address(
&self,
section_idx: usize,
section_idx: SectionIndex,
addr: u32,
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
self.symbols_by_section
.get(section_idx)
.get(section_idx as usize)
.and_then(|v| v.get(&addr))
.into_iter()
.flatten()
.map(move |&idx| (idx, &self.symbols[idx]))
.map(move |&idx| (idx, &self.symbols[idx as usize]))
// "Stripped" symbols don't actually exist at the address
.filter(|(_, sym)| !sym.flags.is_stripped())
}
pub fn kind_at_section_address(
&self,
section_idx: usize,
section_idx: SectionIndex,
addr: u32,
kind: ObjSymbolKind,
) -> Result<Option<(SymbolIndex, &ObjSymbol)>> {
@ -397,7 +402,7 @@ impl ObjSymbols {
self.symbols_by_section
.iter()
.flat_map(|v| v.iter().map(|(_, v)| v))
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u])))
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u as usize])))
}
// Iterate over all ABS symbols
@ -405,24 +410,24 @@ impl ObjSymbols {
debug_assert!(self.obj_kind == ObjKind::Executable);
self.symbols_by_address
.iter()
.flat_map(|(_, v)| v.iter().map(|&u| (u, &self.symbols[u])))
.flat_map(|(_, v)| v.iter().map(|&u| (u, &self.symbols[u as usize])))
.filter(|(_, s)| s.section.is_none())
}
// Iterate over range in address ascending order, excluding ABS symbols
pub fn for_section_range<R>(
&self,
section_index: usize,
section_index: SectionIndex,
range: R,
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)>
where
R: RangeBounds<u32> + Clone,
{
self.symbols_by_section
.get(section_index)
.get(section_index as usize)
.into_iter()
.flat_map(move |v| v.range(range.clone()))
.flat_map(move |(_, v)| v.iter().map(move |u| (*u, &self.symbols[*u])))
.flat_map(move |(_, v)| v.iter().map(move |u| (*u, &self.symbols[*u as usize])))
}
pub fn indexes_for_range<R>(
@ -438,13 +443,13 @@ impl ObjSymbols {
pub fn for_section(
&self,
section_idx: usize,
section_idx: SectionIndex,
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
self.symbols_by_section
.get(section_idx)
.get(section_idx as usize)
.into_iter()
.flat_map(|v| v.iter().map(|(_, v)| v))
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u])))
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u as usize])))
}
pub fn for_name(
@ -454,7 +459,7 @@ impl ObjSymbols {
self.symbols_by_name
.get(name)
.into_iter()
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u])))
.flat_map(move |v| v.iter().map(move |u| (*u, &self.symbols[*u as usize])))
}
pub fn by_name(&self, name: &str) -> Result<Option<(SymbolIndex, &ObjSymbol)>> {
@ -515,11 +520,11 @@ impl ObjSymbols {
&self,
kind: ObjSymbolKind,
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
self.symbols.iter().enumerate().filter(move |(_, sym)| sym.kind == kind)
self.iter().filter(move |(_, sym)| sym.kind == kind)
}
pub fn replace(&mut self, index: SymbolIndex, symbol: ObjSymbol) -> Result<()> {
let symbol_ref = &mut self.symbols[index];
let symbol_ref = &mut self.symbols[index as usize];
ensure!(symbol_ref.address == symbol.address, "Can't modify address with replace_symbol");
ensure!(symbol_ref.section == symbol.section, "Can't modify section with replace_symbol");
if symbol_ref.name != symbol.name {
@ -545,7 +550,7 @@ impl ObjSymbols {
for (_addr, symbol_idxs) in self.indexes_for_range(..=target_addr.address).rev() {
let symbols = symbol_idxs
.iter()
.map(|&idx| (idx, &self.symbols[idx]))
.map(|&idx| (idx, &self.symbols[idx as usize]))
.filter(|(_, sym)| {
(sym.section.is_none() || sym.section == Some(target_addr.section))
&& sym.referenced_by(reloc_kind)
@ -570,14 +575,14 @@ impl ObjSymbols {
#[inline]
pub fn flags(&mut self, idx: SymbolIndex) -> &mut ObjSymbolFlagSet {
&mut self.symbols[idx].flags
&mut self.symbols[idx as usize].flags
}
}
impl Index<SymbolIndex> for ObjSymbols {
type Output = ObjSymbol;
fn index(&self, index: usize) -> &Self::Output { &self.symbols[index] }
fn index(&self, index: SymbolIndex) -> &Self::Output { &self.symbols[index as usize] }
}
impl ObjSymbol {

View File

@ -7,7 +7,7 @@ use anyhow::Result;
use io::{Error, ErrorKind};
use crate::{
obj::{ObjSymbol, ObjSymbolKind},
obj::{ObjSymbol, ObjSymbolKind, SectionIndex},
util::{
dol::{DolLike, DolSection, DolSectionKind},
reader::{
@ -55,7 +55,7 @@ impl FromReader for AlfFile {
data_size: section.data_size,
size: section.size,
kind,
index: sections.len(),
index: sections.len() as SectionIndex,
});
}
for sym in &symtab.symbols {
@ -230,7 +230,7 @@ impl AlfSymbol {
name,
demangled_name,
address: self.address as u64,
section: Some(self.section as usize - 1),
section: Some(self.section as SectionIndex - 1),
size: self.size as u64,
size_known: true,
flags: Default::default(),

View File

@ -11,7 +11,7 @@ use ppc750cl::{Argument, Ins, InsIter, Opcode};
use crate::{
obj::{
ObjDataKind, ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
ObjSymbolKind,
ObjSymbolKind, SymbolIndex,
},
util::nested::NestedVec,
};
@ -25,7 +25,7 @@ enum SymbolEntryKind {
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
struct SymbolEntry {
index: usize,
index: SymbolIndex,
kind: SymbolEntryKind,
}
@ -44,7 +44,7 @@ where W: Write + ?Sized {
}
// We'll append generated symbols to the end
let mut symbols: Vec<ObjSymbol> = obj.symbols.iter().cloned().collect();
let mut symbols: Vec<ObjSymbol> = obj.symbols.iter().map(|(_, s)| s.clone()).collect();
let mut section_entries: Vec<BTreeMap<u32, Vec<SymbolEntry>>> = vec![];
let mut section_relocations: Vec<BTreeMap<u32, ObjReloc>> = vec![];
for (section_idx, section) in obj.sections.iter() {
@ -90,7 +90,7 @@ where W: Write + ?Sized {
.map(|e| e.index);
if target_symbol_idx.is_none() {
let display_address = address as u64 + section.virtual_address.unwrap_or(0);
let symbol_idx = symbols.len();
let symbol_idx = symbols.len() as SymbolIndex;
symbols.push(ObjSymbol {
name: format!(".L_{display_address:08X}"),
address: display_address,
@ -131,7 +131,7 @@ where W: Write + ?Sized {
if reloc.addend == 0 {
continue;
}
let target = &symbols[reloc.target_symbol];
let target = &symbols[reloc.target_symbol as usize];
let target_section_idx = match target.section {
Some(v) => v,
None => continue,
@ -140,7 +140,7 @@ where W: Write + ?Sized {
anyhow!("Invalid relocation target section: {:#010X} {:?}", reloc_address, target)
})?;
let address = (target.address as i64 + reloc.addend) as u64;
let vec = match section_entries[target_section_idx].entry(address as u32) {
let vec = match section_entries[target_section_idx as usize].entry(address as u32) {
btree_map::Entry::Occupied(e) => e.into_mut(),
btree_map::Entry::Vacant(e) => e.insert(vec![]),
};
@ -149,7 +149,7 @@ where W: Write + ?Sized {
.any(|e| e.kind == SymbolEntryKind::Label || e.kind == SymbolEntryKind::Start)
{
let display_address = address + target_section.virtual_address.unwrap_or(0);
let symbol_idx = symbols.len();
let symbol_idx = symbols.len() as SymbolIndex;
symbols.push(ObjSymbol {
name: format!(".L_{display_address:08X}"),
address: display_address,
@ -181,13 +181,17 @@ where W: Write + ?Sized {
}
for (section_index, section) in obj.sections.iter() {
let entries = &section_entries[section_index];
let relocations = &section_relocations[section_index];
let entries = &section_entries[section_index as usize];
let relocations = &section_relocations[section_index as usize];
let mut current_address = section.address as u32;
let section_end = (section.address + section.size) as u32;
let subsection =
obj.sections.iter().take(section_index).filter(|(_, s)| s.name == section.name).count();
let subsection = obj
.sections
.iter()
.take(section_index as usize)
.filter(|(_, s)| s.name == section.name)
.count();
loop {
if current_address >= section_end {
@ -369,7 +373,7 @@ fn write_symbol_entry<W>(
where
W: Write + ?Sized,
{
let symbol = &symbols[entry.index];
let symbol = &symbols[entry.index as usize];
// Skip writing certain symbols
if symbol.kind == ObjSymbolKind::Section {
@ -452,13 +456,13 @@ where
}
fn parse_extab(symbols: &[ObjSymbol], entry: &SymbolEntry, section: &ObjSection) -> Result<String> {
let symbol = &symbols[entry.index];
let symbol = &symbols[entry.index as usize];
let data = section.symbol_data(symbol)?;
let decoded = cwextab::decode_extab(data)?;
let function_names = section
.relocations
.range(symbol.address as u32..(symbol.address + symbol.size) as u32)
.map(|(_, reloc)| symbols[reloc.target_symbol].name.clone())
.map(|(_, reloc)| symbols[reloc.target_symbol as usize].name.clone())
.collect_vec();
decoded.to_string(function_names).ok_or_else(|| anyhow!("Failed to print extab entry"))
}
@ -504,7 +508,7 @@ where
.with_context(|| format!("At address {:#010X}", sym_addr))?;
entry = entry_iter.next();
} else if current_address > sym_addr {
let dbg_symbols = vec.iter().map(|e| &symbols[e.index]).collect_vec();
let dbg_symbols = vec.iter().map(|e| &symbols[e.index as usize]).collect_vec();
bail!(
"Unaligned symbol entry @ {:#010X}:\n\t{:?}",
section.virtual_address.unwrap_or(0) as u32 + sym_addr,
@ -585,7 +589,7 @@ fn find_symbol_kind(
for entry in entries {
match entry.kind {
SymbolEntryKind::Start => {
let new_kind = symbols[entry.index].kind;
let new_kind = symbols[entry.index as usize].kind;
if !matches!(new_kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section) {
ensure!(
!found || new_kind == kind,
@ -611,11 +615,11 @@ fn find_data_kind(
for entry in entries {
match entry.kind {
SymbolEntryKind::Start => {
let new_kind = symbols[entry.index].data_kind;
let new_kind = symbols[entry.index as usize].data_kind;
if !matches!(new_kind, ObjDataKind::Unknown) {
if found && new_kind != kind {
for entry in entries {
log::error!("Symbol {:?}", symbols[entry.index]);
log::error!("Symbol {:?}", symbols[entry.index as usize]);
}
bail!(
"Conflicting data kinds found: {kind:?} and {new_kind:?}",
@ -806,14 +810,14 @@ where
ObjRelocKind::Absolute => {
// Attempt to use .rel macro for relative relocations
if reloc.addend != 0 {
let target = &symbols[reloc.target_symbol];
let target = &symbols[reloc.target_symbol as usize];
let target_addr = (target.address as i64 + reloc.addend) as u32;
if let Some(entry) = target
.section
.and_then(|section_idx| section_entries[section_idx].get(&target_addr))
.and_then(|section_idx| section_entries[section_idx as usize].get(&target_addr))
.and_then(|entries| entries.iter().find(|e| e.kind == SymbolEntryKind::Label))
{
let symbol = &symbols[entry.index];
let symbol = &symbols[entry.index as usize];
write!(w, "\t.rel ")?;
write_symbol_name(w, &target.name)?;
write!(w, ", ")?;
@ -959,7 +963,7 @@ fn write_reloc_symbol<W>(
where
W: Write + ?Sized,
{
write_symbol_name(w, &symbols[reloc.target_symbol].name)?;
write_symbol_name(w, &symbols[reloc.target_symbol as usize].name)?;
match reloc.addend.cmp(&0i64) {
Ordering::Greater => write!(w, "+{:#X}", reloc.addend),
Ordering::Less => write!(w, "-{:#X}", -reloc.addend),

View File

@ -18,7 +18,7 @@ use crate::{
analysis::cfa::SectionAddress,
obj::{
ObjDataKind, ObjInfo, ObjKind, ObjSectionKind, ObjSplit, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolFlags, ObjSymbolKind, ObjUnit,
ObjSymbolFlags, ObjSymbolKind, ObjUnit, SectionIndex,
},
util::{
file::{buf_writer, FileReadInfo},
@ -621,7 +621,7 @@ fn parse_section_line(captures: Captures, state: &SplitState) -> Result<SplitLin
enum SplitState {
None,
Sections(usize),
Sections(SectionIndex),
Unit(String),
}

View File

@ -40,7 +40,7 @@ pub fn process_code(
arch.process_code(
symbol.address,
orig_data,
section.elf_index,
section.elf_index as usize,
&orig_relocs,
&Default::default(),
config,

View File

@ -11,7 +11,7 @@ use crate::{
array_ref,
obj::{
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolFlags, ObjSymbolKind,
ObjSymbolFlags, ObjSymbolKind, SectionIndex,
},
util::{
alf::{AlfFile, AlfSymbol, ALF_MAGIC},
@ -75,7 +75,7 @@ pub struct DolSection {
pub size: u32,
pub kind: DolSectionKind,
// TODO remove
pub index: usize,
pub index: SectionIndex,
}
#[derive(Debug, Clone)]
@ -103,7 +103,7 @@ impl FromReader for DolFile {
data_size: size,
size,
kind: DolSectionKind::Text,
index: sections.len(),
index: sections.len() as SectionIndex,
});
}
for (idx, &size) in header.data_sizes.iter().enumerate() {
@ -116,7 +116,7 @@ impl FromReader for DolFile {
data_size: size,
size,
kind: DolSectionKind::Data,
index: sections.len(),
index: sections.len() as SectionIndex,
});
}
sections.push(DolSection {
@ -125,7 +125,7 @@ impl FromReader for DolFile {
data_size: 0,
size: header.bss_size,
kind: DolSectionKind::Bss,
index: sections.len(),
index: sections.len() as SectionIndex,
});
Ok(Self { header, sections })
}
@ -286,8 +286,8 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
dol.sections().iter().filter(|section| section.kind == DolSectionKind::Text).count();
let mut eti_entries: Vec<EtiEntry> = Vec::new();
let mut eti_init_info_range: Option<(u32, u32)> = None;
let mut extab_section: Option<usize> = None;
let mut extabindex_section: Option<usize> = None;
let mut extab_section: Option<SectionIndex> = None;
let mut extabindex_section: Option<SectionIndex> = None;
'outer: for dol_section in
dol.sections().iter().filter(|section| section.kind == DolSectionKind::Data)
{
@ -537,8 +537,9 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
}
// Apply section indices
let mut init_section_index = None;
let mut init_section_index: Option<SectionIndex> = None;
for (idx, section) in sections.iter_mut().enumerate() {
let idx = idx as SectionIndex;
match section.name.as_str() {
".init" => {
init_section_index = Some(idx);

View File

@ -26,6 +26,7 @@ use crate::{
obj::{
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind,
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjUnit,
SectionIndex as ObjSectionIndex, SymbolIndex as ObjSymbolIndex,
},
util::{
comment::{CommentSym, MWComment},
@ -97,7 +98,7 @@ where P: AsRef<Path> {
size: section.size(),
data: section.uncompressed_data()?.to_vec(),
align: section.align(),
elf_index: section.index().0,
elf_index: section.index().0 as ObjSectionIndex,
relocations: Default::default(),
virtual_address: None, // Loaded from section symbol
file_offset: section.file_range().map(|(v, _)| v).unwrap_or_default(),
@ -151,7 +152,7 @@ where P: AsRef<Path> {
};
let mut symbols: Vec<ObjSymbol> = vec![];
let mut symbol_indexes: Vec<Option<usize>> = vec![None /* ELF null symbol */];
let mut symbol_indexes: Vec<Option<ObjSymbolIndex>> = vec![None /* ELF null symbol */];
let mut section_starts = IndexMap::<String, Vec<(u64, String)>>::new();
let mut name_to_index = HashMap::<String, usize>::new(); // for resolving duplicate names
let mut boundary_state = BoundaryState::LookForFile(Default::default());
@ -307,7 +308,7 @@ where P: AsRef<Path> {
symbol_indexes.push(None);
continue;
}
symbol_indexes.push(Some(symbols.len()));
symbol_indexes.push(Some(symbols.len() as ObjSymbolIndex));
let align = mw_comment.as_ref().map(|(_, vec)| vec[symbol.index().0].align);
symbols.push(to_obj_symbol(&obj_file, &symbol, &section_indexes, align)?);
}
@ -401,7 +402,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
}
writer.reserve_null_section_index();
let mut out_sections: Vec<OutSection> = Vec::with_capacity(obj.sections.len());
let mut out_sections: Vec<OutSection> = Vec::with_capacity(obj.sections.len() as usize);
for (_, section) in obj.sections.iter() {
let name = writer.add_section_name(section.name.as_bytes());
let index = writer.reserve_section_index();
@ -416,7 +417,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
});
}
let mut rela_names: Vec<String> = vec![Default::default(); obj.sections.len()];
let mut rela_names: Vec<String> = vec![Default::default(); obj.sections.len() as usize];
for (((_, section), out_section), rela_name) in
obj.sections.iter().zip(&mut out_sections).zip(&mut rela_names)
{
@ -449,7 +450,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
});
// Generate .comment data
let mut comment_data = Vec::<u8>::with_capacity(0x2C + obj.symbols.count() * 8);
let mut comment_data = Vec::<u8>::with_capacity(0x2C + obj.symbols.count() as usize * 8);
mw_comment.to_writer_static(&mut comment_data, Endian::Big)?;
// Null symbol
CommentSym { align: 0, vis_flags: 0, active_flags: 0 }
@ -485,8 +486,8 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
None
};
let mut out_symbols: Vec<OutSymbol> = Vec::with_capacity(obj.symbols.count());
let mut symbol_map = vec![None; obj.symbols.count()];
let mut out_symbols: Vec<OutSymbol> = Vec::with_capacity(obj.symbols.count() as usize);
let mut symbol_map = vec![None; obj.symbols.count() as usize];
let mut section_symbol_offset = 0;
let mut num_local = 0;
@ -532,7 +533,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
// Add section symbols for relocatable objects
if obj.kind == ObjKind::Relocatable {
for (section_index, section) in obj.sections.iter() {
let out_section_index = out_sections.get(section_index).map(|s| s.index);
let out_section_index = out_sections.get(section_index as usize).map(|s| s.index);
let index = writer.reserve_symbol_index(out_section_index);
let sym = object::write::elf::Sym {
name: None,
@ -561,19 +562,19 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
for (symbol_index, symbol) in obj
.symbols
.iter()
.enumerate()
.filter(|&(_, s)| s.flags.is_local())
.chain(obj.symbols.iter().enumerate().filter(|&(_, s)| !s.flags.is_local()))
.chain(obj.symbols.iter().filter(|&(_, s)| !s.flags.is_local()))
{
if obj.kind == ObjKind::Relocatable && symbol.kind == ObjSymbolKind::Section {
// We wrote section symbols above, so skip them here
let section_index =
symbol.section.ok_or_else(|| anyhow!("section symbol without section index"))?;
symbol_map[symbol_index] = Some(section_symbol_offset + section_index as u32);
symbol_map[symbol_index as usize] =
Some(section_symbol_offset as ObjSectionIndex + section_index);
continue;
}
let section = symbol.section.and_then(|idx| out_sections.get(idx));
let section = symbol.section.and_then(|idx| out_sections.get(idx as usize));
let section_index = section.map(|s| s.index);
let index = writer.reserve_symbol_index(section_index);
let name_index = if symbol.name.is_empty() {
@ -617,7 +618,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
num_local = writer.symbol_count();
}
out_symbols.push(OutSymbol { index, sym });
symbol_map[symbol_index] = Some(index.0);
symbol_map[symbol_index as usize] = Some(index.0);
if let Some((comment_data, _)) = &mut comment_data {
CommentSym::from(symbol, export_all).to_writer_static(comment_data, Endian::Big)?;
}
@ -635,7 +636,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
writer.reserve_file_header();
if obj.kind == ObjKind::Executable {
writer.reserve_program_headers(obj.sections.len() as u32);
writer.reserve_program_headers(obj.sections.len());
}
for ((_, section), out_section) in obj.sections.iter().zip(&mut out_sections) {
@ -734,7 +735,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
ensure!(writer.len() == out_section.rela_offset);
for (addr, reloc) in section.relocations.iter() {
let (r_offset, r_type) = reloc.to_elf(addr);
let r_sym = symbol_map[reloc.target_symbol]
let r_sym = symbol_map[reloc.target_symbol as usize]
.ok_or_else(|| anyhow!("Relocation against stripped symbol"))?;
writer.write_relocation(true, &Rel { r_offset, r_sym, r_type, r_addend: reloc.addend });
}
@ -893,7 +894,7 @@ fn to_obj_symbol(
name: name.to_string(),
demangled_name: demangle(name, &Default::default()),
address: symbol.address(),
section: section_idx,
section: section_idx.map(|s| s as ObjSectionIndex),
size: symbol.size(),
size_known: true,
flags,
@ -927,7 +928,7 @@ pub fn to_obj_reloc_kind(flags: RelocationFlags) -> Result<ObjRelocKind> {
fn to_obj_reloc(
obj_file: &object::File<'_>,
symbol_indexes: &[Option<usize>],
symbol_indexes: &[Option<ObjSymbolIndex>],
section_data: &[u8],
address: u64,
reloc: Relocation,

View File

@ -37,7 +37,7 @@ pub fn generate_ldscript(
}
let mut force_active = force_active.to_vec();
for symbol in obj.symbols.iter() {
for (_, symbol) in obj.symbols.iter() {
if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
force_active.push(symbol.name.clone());
}
@ -86,7 +86,7 @@ pub fn generate_ldscript_partial(
}
let mut force_active = force_active.to_vec();
for symbol in obj.symbols.iter() {
for (_, symbol) in obj.symbols.iter() {
if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
force_active.push(symbol.name.clone());
}

View File

@ -21,7 +21,7 @@ use crate::{
obj::{
section_kind_for_section, ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind,
ObjSections, ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
ObjSymbols, ObjUnit,
ObjSymbols, ObjUnit, SectionIndex,
},
util::nested::NestedVec,
vfs::open_file,
@ -770,7 +770,7 @@ pub fn apply_map(mut result: MapInfo, obj: &mut ObjInfo) -> Result<()> {
&& (s.address + s.size) <= (section.address + section.size) as u32
})
} else {
result.sections.iter().filter(|s| s.size > 0).nth(section_index)
result.sections.iter().filter(|s| s.size > 0).nth(section_index as usize)
};
if let Some(info) = opt {
if section.section_known && section.name != info.name {
@ -814,7 +814,7 @@ pub fn apply_map(mut result: MapInfo, obj: &mut ObjInfo) -> Result<()> {
".data"
}
} else if let Some(section_name) =
DEFAULT_REL_SECTIONS.get(section.elf_index)
DEFAULT_REL_SECTIONS.get(section.elf_index as usize)
{
section_name
} else {
@ -1014,7 +1014,7 @@ pub fn create_obj(result: &MapInfo) -> Result<ObjInfo> {
fn add_symbol(
obj: &mut ObjInfo,
symbol_entry: &SymbolEntry,
section: Option<usize>,
section: Option<SectionIndex>,
ignore_alignment: bool,
) -> Result<()> {
let demangled_name = demangle(&symbol_entry.name, &DemangleOptions::default());

View File

@ -13,7 +13,7 @@ use crate::{
array_ref_mut,
obj::{
ObjArchitecture, ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, SectionIndex,
},
util::{
align_up,
@ -418,7 +418,7 @@ where R: Read + Seek + ?Sized {
_ => None, // determined later
}
.unwrap_or_default() as u64,
elf_index: idx,
elf_index: idx as SectionIndex,
relocations: Default::default(),
virtual_address: None, // TODO option to set?
file_offset: offset as u64,
@ -440,7 +440,7 @@ where R: Read + Seek + ?Sized {
let (section_index, _) = sections
.iter()
.enumerate()
.find(|&(_, section)| section.elf_index == rel_section_idx as usize)
.find(|&(_, section)| section.elf_index == rel_section_idx as SectionIndex)
.ok_or_else(|| anyhow!("Failed to locate {name} section {rel_section_idx}"))?;
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
let mut flags = ObjSymbolFlagSet(ObjSymbolFlags::Global.into());
@ -450,7 +450,7 @@ where R: Read + Seek + ?Sized {
symbols.push(ObjSymbol {
name: name.to_string(),
address: offset as u64,
section: Some(section_index),
section: Some(section_index as SectionIndex),
flags,
kind: ObjSymbolKind::Function,
..Default::default()

View File

@ -9,7 +9,7 @@ use cwdemangle::{demangle, DemangleOptions};
use crate::{
obj::{
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolFlags, ObjSymbolKind,
ObjSymbolFlags, ObjSymbolKind, SectionIndex,
},
util::{
file::{read_c_string, read_string},
@ -452,7 +452,7 @@ where R: Read + Seek + ?Sized {
size: size as u64,
data,
align: 0,
elf_index: idx as usize,
elf_index: idx as SectionIndex,
relocations: Default::default(),
virtual_address: None, // TODO option to set?
file_offset: offset as u64,
@ -476,13 +476,13 @@ where R: Read + Seek + ?Sized {
let (section_index, _) = sections
.iter()
.enumerate()
.find(|&(_, section)| section.elf_index == rel_section_idx as usize)
.find(|&(_, section)| section.elf_index == rel_section_idx as SectionIndex)
.ok_or_else(|| anyhow!("Failed to locate {name} section {rel_section_idx}"))?;
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
symbols.push(ObjSymbol {
name: name.to_string(),
address: offset as u64,
section: Some(section_index),
section: Some(section_index as SectionIndex),
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
kind: ObjSymbolKind::Function,
..Default::default()
@ -526,7 +526,7 @@ where R: Read + Seek + ?Sized {
let section = sections
.iter()
.enumerate()
.find(|&(_, section)| section.elf_index == symbol.section_index as usize)
.find(|&(_, section)| section.elf_index == symbol.section_index as SectionIndex)
.map(|(idx, _)| idx)
// HACK: selfiles won't have any sections
.unwrap_or(symbol.section_index as usize);
@ -541,7 +541,7 @@ where R: Read + Seek + ?Sized {
name,
demangled_name,
address: symbol.offset as u64,
section: Some(section),
section: Some(section as SectionIndex),
..Default::default()
});
}

View File

@ -18,7 +18,7 @@ use crate::{
array_ref,
obj::{
ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSymbol, ObjSymbolFlagSet,
ObjSymbolKind,
ObjSymbolKind, SectionIndex, SymbolIndex,
},
util::elf::process_elf,
};
@ -36,13 +36,13 @@ pub struct OutSymbol {
pub struct OutReloc {
pub offset: u32,
pub kind: ObjRelocKind,
pub symbol: usize,
pub symbol: u32,
pub addend: i32,
}
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
pub struct FunctionSignature {
pub symbol: usize,
pub symbol: u32,
pub hash: String,
pub signature: String,
pub symbols: Vec<OutSymbol>,
@ -92,12 +92,12 @@ pub fn check_signatures(
let mut name = None;
for signature in signatures {
if name.is_none() {
name = Some(signature.symbols[signature.symbol].name.clone());
name = Some(signature.symbols[signature.symbol as usize].name.clone());
}
if check_signature(data, signature)? {
log::debug!(
"Found {} @ {:#010X} (hash {})",
signature.symbols[signature.symbol].name,
signature.symbols[signature.symbol as usize].name,
addr,
signature.hash
);
@ -114,9 +114,9 @@ pub fn apply_symbol(
obj: &mut ObjInfo,
target: SectionAddress,
sig_symbol: &OutSymbol,
) -> Result<usize> {
) -> Result<SymbolIndex> {
let mut target_section_index =
if target.section == usize::MAX { None } else { Some(target.section) };
if target.section == SectionIndex::MAX { None } else { Some(target.section) };
if let Some(target_section_index) = target_section_index {
let target_section = &mut obj.sections[target_section_index];
if !target_section.section_known {
@ -154,7 +154,7 @@ pub fn apply_signature(
addr: SectionAddress,
signature: &FunctionSignature,
) -> Result<()> {
let in_symbol = &signature.symbols[signature.symbol];
let in_symbol = &signature.symbols[signature.symbol as usize];
let symbol_idx = apply_symbol(obj, addr, in_symbol)?;
let mut tracker = Tracker::new(obj);
for reloc in &signature.relocations {
@ -185,7 +185,7 @@ pub fn apply_signature(
}
_ => bail!("Relocation mismatch: {:?} != {:?}", reloc, sig_reloc.kind),
};
let sig_symbol = &signature.symbols[sig_reloc.symbol];
let sig_symbol = &signature.symbols[sig_reloc.symbol as usize];
// log::info!("Processing relocation {:#010X} {:?} -> {:#010X} {:?}", reloc_addr, reloc, target, sig_symbol);
let target_symbol_idx = apply_symbol(obj, target, sig_symbol)?;
let obj_reloc = ObjReloc {
@ -200,7 +200,7 @@ pub fn apply_signature(
for reloc in &signature.relocations {
let addr = addr + reloc.offset;
if !tracker.relocations.contains_key(&addr) {
let sig_symbol = &signature.symbols[reloc.symbol];
let sig_symbol = &signature.symbols[reloc.symbol as usize];
bail!("Missing relocation @ {:#010X}: {:?} -> {:?}", addr, reloc, sig_symbol);
}
}
@ -250,7 +250,7 @@ pub fn generate_signature<P>(path: P, symbol_name: &str) -> Result<Option<Functi
where P: AsRef<Path> {
let mut out_symbols: Vec<OutSymbol> = Vec::new();
let mut out_relocs: Vec<OutReloc> = Vec::new();
let mut symbol_map: BTreeMap<usize, usize> = BTreeMap::new();
let mut symbol_map: BTreeMap<SymbolIndex, u32> = BTreeMap::new();
let mut obj = process_elf(path)?;
if obj.kind == ObjKind::Executable
@ -312,7 +312,7 @@ where P: AsRef<Path> {
let symbol_idx = match symbol_map.entry(reloc.target_symbol) {
btree_map::Entry::Vacant(e) => {
let target = &obj.symbols[reloc.target_symbol];
let symbol_idx = out_symbols.len();
let symbol_idx = out_symbols.len() as u32;
e.insert(symbol_idx);
out_symbols.push(OutSymbol {
kind: target.kind,

View File

@ -15,7 +15,7 @@ use crate::{
obj::{
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocations, ObjSection, ObjSectionKind,
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope,
ObjUnit,
ObjUnit, SectionIndex, SymbolIndex,
},
util::{align_up, comment::MWComment},
};
@ -444,8 +444,8 @@ fn create_gap_splits(obj: &mut ObjInfo) -> Result<()> {
/// Ensures that all .bss splits following a common split are also marked as common.
fn update_common_splits(obj: &mut ObjInfo, common_start: Option<u32>) -> Result<()> {
let Some((bss_section_index, common_bss_start)) = (match common_start {
Some(addr) => Some((
let Some(common_bss_start) = (match common_start {
Some(addr) => Some(SectionAddress::new(
obj.sections.by_name(".bss")?.ok_or_else(|| anyhow!("Failed to find .bss section"))?.0,
addr,
)),
@ -454,8 +454,8 @@ fn update_common_splits(obj: &mut ObjInfo, common_start: Option<u32>) -> Result<
return Ok(());
};
log::debug!("Found common BSS start at {:#010X}", common_bss_start);
let bss_section = &mut obj.sections[bss_section_index];
for (addr, split) in bss_section.splits.for_range_mut(common_bss_start..) {
let bss_section = &mut obj.sections[common_bss_start.section];
for (addr, split) in bss_section.splits.for_range_mut(common_bss_start.address..) {
if !split.common {
split.common = true;
log::debug!("Added common flag to split {} at {:#010X}", split.unit, addr);
@ -593,8 +593,8 @@ fn add_padding_symbols(obj: &mut ObjInfo) -> Result<()> {
.peekable();
while let Some((_, symbol)) = iter.next() {
// Common BSS is allowed to have gaps and overlaps to accurately match the common BSS inflation bug
if matches!(common_bss, Some((idx, addr)) if
section_index == idx && symbol.address as u32 >= addr)
if matches!(common_bss, Some(addr) if
section_index == addr.section && symbol.address as u32 >= addr.address)
{
continue;
}
@ -933,11 +933,11 @@ fn resolve_link_order(obj: &ObjInfo) -> Result<Vec<ObjUnit>> {
#[instrument(level = "debug", skip(obj))]
pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo>> {
let mut objects: Vec<ObjInfo> = vec![];
let mut object_symbols: Vec<Vec<Option<usize>>> = vec![];
let mut object_symbols: Vec<Vec<Option<SymbolIndex>>> = vec![];
let mut name_to_obj: HashMap<String, usize> = HashMap::new();
for unit in &obj.link_order {
name_to_obj.insert(unit.name.clone(), objects.len());
object_symbols.push(vec![None; obj.symbols.count()]);
object_symbols.push(vec![None; obj.symbols.count() as usize]);
let mut split_obj = ObjInfo::new(
ObjKind::Relocatable,
ObjArchitecture::PowerPc,
@ -1079,7 +1079,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
s.section == Some(section_index) && !is_linker_generated_label(&s.name)
})
{
if symbol_idxs[symbol_idx].is_some() {
if symbol_idxs[symbol_idx as usize].is_some() {
continue; // should never happen?
}
@ -1092,7 +1092,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
continue;
}
symbol_idxs[symbol_idx] = Some(split_obj.symbols.add_direct(ObjSymbol {
let new_index = split_obj.symbols.add_direct(ObjSymbol {
name: symbol.name.clone(),
demangled_name: symbol.demangled_name.clone(),
address: if split.common {
@ -1113,7 +1113,8 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
data_kind: symbol.data_kind,
name_hash: symbol.name_hash,
demangled_name_hash: symbol.demangled_name_hash,
})?);
})?;
symbol_idxs[symbol_idx as usize] = Some(new_index);
}
// For mwldeppc 2.7 and above, a .comment section is required to link without error
@ -1156,7 +1157,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
let symbol_idxs = &mut object_symbols[obj_idx];
for (_section_index, section) in out_obj.sections.iter_mut() {
for (reloc_address, reloc) in section.relocations.iter_mut() {
match symbol_idxs[reloc.target_symbol] {
match symbol_idxs[reloc.target_symbol as usize] {
Some(out_sym_idx) => {
reloc.target_symbol = out_sym_idx;
}
@ -1189,7 +1190,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
globalize_symbols.push((reloc.target_symbol, new_name));
}
symbol_idxs[reloc.target_symbol] = Some(out_sym_idx);
symbol_idxs[reloc.target_symbol as usize] = Some(out_sym_idx);
out_obj.symbols.add_direct(ObjSymbol {
name: target_sym.name.clone(),
demangled_name: target_sym.demangled_name.clone(),
@ -1233,7 +1234,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
// Upgrade local symbols to global if necessary
for (obj, symbol_map) in objects.iter_mut().zip(&object_symbols) {
for (globalize_idx, new_name) in &globalize_symbols {
if let Some(symbol_idx) = symbol_map[*globalize_idx] {
if let Some(symbol_idx) = symbol_map[*globalize_idx as usize] {
let mut symbol = obj.symbols[symbol_idx].clone();
symbol.name.clone_from(new_name);
if symbol.flags.is_local() {
@ -1248,7 +1249,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
// Extern linker generated symbols
for obj in &mut objects {
let mut replace_symbols = vec![];
for (symbol_idx, symbol) in obj.symbols.iter().enumerate() {
for (symbol_idx, symbol) in obj.symbols.iter() {
if is_linker_generated_label(&symbol.name) && symbol.section.is_some() {
log::debug!("Externing {:?} in {}", symbol, obj.name);
replace_symbols.push((symbol_idx, ObjSymbol {
@ -1352,7 +1353,7 @@ pub fn is_linker_generated_object(name: &str) -> bool {
}
/// Locate the end address of a section when excluding linker generated objects
pub fn end_for_section(obj: &ObjInfo, section_index: usize) -> Result<SectionAddress> {
pub fn end_for_section(obj: &ObjInfo, section_index: SectionIndex) -> Result<SectionAddress> {
let section = obj
.sections
.get(section_index)