Migrate SectionIndex/SymbolIndex to u32
This halves the size of structs like SectionAddress.
This commit is contained in:
parent
1f4b452bd5
commit
b184fee73f
|
@ -16,12 +16,15 @@ use crate::{
|
||||||
vm::{BranchTarget, GprValue, StepResult, VM},
|
vm::{BranchTarget, GprValue, StepResult, VM},
|
||||||
RelocationTarget,
|
RelocationTarget,
|
||||||
},
|
},
|
||||||
obj::{ObjInfo, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind},
|
obj::{
|
||||||
|
ObjInfo, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
||||||
|
SectionIndex,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SectionAddress {
|
pub struct SectionAddress {
|
||||||
pub section: usize,
|
pub section: SectionIndex,
|
||||||
pub address: u32,
|
pub address: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +41,7 @@ impl Display for SectionAddress {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl 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 {
|
pub fn offset(self, offset: i32) -> Self {
|
||||||
Self { section: self.section, address: self.address.wrapping_add_signed(offset) }
|
Self { section: self.section, address: self.address.wrapping_add_signed(offset) }
|
||||||
|
@ -116,7 +119,7 @@ pub struct AnalyzerState {
|
||||||
pub functions: BTreeMap<SectionAddress, FunctionInfo>,
|
pub functions: BTreeMap<SectionAddress, FunctionInfo>,
|
||||||
pub jump_tables: BTreeMap<SectionAddress, u32>,
|
pub jump_tables: BTreeMap<SectionAddress, u32>,
|
||||||
pub known_symbols: BTreeMap<SectionAddress, Vec<ObjSymbol>>,
|
pub known_symbols: BTreeMap<SectionAddress, Vec<ObjSymbol>>,
|
||||||
pub known_sections: BTreeMap<usize, String>,
|
pub known_sections: BTreeMap<SectionIndex, String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AnalyzerState {
|
impl AnalyzerState {
|
||||||
|
|
|
@ -18,7 +18,7 @@ struct VisitedAddresses {
|
||||||
|
|
||||||
impl VisitedAddresses {
|
impl VisitedAddresses {
|
||||||
pub fn new(obj: &ObjInfo) -> Self {
|
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() {
|
for (_, section) in obj.sections.iter() {
|
||||||
if section.kind == ObjSectionKind::Code {
|
if section.kind == ObjSectionKind::Code {
|
||||||
let size = (section.size / 4) as usize;
|
let size = (section.size / 4) as usize;
|
||||||
|
@ -32,11 +32,13 @@ impl VisitedAddresses {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains(&self, section_address: u32, address: SectionAddress) -> bool {
|
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) {
|
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]
|
#[inline]
|
||||||
|
|
|
@ -6,7 +6,9 @@ use ppc750cl::Ins;
|
||||||
use crate::{
|
use crate::{
|
||||||
analysis::cfa::SectionAddress,
|
analysis::cfa::SectionAddress,
|
||||||
array_ref,
|
array_ref,
|
||||||
obj::{ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbolKind},
|
obj::{
|
||||||
|
ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbolKind, SectionIndex,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub mod cfa;
|
pub mod cfa;
|
||||||
|
@ -36,11 +38,9 @@ fn read_unresolved_relocation_address(
|
||||||
address: u32,
|
address: u32,
|
||||||
reloc_kind: Option<ObjRelocKind>,
|
reloc_kind: Option<ObjRelocKind>,
|
||||||
) -> Result<Option<RelocationTarget>> {
|
) -> Result<Option<RelocationTarget>> {
|
||||||
if let Some(reloc) = obj
|
if let Some(reloc) = obj.unresolved_relocations.iter().find(|reloc| {
|
||||||
.unresolved_relocations
|
reloc.section as SectionIndex == section.elf_index && reloc.address == address
|
||||||
.iter()
|
}) {
|
||||||
.find(|reloc| reloc.section as usize == section.elf_index && reloc.address == address)
|
|
||||||
{
|
|
||||||
if reloc.module_id != obj.module_id {
|
if reloc.module_id != obj.module_id {
|
||||||
return Ok(Some(RelocationTarget::External));
|
return Ok(Some(RelocationTarget::External));
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ fn read_unresolved_relocation_address(
|
||||||
ensure!(reloc.kind == reloc_kind);
|
ensure!(reloc.kind == reloc_kind);
|
||||||
}
|
}
|
||||||
let (target_section_index, target_section) =
|
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!(
|
anyhow!(
|
||||||
"Failed to find target section {} for unresolved relocation",
|
"Failed to find target section {} for unresolved relocation",
|
||||||
reloc.target_section
|
reloc.target_section
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{ObjDataKind, ObjInfo, ObjSectionKind, ObjSymbolKind},
|
obj::{ObjDataKind, ObjInfo, ObjSectionKind, ObjSymbolKind, SymbolIndex},
|
||||||
util::split::is_linker_generated_label,
|
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<()> {
|
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
|
for (section_index, section) in obj
|
||||||
.sections
|
.sections
|
||||||
.iter()
|
.iter()
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
analysis::cfa::{AnalyzerState, FunctionInfo, SectionAddress},
|
analysis::cfa::{AnalyzerState, FunctionInfo, SectionAddress},
|
||||||
obj::{
|
obj::{
|
||||||
ObjInfo, ObjKind, ObjRelocKind, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
|
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
|
// And the section ends with a null pointer
|
||||||
while let Some(reloc) = obj.unresolved_relocations.iter().find(|reloc| {
|
while let Some(reloc) = obj.unresolved_relocations.iter().find(|reloc| {
|
||||||
reloc.module_id == obj.module_id
|
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.address == current_address
|
||||||
&& reloc.kind == ObjRelocKind::Absolute
|
&& reloc.kind == ObjRelocKind::Absolute
|
||||||
}) {
|
}) {
|
||||||
let Some((target_section_index, target_section)) = obj
|
let Some((target_section_index, target_section)) =
|
||||||
.sections
|
obj.sections.iter().find(|(_, section)| {
|
||||||
.iter()
|
section.elf_index == reloc.target_section as SectionIndex
|
||||||
.find(|(_, section)| section.elf_index == reloc.target_section as usize)
|
})
|
||||||
else {
|
else {
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,7 +19,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
obj::{
|
obj::{
|
||||||
ObjDataKind, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind,
|
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!(
|
debug_assert_ne!(
|
||||||
value,
|
value,
|
||||||
RelocationTarget::Address(SectionAddress::new(
|
RelocationTarget::Address(SectionAddress::new(
|
||||||
usize::MAX,
|
SectionIndex::MAX,
|
||||||
0
|
0
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -359,7 +359,7 @@ impl Tracker {
|
||||||
debug_assert_ne!(
|
debug_assert_ne!(
|
||||||
address,
|
address,
|
||||||
RelocationTarget::Address(SectionAddress::new(
|
RelocationTarget::Address(SectionAddress::new(
|
||||||
usize::MAX,
|
SectionIndex::MAX,
|
||||||
0
|
0
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -380,7 +380,7 @@ impl Tracker {
|
||||||
debug_assert_ne!(
|
debug_assert_ne!(
|
||||||
address,
|
address,
|
||||||
RelocationTarget::Address(SectionAddress::new(
|
RelocationTarget::Address(SectionAddress::new(
|
||||||
usize::MAX,
|
SectionIndex::MAX,
|
||||||
0
|
0
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
|
@ -464,7 +464,7 @@ impl Tracker {
|
||||||
{
|
{
|
||||||
(addr, is_function_addr(addr))
|
(addr, is_function_addr(addr))
|
||||||
} else {
|
} else {
|
||||||
(SectionAddress::new(usize::MAX, 0), false)
|
(SectionAddress::new(SectionIndex::MAX, 0), false)
|
||||||
};
|
};
|
||||||
if branch.link || !is_fn_addr {
|
if branch.link || !is_fn_addr {
|
||||||
self.relocations.insert(ins_addr, match ins.op {
|
self.relocations.insert(ins_addr, match ins.op {
|
||||||
|
@ -549,7 +549,7 @@ impl Tracker {
|
||||||
fn process_data(
|
fn process_data(
|
||||||
&mut self,
|
&mut self,
|
||||||
obj: &ObjInfo,
|
obj: &ObjInfo,
|
||||||
section_index: usize,
|
section_index: SectionIndex,
|
||||||
section: &ObjSection,
|
section: &ObjSection,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut addr = SectionAddress::new(section_index, section.address as u32);
|
let mut addr = SectionAddress::new(section_index, section.address as u32);
|
||||||
|
@ -602,7 +602,7 @@ impl Tracker {
|
||||||
} else {
|
} else {
|
||||||
// Check known relocations (function signature matching)
|
// Check known relocations (function signature matching)
|
||||||
if self.known_relocations.contains(&from) {
|
if self.known_relocations.contains(&from) {
|
||||||
return Some(SectionAddress::new(usize::MAX, addr));
|
return Some(SectionAddress::new(SectionIndex::MAX, addr));
|
||||||
}
|
}
|
||||||
// Check special symbols
|
// Check special symbols
|
||||||
if self.stack_address == Some(addr)
|
if self.stack_address == Some(addr)
|
||||||
|
@ -613,7 +613,7 @@ impl Tracker {
|
||||||
|| self.sda2_base == Some(addr)
|
|| self.sda2_base == Some(addr)
|
||||||
|| self.sda_base == Some(addr)
|
|| self.sda_base == Some(addr)
|
||||||
{
|
{
|
||||||
return Some(SectionAddress::new(usize::MAX, addr));
|
return Some(SectionAddress::new(SectionIndex::MAX, addr));
|
||||||
}
|
}
|
||||||
// Not valid
|
// Not valid
|
||||||
None
|
None
|
||||||
|
@ -625,7 +625,7 @@ impl Tracker {
|
||||||
obj: &mut ObjInfo,
|
obj: &mut ObjInfo,
|
||||||
addr: u32,
|
addr: u32,
|
||||||
reloc_kind: ObjRelocKind,
|
reloc_kind: ObjRelocKind,
|
||||||
) -> Option<usize> {
|
) -> Option<SymbolIndex> {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
reloc_kind,
|
reloc_kind,
|
||||||
ObjRelocKind::PpcAddr16Ha | ObjRelocKind::PpcAddr16Lo
|
ObjRelocKind::PpcAddr16Ha | ObjRelocKind::PpcAddr16Lo
|
||||||
|
@ -641,7 +641,7 @@ impl Tracker {
|
||||||
// return generate_special_symbol(obj, addr, &name).ok();
|
// 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 let Some(value) = opt {
|
||||||
if addr == value {
|
if addr == value {
|
||||||
return generate_special_symbol(obj, value, name).ok();
|
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(
|
obj.add_symbol(
|
||||||
ObjSymbol {
|
ObjSymbol {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::{
|
||||||
cmd::shasum::file_sha1_string,
|
cmd::shasum::file_sha1_string,
|
||||||
obj::{
|
obj::{
|
||||||
best_match_for_reloc, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSectionKind, ObjSymbol,
|
best_match_for_reloc, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSectionKind, ObjSymbol,
|
||||||
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope, SymbolIndex,
|
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope, SectionIndex, SymbolIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
asm::write_asm,
|
asm::write_asm,
|
||||||
|
@ -402,7 +402,7 @@ pub fn run(args: Args) -> Result<()> {
|
||||||
|
|
||||||
fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
|
fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
|
||||||
let rso = process_rso(&mut Cursor::new(buf))?;
|
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 {
|
let dol_section_index = match symbol.section {
|
||||||
Some(section) => section,
|
Some(section) => section,
|
||||||
None => bail!(
|
None => bail!(
|
||||||
|
@ -411,15 +411,17 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
|
||||||
symbol.address
|
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)
|
(None, symbol.address as u32, None)
|
||||||
} else {
|
} 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"
|
"extabindex"
|
||||||
} else {
|
} else {
|
||||||
DOL_SECTION_NAMES.get(dol_section_index).and_then(|&opt| opt).ok_or_else(|| {
|
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)
|
|| anyhow!("Can't add symbol for unknown DOL section {}", dol_section_index),
|
||||||
})?
|
)?
|
||||||
};
|
};
|
||||||
let (dol_section_index, dol_section) = obj
|
let (dol_section_index, dol_section) = obj
|
||||||
.sections
|
.sections
|
||||||
|
@ -577,7 +579,7 @@ fn update_symbols(
|
||||||
if source_module_id == obj.module_id {
|
if source_module_id == obj.module_id {
|
||||||
// Skip if already resolved
|
// Skip if already resolved
|
||||||
let (_, source_section) =
|
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!(
|
anyhow!(
|
||||||
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
|
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
|
||||||
rel_reloc.section,
|
rel_reloc.section,
|
||||||
|
@ -591,8 +593,10 @@ fn update_symbols(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let (target_section_index, target_section) =
|
let (target_section_index, target_section) = obj
|
||||||
obj.sections.get_elf_index(rel_reloc.target_section as usize).ok_or_else(|| {
|
.sections
|
||||||
|
.get_elf_index(rel_reloc.target_section as SectionIndex)
|
||||||
|
.ok_or_else(|| {
|
||||||
anyhow!(
|
anyhow!(
|
||||||
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
|
"Failed to locate REL section {} in module ID {}: source module {}, {:?}",
|
||||||
rel_reloc.target_section,
|
rel_reloc.target_section,
|
||||||
|
@ -655,7 +659,7 @@ fn create_relocations(
|
||||||
for rel_reloc in take(&mut obj.unresolved_relocations) {
|
for rel_reloc in take(&mut obj.unresolved_relocations) {
|
||||||
// Skip if already resolved
|
// Skip if already resolved
|
||||||
let (_, source_section) =
|
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!(
|
anyhow!(
|
||||||
"Failed to locate REL section {} in module ID {}: {:?}",
|
"Failed to locate REL section {} in module ID {}: {:?}",
|
||||||
rel_reloc.section,
|
rel_reloc.section,
|
||||||
|
@ -683,7 +687,7 @@ fn create_relocations(
|
||||||
anyhow!("Failed to locate DOL section at {:#010X}", rel_reloc.addend)
|
anyhow!("Failed to locate DOL section at {:#010X}", rel_reloc.addend)
|
||||||
})?
|
})?
|
||||||
} else {
|
} 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!(
|
anyhow!(
|
||||||
"Failed to locate module {} section {}",
|
"Failed to locate module {} section {}",
|
||||||
|
@ -720,7 +724,7 @@ fn create_relocations(
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
let (_, source_section) =
|
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)?;
|
source_section.relocations.insert(rel_reloc.address, reloc)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,7 +743,7 @@ fn resolve_external_relocations(
|
||||||
module_id: u32,
|
module_id: u32,
|
||||||
symbol_index: SymbolIndex,
|
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 (_section_index, section) in obj.sections.iter_mut() {
|
||||||
for (_reloc_address, reloc) in section.relocations.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 linked_obj = process_elf(&args.elf_file)?;
|
||||||
|
|
||||||
let common_bss = obj.sections.common_bss_start();
|
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()
|
!matches!(s.kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section) && !s.flags.is_stripped()
|
||||||
}) {
|
}) {
|
||||||
let Some(orig_section_index) = orig_sym.section else { continue };
|
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 &&
|
if linked_sym.size != orig_sym.size &&
|
||||||
// TODO validate common symbol sizes
|
// TODO validate common symbol sizes
|
||||||
// (need to account for inflation bug)
|
// (need to account for inflation bug)
|
||||||
matches!(common_bss, Some((idx, addr)) if
|
matches!(common_bss, Some(addr) if
|
||||||
orig_section_index == idx && orig_sym.address as u32 >= addr)
|
orig_section_index == addr.section && orig_sym.address as u32 >= addr.address)
|
||||||
{
|
{
|
||||||
log::error!(
|
log::error!(
|
||||||
"Expected {} (type {:?}) to have size {:#X}, but found {:#X}",
|
"Expected {} (type {:?}) to have size {:#X}, but found {:#X}",
|
||||||
|
@ -1656,7 +1660,7 @@ fn diff(args: DiffArgs) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Data diff
|
// 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)
|
s.size > 0 && !matches!(s.kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section)
|
||||||
}) {
|
}) {
|
||||||
let Some(orig_section_index) = orig_sym.section else { continue };
|
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 linked_obj = process_elf(&args.elf_file)?;
|
||||||
|
|
||||||
let mut replacements: Vec<(SymbolIndex, Option<ObjSymbol>)> = vec![];
|
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
|
// skip ABS for now
|
||||||
if orig_sym.section.is_none() {
|
if orig_sym.section.is_none() {
|
||||||
continue;
|
continue;
|
||||||
|
@ -1832,7 +1836,7 @@ fn apply(args: ApplyArgs) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add symbols from the linked object that aren't in the original
|
// 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)
|
if matches!(linked_sym.kind, ObjSymbolKind::Section)
|
||||||
|| is_auto_symbol(linked_sym)
|
|| is_auto_symbol(linked_sym)
|
||||||
|| is_linker_generated_object(&linked_sym.name)
|
|| is_linker_generated_object(&linked_sym.name)
|
||||||
|
|
|
@ -28,7 +28,10 @@ use crate::{
|
||||||
},
|
},
|
||||||
array_ref_mut,
|
array_ref_mut,
|
||||||
cmd::dol::{find_object_base, ModuleConfig, ObjectBase, ProjectConfig},
|
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::{
|
util::{
|
||||||
config::{is_auto_symbol, read_splits_sections, SectionDef},
|
config::{is_auto_symbol, read_splits_sections, SectionDef},
|
||||||
dol::process_dol,
|
dol::process_dol,
|
||||||
|
@ -499,7 +502,7 @@ fn merge(args: MergeArgs) -> Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Merging {} REL(s)", processed);
|
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);
|
let mut offset = align32(arena_lo + 0x2000);
|
||||||
for module in module_map.values() {
|
for module in module_map.values() {
|
||||||
for (mod_section_index, mod_section) in module.sections.iter() {
|
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,
|
section_known: mod_section.section_known,
|
||||||
splits: mod_section.splits.clone(),
|
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) {
|
for (_, mod_symbol) in module.symbols.for_section(mod_section_index) {
|
||||||
obj.symbols.add_direct(ObjSymbol {
|
obj.symbols.add_direct(ObjSymbol {
|
||||||
name: mod_symbol.name.clone(),
|
name: mod_symbol.name.clone(),
|
||||||
|
@ -542,7 +545,8 @@ fn merge(args: MergeArgs) -> Result<()> {
|
||||||
log::info!("Applying REL relocations");
|
log::info!("Applying REL relocations");
|
||||||
for module in module_map.values() {
|
for module in module_map.values() {
|
||||||
for rel_reloc in &module.unresolved_relocations {
|
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)
|
+ rel_reloc.address)
|
||||||
& !3;
|
& !3;
|
||||||
let target_addr = if rel_reloc.module_id == 0 {
|
let target_addr = if rel_reloc.module_id == 0 {
|
||||||
|
|
|
@ -13,7 +13,9 @@ use std::{
|
||||||
use anyhow::{anyhow, bail, ensure, Result};
|
use anyhow::{anyhow, bail, ensure, Result};
|
||||||
use objdiff_core::obj::split_meta::SplitMeta;
|
use objdiff_core::obj::split_meta::SplitMeta;
|
||||||
pub use relocations::{ObjReloc, ObjRelocKind, ObjRelocations};
|
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 splits::{ObjSplit, ObjSplits};
|
||||||
pub use symbols::{
|
pub use symbols::{
|
||||||
best_match_for_reloc, ObjDataKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
best_match_for_reloc, ObjDataKind, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
||||||
|
@ -132,7 +134,12 @@ impl ObjInfo {
|
||||||
self.symbols.add(in_symbol, replace)
|
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
|
let section = self
|
||||||
.sections
|
.sections
|
||||||
.get_mut(section_index)
|
.get_mut(section_index)
|
||||||
|
@ -322,8 +329,8 @@ impl ObjInfo {
|
||||||
// Include common symbols
|
// Include common symbols
|
||||||
self.symbols
|
self.symbols
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|&symbol| symbol.flags.is_common())
|
.filter(|&(_, symbol)| symbol.flags.is_common())
|
||||||
.map(|s| s.size as u32),
|
.map(|(_, s)| s.size as u32),
|
||||||
)
|
)
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,10 @@ use std::{
|
||||||
use anyhow::{anyhow, bail, ensure, Result};
|
use anyhow::{anyhow, bail, ensure, Result};
|
||||||
use itertools::Itertools;
|
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)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
pub enum ObjSectionKind {
|
pub enum ObjSectionKind {
|
||||||
|
@ -26,7 +29,7 @@ pub struct ObjSection {
|
||||||
pub data: Vec<u8>,
|
pub data: Vec<u8>,
|
||||||
pub align: u64,
|
pub align: u64,
|
||||||
/// REL files reference the original ELF section indices
|
/// REL files reference the original ELF section indices
|
||||||
pub elf_index: usize,
|
pub elf_index: SectionIndex,
|
||||||
pub relocations: ObjRelocations,
|
pub relocations: ObjRelocations,
|
||||||
pub virtual_address: Option<u64>,
|
pub virtual_address: Option<u64>,
|
||||||
pub file_offset: u64,
|
pub file_offset: u64,
|
||||||
|
@ -40,38 +43,45 @@ pub struct ObjSections {
|
||||||
sections: Vec<ObjSection>,
|
sections: Vec<ObjSection>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type SectionIndex = u32;
|
||||||
|
|
||||||
impl ObjSections {
|
impl ObjSections {
|
||||||
pub fn new(obj_kind: ObjKind, sections: Vec<ObjSection>) -> Self { Self { obj_kind, sections } }
|
pub fn new(obj_kind: ObjKind, sections: Vec<ObjSection>) -> Self { Self { obj_kind, sections } }
|
||||||
|
|
||||||
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (usize, &ObjSection)> {
|
pub fn iter(&self) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection)> {
|
||||||
self.sections.iter().enumerate()
|
self.sections.iter().enumerate().map(|(i, s)| (i as SectionIndex, s))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (usize, &mut ObjSection)> {
|
pub fn iter_mut(&mut self) -> impl DoubleEndedIterator<Item = (SectionIndex, &mut ObjSection)> {
|
||||||
self.sections.iter_mut().enumerate()
|
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 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(&self, index: SectionIndex) -> Option<&ObjSection> {
|
||||||
|
self.sections.get(index as usize)
|
||||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut ObjSection> {
|
|
||||||
self.sections.get_mut(index)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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)
|
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!(
|
ensure!(
|
||||||
self.obj_kind == ObjKind::Executable,
|
self.obj_kind == ObjKind::Executable,
|
||||||
"Use of ObjSections::at_address in relocatable object"
|
"Use of ObjSections::at_address in relocatable object"
|
||||||
|
@ -81,7 +91,7 @@ impl ObjSections {
|
||||||
.ok_or_else(|| anyhow!("Failed to locate section @ {:#010X}", addr))
|
.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!(
|
ensure!(
|
||||||
self.obj_kind == ObjKind::Executable,
|
self.obj_kind == ObjKind::Executable,
|
||||||
"Use of ObjSections::at_address_mut in relocatable object"
|
"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))
|
.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!(
|
ensure!(
|
||||||
self.obj_kind == ObjKind::Executable,
|
self.obj_kind == ObjKind::Executable,
|
||||||
"Use of ObjSections::with_range in relocatable object"
|
"Use of ObjSections::with_range in relocatable object"
|
||||||
|
@ -104,46 +114,52 @@ impl ObjSections {
|
||||||
pub fn by_kind(
|
pub fn by_kind(
|
||||||
&self,
|
&self,
|
||||||
kind: ObjSectionKind,
|
kind: ObjSectionKind,
|
||||||
) -> impl DoubleEndedIterator<Item = (usize, &ObjSection)> {
|
) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection)> {
|
||||||
self.iter().filter(move |(_, s)| s.kind == kind)
|
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()
|
self.iter()
|
||||||
.filter(move |(_, s)| s.name == name)
|
.filter(move |(_, s)| s.name == name)
|
||||||
.at_most_one()
|
.at_most_one()
|
||||||
.map_err(|_| anyhow!("Multiple sections with name {}", name))
|
.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();
|
let index = self.sections.len();
|
||||||
self.sections.push(section);
|
self.sections.push(section);
|
||||||
index
|
index as SectionIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn all_splits(
|
pub fn all_splits(
|
||||||
&self,
|
&self,
|
||||||
) -> impl DoubleEndedIterator<Item = (usize, &ObjSection, u32, &ObjSplit)> {
|
) -> impl DoubleEndedIterator<Item = (SectionIndex, &ObjSection, u32, &ObjSplit)> {
|
||||||
self.iter()
|
self.iter()
|
||||||
.flat_map(|(idx, s)| s.splits.iter().map(move |(addr, split)| (idx, s, addr, split)))
|
.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 {
|
let Ok(Some((section_index, section))) = self.by_name(".bss") else {
|
||||||
return None;
|
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;
|
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 {
|
impl IndexMut<SectionIndex> for ObjSections {
|
||||||
fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.sections[index] }
|
fn index_mut(&mut self, index: SectionIndex) -> &mut Self::Output {
|
||||||
|
&mut self.sections[index as usize]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjSection {
|
impl ObjSection {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use anyhow::{anyhow, Result};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{ObjInfo, ObjSection},
|
obj::{ObjInfo, ObjSection, SectionIndex},
|
||||||
util::{nested::NestedVec, split::default_section_align},
|
util::{nested::NestedVec, split::default_section_align},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ impl ObjSplit {
|
||||||
pub fn alignment(
|
pub fn alignment(
|
||||||
&self,
|
&self,
|
||||||
obj: &ObjInfo,
|
obj: &ObjInfo,
|
||||||
section_index: usize,
|
section_index: SectionIndex,
|
||||||
section: &ObjSection,
|
section: &ObjSection,
|
||||||
split_addr: u32,
|
split_addr: u32,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
|
|
|
@ -12,7 +12,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
analysis::cfa::SectionAddress,
|
analysis::cfa::SectionAddress,
|
||||||
obj::{ObjKind, ObjRelocKind, ObjSections},
|
obj::{sections::SectionIndex, ObjKind, ObjRelocKind, ObjSections},
|
||||||
util::{
|
util::{
|
||||||
config::{is_auto_jump_table, is_auto_label, is_auto_symbol, parse_u32},
|
config::{is_auto_jump_table, is_auto_label, is_auto_symbol, parse_u32},
|
||||||
nested::NestedVec,
|
nested::NestedVec,
|
||||||
|
@ -187,7 +187,7 @@ pub struct ObjSymbol {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub demangled_name: Option<String>,
|
pub demangled_name: Option<String>,
|
||||||
pub address: u64,
|
pub address: u64,
|
||||||
pub section: Option<usize>,
|
pub section: Option<SectionIndex>,
|
||||||
pub size: u64,
|
pub size: u64,
|
||||||
pub size_known: bool,
|
pub size_known: bool,
|
||||||
pub flags: ObjSymbolFlagSet,
|
pub flags: ObjSymbolFlagSet,
|
||||||
|
@ -199,7 +199,7 @@ pub struct ObjSymbol {
|
||||||
pub demangled_name_hash: Option<u32>,
|
pub demangled_name_hash: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type SymbolIndex = usize;
|
pub type SymbolIndex = u32;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct ObjSymbols {
|
pub struct ObjSymbols {
|
||||||
|
@ -216,8 +216,10 @@ impl ObjSymbols {
|
||||||
let mut symbols_by_section: Vec<BTreeMap<u32, Vec<SymbolIndex>>> = vec![];
|
let mut symbols_by_section: Vec<BTreeMap<u32, Vec<SymbolIndex>>> = vec![];
|
||||||
let mut symbols_by_name = HashMap::<String, Vec<SymbolIndex>>::new();
|
let mut symbols_by_name = HashMap::<String, Vec<SymbolIndex>>::new();
|
||||||
for (idx, symbol) in symbols.iter().enumerate() {
|
for (idx, symbol) in symbols.iter().enumerate() {
|
||||||
|
let idx = idx as SymbolIndex;
|
||||||
symbols_by_address.nested_push(symbol.address as u32, idx);
|
symbols_by_address.nested_push(symbol.address as u32, idx);
|
||||||
if let Some(section_idx) = symbol.section {
|
if let Some(section_idx) = symbol.section {
|
||||||
|
let section_idx = section_idx as usize;
|
||||||
if section_idx >= symbols_by_section.len() {
|
if section_idx >= symbols_by_section.len() {
|
||||||
symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
|
symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
|
||||||
}
|
}
|
||||||
|
@ -312,7 +314,7 @@ impl ObjSymbols {
|
||||||
}
|
}
|
||||||
symbol_idx
|
symbol_idx
|
||||||
} else {
|
} else {
|
||||||
let target_symbol_idx = self.symbols.len();
|
let target_symbol_idx = self.symbols.len() as SymbolIndex;
|
||||||
self.add_direct(ObjSymbol {
|
self.add_direct(ObjSymbol {
|
||||||
name: in_symbol.name,
|
name: in_symbol.name,
|
||||||
demangled_name: in_symbol.demangled_name,
|
demangled_name: in_symbol.demangled_name,
|
||||||
|
@ -333,9 +335,10 @@ impl ObjSymbols {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_direct(&mut self, in_symbol: ObjSymbol) -> Result<SymbolIndex> {
|
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);
|
self.symbols_by_address.nested_push(in_symbol.address as u32, symbol_idx);
|
||||||
if let Some(section_idx) = in_symbol.section {
|
if let Some(section_idx) = in_symbol.section {
|
||||||
|
let section_idx = section_idx as usize;
|
||||||
if section_idx >= self.symbols_by_section.len() {
|
if section_idx >= self.symbols_by_section.len() {
|
||||||
self.symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
|
self.symbols_by_section.resize_with(section_idx + 1, BTreeMap::new);
|
||||||
}
|
}
|
||||||
|
@ -355,28 +358,30 @@ impl ObjSymbols {
|
||||||
Ok(symbol_idx)
|
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(
|
pub fn at_section_address(
|
||||||
&self,
|
&self,
|
||||||
section_idx: usize,
|
section_idx: SectionIndex,
|
||||||
addr: u32,
|
addr: u32,
|
||||||
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
|
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
|
||||||
self.symbols_by_section
|
self.symbols_by_section
|
||||||
.get(section_idx)
|
.get(section_idx as usize)
|
||||||
.and_then(|v| v.get(&addr))
|
.and_then(|v| v.get(&addr))
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flatten()
|
.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
|
// "Stripped" symbols don't actually exist at the address
|
||||||
.filter(|(_, sym)| !sym.flags.is_stripped())
|
.filter(|(_, sym)| !sym.flags.is_stripped())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kind_at_section_address(
|
pub fn kind_at_section_address(
|
||||||
&self,
|
&self,
|
||||||
section_idx: usize,
|
section_idx: SectionIndex,
|
||||||
addr: u32,
|
addr: u32,
|
||||||
kind: ObjSymbolKind,
|
kind: ObjSymbolKind,
|
||||||
) -> Result<Option<(SymbolIndex, &ObjSymbol)>> {
|
) -> Result<Option<(SymbolIndex, &ObjSymbol)>> {
|
||||||
|
@ -397,7 +402,7 @@ impl ObjSymbols {
|
||||||
self.symbols_by_section
|
self.symbols_by_section
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|v| v.iter().map(|(_, v)| v))
|
.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
|
// Iterate over all ABS symbols
|
||||||
|
@ -405,24 +410,24 @@ impl ObjSymbols {
|
||||||
debug_assert!(self.obj_kind == ObjKind::Executable);
|
debug_assert!(self.obj_kind == ObjKind::Executable);
|
||||||
self.symbols_by_address
|
self.symbols_by_address
|
||||||
.iter()
|
.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())
|
.filter(|(_, s)| s.section.is_none())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over range in address ascending order, excluding ABS symbols
|
// Iterate over range in address ascending order, excluding ABS symbols
|
||||||
pub fn for_section_range<R>(
|
pub fn for_section_range<R>(
|
||||||
&self,
|
&self,
|
||||||
section_index: usize,
|
section_index: SectionIndex,
|
||||||
range: R,
|
range: R,
|
||||||
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)>
|
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)>
|
||||||
where
|
where
|
||||||
R: RangeBounds<u32> + Clone,
|
R: RangeBounds<u32> + Clone,
|
||||||
{
|
{
|
||||||
self.symbols_by_section
|
self.symbols_by_section
|
||||||
.get(section_index)
|
.get(section_index as usize)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(move |v| v.range(range.clone()))
|
.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>(
|
pub fn indexes_for_range<R>(
|
||||||
|
@ -438,13 +443,13 @@ impl ObjSymbols {
|
||||||
|
|
||||||
pub fn for_section(
|
pub fn for_section(
|
||||||
&self,
|
&self,
|
||||||
section_idx: usize,
|
section_idx: SectionIndex,
|
||||||
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
|
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
|
||||||
self.symbols_by_section
|
self.symbols_by_section
|
||||||
.get(section_idx)
|
.get(section_idx as usize)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|v| v.iter().map(|(_, v)| v))
|
.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(
|
pub fn for_name(
|
||||||
|
@ -454,7 +459,7 @@ impl ObjSymbols {
|
||||||
self.symbols_by_name
|
self.symbols_by_name
|
||||||
.get(name)
|
.get(name)
|
||||||
.into_iter()
|
.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)>> {
|
pub fn by_name(&self, name: &str) -> Result<Option<(SymbolIndex, &ObjSymbol)>> {
|
||||||
|
@ -515,11 +520,11 @@ impl ObjSymbols {
|
||||||
&self,
|
&self,
|
||||||
kind: ObjSymbolKind,
|
kind: ObjSymbolKind,
|
||||||
) -> impl DoubleEndedIterator<Item = (SymbolIndex, &ObjSymbol)> {
|
) -> 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<()> {
|
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.address == symbol.address, "Can't modify address with replace_symbol");
|
||||||
ensure!(symbol_ref.section == symbol.section, "Can't modify section with replace_symbol");
|
ensure!(symbol_ref.section == symbol.section, "Can't modify section with replace_symbol");
|
||||||
if symbol_ref.name != symbol.name {
|
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() {
|
for (_addr, symbol_idxs) in self.indexes_for_range(..=target_addr.address).rev() {
|
||||||
let symbols = symbol_idxs
|
let symbols = symbol_idxs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&idx| (idx, &self.symbols[idx]))
|
.map(|&idx| (idx, &self.symbols[idx as usize]))
|
||||||
.filter(|(_, sym)| {
|
.filter(|(_, sym)| {
|
||||||
(sym.section.is_none() || sym.section == Some(target_addr.section))
|
(sym.section.is_none() || sym.section == Some(target_addr.section))
|
||||||
&& sym.referenced_by(reloc_kind)
|
&& sym.referenced_by(reloc_kind)
|
||||||
|
@ -570,14 +575,14 @@ impl ObjSymbols {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn flags(&mut self, idx: SymbolIndex) -> &mut ObjSymbolFlagSet {
|
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 {
|
impl Index<SymbolIndex> for ObjSymbols {
|
||||||
type Output = ObjSymbol;
|
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 {
|
impl ObjSymbol {
|
||||||
|
|
|
@ -7,7 +7,7 @@ use anyhow::Result;
|
||||||
use io::{Error, ErrorKind};
|
use io::{Error, ErrorKind};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{ObjSymbol, ObjSymbolKind},
|
obj::{ObjSymbol, ObjSymbolKind, SectionIndex},
|
||||||
util::{
|
util::{
|
||||||
dol::{DolLike, DolSection, DolSectionKind},
|
dol::{DolLike, DolSection, DolSectionKind},
|
||||||
reader::{
|
reader::{
|
||||||
|
@ -55,7 +55,7 @@ impl FromReader for AlfFile {
|
||||||
data_size: section.data_size,
|
data_size: section.data_size,
|
||||||
size: section.size,
|
size: section.size,
|
||||||
kind,
|
kind,
|
||||||
index: sections.len(),
|
index: sections.len() as SectionIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for sym in &symtab.symbols {
|
for sym in &symtab.symbols {
|
||||||
|
@ -230,7 +230,7 @@ impl AlfSymbol {
|
||||||
name,
|
name,
|
||||||
demangled_name,
|
demangled_name,
|
||||||
address: self.address as u64,
|
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: self.size as u64,
|
||||||
size_known: true,
|
size_known: true,
|
||||||
flags: Default::default(),
|
flags: Default::default(),
|
||||||
|
|
|
@ -11,7 +11,7 @@ use ppc750cl::{Argument, Ins, InsIter, Opcode};
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{
|
obj::{
|
||||||
ObjDataKind, ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
|
ObjDataKind, ObjInfo, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
|
||||||
ObjSymbolKind,
|
ObjSymbolKind, SymbolIndex,
|
||||||
},
|
},
|
||||||
util::nested::NestedVec,
|
util::nested::NestedVec,
|
||||||
};
|
};
|
||||||
|
@ -25,7 +25,7 @@ enum SymbolEntryKind {
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||||
struct SymbolEntry {
|
struct SymbolEntry {
|
||||||
index: usize,
|
index: SymbolIndex,
|
||||||
kind: SymbolEntryKind,
|
kind: SymbolEntryKind,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ where W: Write + ?Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll append generated symbols to the end
|
// 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_entries: Vec<BTreeMap<u32, Vec<SymbolEntry>>> = vec![];
|
||||||
let mut section_relocations: Vec<BTreeMap<u32, ObjReloc>> = vec![];
|
let mut section_relocations: Vec<BTreeMap<u32, ObjReloc>> = vec![];
|
||||||
for (section_idx, section) in obj.sections.iter() {
|
for (section_idx, section) in obj.sections.iter() {
|
||||||
|
@ -90,7 +90,7 @@ where W: Write + ?Sized {
|
||||||
.map(|e| e.index);
|
.map(|e| e.index);
|
||||||
if target_symbol_idx.is_none() {
|
if target_symbol_idx.is_none() {
|
||||||
let display_address = address as u64 + section.virtual_address.unwrap_or(0);
|
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 {
|
symbols.push(ObjSymbol {
|
||||||
name: format!(".L_{display_address:08X}"),
|
name: format!(".L_{display_address:08X}"),
|
||||||
address: display_address,
|
address: display_address,
|
||||||
|
@ -131,7 +131,7 @@ where W: Write + ?Sized {
|
||||||
if reloc.addend == 0 {
|
if reloc.addend == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let target = &symbols[reloc.target_symbol];
|
let target = &symbols[reloc.target_symbol as usize];
|
||||||
let target_section_idx = match target.section {
|
let target_section_idx = match target.section {
|
||||||
Some(v) => v,
|
Some(v) => v,
|
||||||
None => continue,
|
None => continue,
|
||||||
|
@ -140,7 +140,7 @@ where W: Write + ?Sized {
|
||||||
anyhow!("Invalid relocation target section: {:#010X} {:?}", reloc_address, target)
|
anyhow!("Invalid relocation target section: {:#010X} {:?}", reloc_address, target)
|
||||||
})?;
|
})?;
|
||||||
let address = (target.address as i64 + reloc.addend) as u64;
|
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::Occupied(e) => e.into_mut(),
|
||||||
btree_map::Entry::Vacant(e) => e.insert(vec![]),
|
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)
|
.any(|e| e.kind == SymbolEntryKind::Label || e.kind == SymbolEntryKind::Start)
|
||||||
{
|
{
|
||||||
let display_address = address + target_section.virtual_address.unwrap_or(0);
|
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 {
|
symbols.push(ObjSymbol {
|
||||||
name: format!(".L_{display_address:08X}"),
|
name: format!(".L_{display_address:08X}"),
|
||||||
address: display_address,
|
address: display_address,
|
||||||
|
@ -181,13 +181,17 @@ where W: Write + ?Sized {
|
||||||
}
|
}
|
||||||
|
|
||||||
for (section_index, section) in obj.sections.iter() {
|
for (section_index, section) in obj.sections.iter() {
|
||||||
let entries = §ion_entries[section_index];
|
let entries = §ion_entries[section_index as usize];
|
||||||
let relocations = §ion_relocations[section_index];
|
let relocations = §ion_relocations[section_index as usize];
|
||||||
|
|
||||||
let mut current_address = section.address as u32;
|
let mut current_address = section.address as u32;
|
||||||
let section_end = (section.address + section.size) as u32;
|
let section_end = (section.address + section.size) as u32;
|
||||||
let subsection =
|
let subsection = obj
|
||||||
obj.sections.iter().take(section_index).filter(|(_, s)| s.name == section.name).count();
|
.sections
|
||||||
|
.iter()
|
||||||
|
.take(section_index as usize)
|
||||||
|
.filter(|(_, s)| s.name == section.name)
|
||||||
|
.count();
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if current_address >= section_end {
|
if current_address >= section_end {
|
||||||
|
@ -369,7 +373,7 @@ fn write_symbol_entry<W>(
|
||||||
where
|
where
|
||||||
W: Write + ?Sized,
|
W: Write + ?Sized,
|
||||||
{
|
{
|
||||||
let symbol = &symbols[entry.index];
|
let symbol = &symbols[entry.index as usize];
|
||||||
|
|
||||||
// Skip writing certain symbols
|
// Skip writing certain symbols
|
||||||
if symbol.kind == ObjSymbolKind::Section {
|
if symbol.kind == ObjSymbolKind::Section {
|
||||||
|
@ -452,13 +456,13 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_extab(symbols: &[ObjSymbol], entry: &SymbolEntry, section: &ObjSection) -> Result<String> {
|
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 data = section.symbol_data(symbol)?;
|
||||||
let decoded = cwextab::decode_extab(data)?;
|
let decoded = cwextab::decode_extab(data)?;
|
||||||
let function_names = section
|
let function_names = section
|
||||||
.relocations
|
.relocations
|
||||||
.range(symbol.address as u32..(symbol.address + symbol.size) as u32)
|
.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();
|
.collect_vec();
|
||||||
decoded.to_string(function_names).ok_or_else(|| anyhow!("Failed to print extab entry"))
|
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))?;
|
.with_context(|| format!("At address {:#010X}", sym_addr))?;
|
||||||
entry = entry_iter.next();
|
entry = entry_iter.next();
|
||||||
} else if current_address > sym_addr {
|
} 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!(
|
bail!(
|
||||||
"Unaligned symbol entry @ {:#010X}:\n\t{:?}",
|
"Unaligned symbol entry @ {:#010X}:\n\t{:?}",
|
||||||
section.virtual_address.unwrap_or(0) as u32 + sym_addr,
|
section.virtual_address.unwrap_or(0) as u32 + sym_addr,
|
||||||
|
@ -585,7 +589,7 @@ fn find_symbol_kind(
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
match entry.kind {
|
match entry.kind {
|
||||||
SymbolEntryKind::Start => {
|
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) {
|
if !matches!(new_kind, ObjSymbolKind::Unknown | ObjSymbolKind::Section) {
|
||||||
ensure!(
|
ensure!(
|
||||||
!found || new_kind == kind,
|
!found || new_kind == kind,
|
||||||
|
@ -611,11 +615,11 @@ fn find_data_kind(
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
match entry.kind {
|
match entry.kind {
|
||||||
SymbolEntryKind::Start => {
|
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 !matches!(new_kind, ObjDataKind::Unknown) {
|
||||||
if found && new_kind != kind {
|
if found && new_kind != kind {
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
log::error!("Symbol {:?}", symbols[entry.index]);
|
log::error!("Symbol {:?}", symbols[entry.index as usize]);
|
||||||
}
|
}
|
||||||
bail!(
|
bail!(
|
||||||
"Conflicting data kinds found: {kind:?} and {new_kind:?}",
|
"Conflicting data kinds found: {kind:?} and {new_kind:?}",
|
||||||
|
@ -806,14 +810,14 @@ where
|
||||||
ObjRelocKind::Absolute => {
|
ObjRelocKind::Absolute => {
|
||||||
// Attempt to use .rel macro for relative relocations
|
// Attempt to use .rel macro for relative relocations
|
||||||
if reloc.addend != 0 {
|
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;
|
let target_addr = (target.address as i64 + reloc.addend) as u32;
|
||||||
if let Some(entry) = target
|
if let Some(entry) = target
|
||||||
.section
|
.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))
|
.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!(w, "\t.rel ")?;
|
||||||
write_symbol_name(w, &target.name)?;
|
write_symbol_name(w, &target.name)?;
|
||||||
write!(w, ", ")?;
|
write!(w, ", ")?;
|
||||||
|
@ -959,7 +963,7 @@ fn write_reloc_symbol<W>(
|
||||||
where
|
where
|
||||||
W: Write + ?Sized,
|
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) {
|
match reloc.addend.cmp(&0i64) {
|
||||||
Ordering::Greater => write!(w, "+{:#X}", reloc.addend),
|
Ordering::Greater => write!(w, "+{:#X}", reloc.addend),
|
||||||
Ordering::Less => write!(w, "-{:#X}", -reloc.addend),
|
Ordering::Less => write!(w, "-{:#X}", -reloc.addend),
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
analysis::cfa::SectionAddress,
|
analysis::cfa::SectionAddress,
|
||||||
obj::{
|
obj::{
|
||||||
ObjDataKind, ObjInfo, ObjKind, ObjSectionKind, ObjSplit, ObjSymbol, ObjSymbolFlagSet,
|
ObjDataKind, ObjInfo, ObjKind, ObjSectionKind, ObjSplit, ObjSymbol, ObjSymbolFlagSet,
|
||||||
ObjSymbolFlags, ObjSymbolKind, ObjUnit,
|
ObjSymbolFlags, ObjSymbolKind, ObjUnit, SectionIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
file::{buf_writer, FileReadInfo},
|
file::{buf_writer, FileReadInfo},
|
||||||
|
@ -621,7 +621,7 @@ fn parse_section_line(captures: Captures, state: &SplitState) -> Result<SplitLin
|
||||||
|
|
||||||
enum SplitState {
|
enum SplitState {
|
||||||
None,
|
None,
|
||||||
Sections(usize),
|
Sections(SectionIndex),
|
||||||
Unit(String),
|
Unit(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ pub fn process_code(
|
||||||
arch.process_code(
|
arch.process_code(
|
||||||
symbol.address,
|
symbol.address,
|
||||||
orig_data,
|
orig_data,
|
||||||
section.elf_index,
|
section.elf_index as usize,
|
||||||
&orig_relocs,
|
&orig_relocs,
|
||||||
&Default::default(),
|
&Default::default(),
|
||||||
config,
|
config,
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
||||||
array_ref,
|
array_ref,
|
||||||
obj::{
|
obj::{
|
||||||
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
|
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
|
||||||
ObjSymbolFlags, ObjSymbolKind,
|
ObjSymbolFlags, ObjSymbolKind, SectionIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
alf::{AlfFile, AlfSymbol, ALF_MAGIC},
|
alf::{AlfFile, AlfSymbol, ALF_MAGIC},
|
||||||
|
@ -75,7 +75,7 @@ pub struct DolSection {
|
||||||
pub size: u32,
|
pub size: u32,
|
||||||
pub kind: DolSectionKind,
|
pub kind: DolSectionKind,
|
||||||
// TODO remove
|
// TODO remove
|
||||||
pub index: usize,
|
pub index: SectionIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -103,7 +103,7 @@ impl FromReader for DolFile {
|
||||||
data_size: size,
|
data_size: size,
|
||||||
size,
|
size,
|
||||||
kind: DolSectionKind::Text,
|
kind: DolSectionKind::Text,
|
||||||
index: sections.len(),
|
index: sections.len() as SectionIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
for (idx, &size) in header.data_sizes.iter().enumerate() {
|
for (idx, &size) in header.data_sizes.iter().enumerate() {
|
||||||
|
@ -116,7 +116,7 @@ impl FromReader for DolFile {
|
||||||
data_size: size,
|
data_size: size,
|
||||||
size,
|
size,
|
||||||
kind: DolSectionKind::Data,
|
kind: DolSectionKind::Data,
|
||||||
index: sections.len(),
|
index: sections.len() as SectionIndex,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
sections.push(DolSection {
|
sections.push(DolSection {
|
||||||
|
@ -125,7 +125,7 @@ impl FromReader for DolFile {
|
||||||
data_size: 0,
|
data_size: 0,
|
||||||
size: header.bss_size,
|
size: header.bss_size,
|
||||||
kind: DolSectionKind::Bss,
|
kind: DolSectionKind::Bss,
|
||||||
index: sections.len(),
|
index: sections.len() as SectionIndex,
|
||||||
});
|
});
|
||||||
Ok(Self { header, sections })
|
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();
|
dol.sections().iter().filter(|section| section.kind == DolSectionKind::Text).count();
|
||||||
let mut eti_entries: Vec<EtiEntry> = Vec::new();
|
let mut eti_entries: Vec<EtiEntry> = Vec::new();
|
||||||
let mut eti_init_info_range: Option<(u32, u32)> = None;
|
let mut eti_init_info_range: Option<(u32, u32)> = None;
|
||||||
let mut extab_section: Option<usize> = None;
|
let mut extab_section: Option<SectionIndex> = None;
|
||||||
let mut extabindex_section: Option<usize> = None;
|
let mut extabindex_section: Option<SectionIndex> = None;
|
||||||
'outer: for dol_section in
|
'outer: for dol_section in
|
||||||
dol.sections().iter().filter(|section| section.kind == DolSectionKind::Data)
|
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
|
// 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() {
|
for (idx, section) in sections.iter_mut().enumerate() {
|
||||||
|
let idx = idx as SectionIndex;
|
||||||
match section.name.as_str() {
|
match section.name.as_str() {
|
||||||
".init" => {
|
".init" => {
|
||||||
init_section_index = Some(idx);
|
init_section_index = Some(idx);
|
||||||
|
|
|
@ -26,6 +26,7 @@ use crate::{
|
||||||
obj::{
|
obj::{
|
||||||
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind,
|
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind,
|
||||||
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjUnit,
|
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjUnit,
|
||||||
|
SectionIndex as ObjSectionIndex, SymbolIndex as ObjSymbolIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
comment::{CommentSym, MWComment},
|
comment::{CommentSym, MWComment},
|
||||||
|
@ -97,7 +98,7 @@ where P: AsRef<Path> {
|
||||||
size: section.size(),
|
size: section.size(),
|
||||||
data: section.uncompressed_data()?.to_vec(),
|
data: section.uncompressed_data()?.to_vec(),
|
||||||
align: section.align(),
|
align: section.align(),
|
||||||
elf_index: section.index().0,
|
elf_index: section.index().0 as ObjSectionIndex,
|
||||||
relocations: Default::default(),
|
relocations: Default::default(),
|
||||||
virtual_address: None, // Loaded from section symbol
|
virtual_address: None, // Loaded from section symbol
|
||||||
file_offset: section.file_range().map(|(v, _)| v).unwrap_or_default(),
|
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 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 section_starts = IndexMap::<String, Vec<(u64, String)>>::new();
|
||||||
let mut name_to_index = HashMap::<String, usize>::new(); // for resolving duplicate names
|
let mut name_to_index = HashMap::<String, usize>::new(); // for resolving duplicate names
|
||||||
let mut boundary_state = BoundaryState::LookForFile(Default::default());
|
let mut boundary_state = BoundaryState::LookForFile(Default::default());
|
||||||
|
@ -307,7 +308,7 @@ where P: AsRef<Path> {
|
||||||
symbol_indexes.push(None);
|
symbol_indexes.push(None);
|
||||||
continue;
|
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);
|
let align = mw_comment.as_ref().map(|(_, vec)| vec[symbol.index().0].align);
|
||||||
symbols.push(to_obj_symbol(&obj_file, &symbol, §ion_indexes, align)?);
|
symbols.push(to_obj_symbol(&obj_file, &symbol, §ion_indexes, align)?);
|
||||||
}
|
}
|
||||||
|
@ -401,7 +402,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.reserve_null_section_index();
|
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() {
|
for (_, section) in obj.sections.iter() {
|
||||||
let name = writer.add_section_name(section.name.as_bytes());
|
let name = writer.add_section_name(section.name.as_bytes());
|
||||||
let index = writer.reserve_section_index();
|
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
|
for (((_, section), out_section), rela_name) in
|
||||||
obj.sections.iter().zip(&mut out_sections).zip(&mut rela_names)
|
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
|
// 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)?;
|
mw_comment.to_writer_static(&mut comment_data, Endian::Big)?;
|
||||||
// Null symbol
|
// Null symbol
|
||||||
CommentSym { align: 0, vis_flags: 0, active_flags: 0 }
|
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
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut out_symbols: Vec<OutSymbol> = Vec::with_capacity(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()];
|
let mut symbol_map = vec![None; obj.symbols.count() as usize];
|
||||||
let mut section_symbol_offset = 0;
|
let mut section_symbol_offset = 0;
|
||||||
let mut num_local = 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
|
// Add section symbols for relocatable objects
|
||||||
if obj.kind == ObjKind::Relocatable {
|
if obj.kind == ObjKind::Relocatable {
|
||||||
for (section_index, section) in obj.sections.iter() {
|
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 index = writer.reserve_symbol_index(out_section_index);
|
||||||
let sym = object::write::elf::Sym {
|
let sym = object::write::elf::Sym {
|
||||||
name: None,
|
name: None,
|
||||||
|
@ -561,19 +562,19 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||||
for (symbol_index, symbol) in obj
|
for (symbol_index, symbol) in obj
|
||||||
.symbols
|
.symbols
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
|
||||||
.filter(|&(_, s)| s.flags.is_local())
|
.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 {
|
if obj.kind == ObjKind::Relocatable && symbol.kind == ObjSymbolKind::Section {
|
||||||
// We wrote section symbols above, so skip them here
|
// We wrote section symbols above, so skip them here
|
||||||
let section_index =
|
let section_index =
|
||||||
symbol.section.ok_or_else(|| anyhow!("section symbol without 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;
|
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 section_index = section.map(|s| s.index);
|
||||||
let index = writer.reserve_symbol_index(section_index);
|
let index = writer.reserve_symbol_index(section_index);
|
||||||
let name_index = if symbol.name.is_empty() {
|
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();
|
num_local = writer.symbol_count();
|
||||||
}
|
}
|
||||||
out_symbols.push(OutSymbol { index, sym });
|
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 {
|
if let Some((comment_data, _)) = &mut comment_data {
|
||||||
CommentSym::from(symbol, export_all).to_writer_static(comment_data, Endian::Big)?;
|
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();
|
writer.reserve_file_header();
|
||||||
|
|
||||||
if obj.kind == ObjKind::Executable {
|
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) {
|
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);
|
ensure!(writer.len() == out_section.rela_offset);
|
||||||
for (addr, reloc) in section.relocations.iter() {
|
for (addr, reloc) in section.relocations.iter() {
|
||||||
let (r_offset, r_type) = reloc.to_elf(addr);
|
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"))?;
|
.ok_or_else(|| anyhow!("Relocation against stripped symbol"))?;
|
||||||
writer.write_relocation(true, &Rel { r_offset, r_sym, r_type, r_addend: reloc.addend });
|
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(),
|
name: name.to_string(),
|
||||||
demangled_name: demangle(name, &Default::default()),
|
demangled_name: demangle(name, &Default::default()),
|
||||||
address: symbol.address(),
|
address: symbol.address(),
|
||||||
section: section_idx,
|
section: section_idx.map(|s| s as ObjSectionIndex),
|
||||||
size: symbol.size(),
|
size: symbol.size(),
|
||||||
size_known: true,
|
size_known: true,
|
||||||
flags,
|
flags,
|
||||||
|
@ -927,7 +928,7 @@ pub fn to_obj_reloc_kind(flags: RelocationFlags) -> Result<ObjRelocKind> {
|
||||||
|
|
||||||
fn to_obj_reloc(
|
fn to_obj_reloc(
|
||||||
obj_file: &object::File<'_>,
|
obj_file: &object::File<'_>,
|
||||||
symbol_indexes: &[Option<usize>],
|
symbol_indexes: &[Option<ObjSymbolIndex>],
|
||||||
section_data: &[u8],
|
section_data: &[u8],
|
||||||
address: u64,
|
address: u64,
|
||||||
reloc: Relocation,
|
reloc: Relocation,
|
||||||
|
|
|
@ -37,7 +37,7 @@ pub fn generate_ldscript(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut force_active = force_active.to_vec();
|
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() {
|
if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
|
||||||
force_active.push(symbol.name.clone());
|
force_active.push(symbol.name.clone());
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ pub fn generate_ldscript_partial(
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut force_active = force_active.to_vec();
|
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() {
|
if symbol.flags.is_exported() && symbol.flags.is_global() && !symbol.flags.is_no_write() {
|
||||||
force_active.push(symbol.name.clone());
|
force_active.push(symbol.name.clone());
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
||||||
obj::{
|
obj::{
|
||||||
section_kind_for_section, ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind,
|
section_kind_for_section, ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind,
|
||||||
ObjSections, ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
ObjSections, ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
||||||
ObjSymbols, ObjUnit,
|
ObjSymbols, ObjUnit, SectionIndex,
|
||||||
},
|
},
|
||||||
util::nested::NestedVec,
|
util::nested::NestedVec,
|
||||||
vfs::open_file,
|
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
|
&& (s.address + s.size) <= (section.address + section.size) as u32
|
||||||
})
|
})
|
||||||
} else {
|
} 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 let Some(info) = opt {
|
||||||
if section.section_known && section.name != info.name {
|
if section.section_known && section.name != info.name {
|
||||||
|
@ -814,7 +814,7 @@ pub fn apply_map(mut result: MapInfo, obj: &mut ObjInfo) -> Result<()> {
|
||||||
".data"
|
".data"
|
||||||
}
|
}
|
||||||
} else if let Some(section_name) =
|
} else if let Some(section_name) =
|
||||||
DEFAULT_REL_SECTIONS.get(section.elf_index)
|
DEFAULT_REL_SECTIONS.get(section.elf_index as usize)
|
||||||
{
|
{
|
||||||
section_name
|
section_name
|
||||||
} else {
|
} else {
|
||||||
|
@ -1014,7 +1014,7 @@ pub fn create_obj(result: &MapInfo) -> Result<ObjInfo> {
|
||||||
fn add_symbol(
|
fn add_symbol(
|
||||||
obj: &mut ObjInfo,
|
obj: &mut ObjInfo,
|
||||||
symbol_entry: &SymbolEntry,
|
symbol_entry: &SymbolEntry,
|
||||||
section: Option<usize>,
|
section: Option<SectionIndex>,
|
||||||
ignore_alignment: bool,
|
ignore_alignment: bool,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let demangled_name = demangle(&symbol_entry.name, &DemangleOptions::default());
|
let demangled_name = demangle(&symbol_entry.name, &DemangleOptions::default());
|
||||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
||||||
array_ref_mut,
|
array_ref_mut,
|
||||||
obj::{
|
obj::{
|
||||||
ObjArchitecture, ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
|
ObjArchitecture, ObjInfo, ObjKind, ObjRelocKind, ObjSection, ObjSectionKind, ObjSymbol,
|
||||||
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind,
|
ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, SectionIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
align_up,
|
align_up,
|
||||||
|
@ -418,7 +418,7 @@ where R: Read + Seek + ?Sized {
|
||||||
_ => None, // determined later
|
_ => None, // determined later
|
||||||
}
|
}
|
||||||
.unwrap_or_default() as u64,
|
.unwrap_or_default() as u64,
|
||||||
elf_index: idx,
|
elf_index: idx as SectionIndex,
|
||||||
relocations: Default::default(),
|
relocations: Default::default(),
|
||||||
virtual_address: None, // TODO option to set?
|
virtual_address: None, // TODO option to set?
|
||||||
file_offset: offset as u64,
|
file_offset: offset as u64,
|
||||||
|
@ -440,7 +440,7 @@ where R: Read + Seek + ?Sized {
|
||||||
let (section_index, _) = sections
|
let (section_index, _) = sections
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.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}"))?;
|
.ok_or_else(|| anyhow!("Failed to locate {name} section {rel_section_idx}"))?;
|
||||||
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
|
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
|
||||||
let mut flags = ObjSymbolFlagSet(ObjSymbolFlags::Global.into());
|
let mut flags = ObjSymbolFlagSet(ObjSymbolFlags::Global.into());
|
||||||
|
@ -450,7 +450,7 @@ where R: Read + Seek + ?Sized {
|
||||||
symbols.push(ObjSymbol {
|
symbols.push(ObjSymbol {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
address: offset as u64,
|
address: offset as u64,
|
||||||
section: Some(section_index),
|
section: Some(section_index as SectionIndex),
|
||||||
flags,
|
flags,
|
||||||
kind: ObjSymbolKind::Function,
|
kind: ObjSymbolKind::Function,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|
|
@ -9,7 +9,7 @@ use cwdemangle::{demangle, DemangleOptions};
|
||||||
use crate::{
|
use crate::{
|
||||||
obj::{
|
obj::{
|
||||||
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
|
ObjArchitecture, ObjInfo, ObjKind, ObjSection, ObjSectionKind, ObjSymbol, ObjSymbolFlagSet,
|
||||||
ObjSymbolFlags, ObjSymbolKind,
|
ObjSymbolFlags, ObjSymbolKind, SectionIndex,
|
||||||
},
|
},
|
||||||
util::{
|
util::{
|
||||||
file::{read_c_string, read_string},
|
file::{read_c_string, read_string},
|
||||||
|
@ -452,7 +452,7 @@ where R: Read + Seek + ?Sized {
|
||||||
size: size as u64,
|
size: size as u64,
|
||||||
data,
|
data,
|
||||||
align: 0,
|
align: 0,
|
||||||
elf_index: idx as usize,
|
elf_index: idx as SectionIndex,
|
||||||
relocations: Default::default(),
|
relocations: Default::default(),
|
||||||
virtual_address: None, // TODO option to set?
|
virtual_address: None, // TODO option to set?
|
||||||
file_offset: offset as u64,
|
file_offset: offset as u64,
|
||||||
|
@ -476,13 +476,13 @@ where R: Read + Seek + ?Sized {
|
||||||
let (section_index, _) = sections
|
let (section_index, _) = sections
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.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}"))?;
|
.ok_or_else(|| anyhow!("Failed to locate {name} section {rel_section_idx}"))?;
|
||||||
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
|
log::debug!("Adding {name} section {rel_section_idx} offset {offset:#X}");
|
||||||
symbols.push(ObjSymbol {
|
symbols.push(ObjSymbol {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
address: offset as u64,
|
address: offset as u64,
|
||||||
section: Some(section_index),
|
section: Some(section_index as SectionIndex),
|
||||||
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
|
flags: ObjSymbolFlagSet(ObjSymbolFlags::Global.into()),
|
||||||
kind: ObjSymbolKind::Function,
|
kind: ObjSymbolKind::Function,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
@ -526,7 +526,7 @@ where R: Read + Seek + ?Sized {
|
||||||
let section = sections
|
let section = sections
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.find(|&(_, section)| section.elf_index == symbol.section_index as usize)
|
.find(|&(_, section)| section.elf_index == symbol.section_index as SectionIndex)
|
||||||
.map(|(idx, _)| idx)
|
.map(|(idx, _)| idx)
|
||||||
// HACK: selfiles won't have any sections
|
// HACK: selfiles won't have any sections
|
||||||
.unwrap_or(symbol.section_index as usize);
|
.unwrap_or(symbol.section_index as usize);
|
||||||
|
@ -541,7 +541,7 @@ where R: Read + Seek + ?Sized {
|
||||||
name,
|
name,
|
||||||
demangled_name,
|
demangled_name,
|
||||||
address: symbol.offset as u64,
|
address: symbol.offset as u64,
|
||||||
section: Some(section),
|
section: Some(section as SectionIndex),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use crate::{
|
||||||
array_ref,
|
array_ref,
|
||||||
obj::{
|
obj::{
|
||||||
ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSymbol, ObjSymbolFlagSet,
|
ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSymbol, ObjSymbolFlagSet,
|
||||||
ObjSymbolKind,
|
ObjSymbolKind, SectionIndex, SymbolIndex,
|
||||||
},
|
},
|
||||||
util::elf::process_elf,
|
util::elf::process_elf,
|
||||||
};
|
};
|
||||||
|
@ -36,13 +36,13 @@ pub struct OutSymbol {
|
||||||
pub struct OutReloc {
|
pub struct OutReloc {
|
||||||
pub offset: u32,
|
pub offset: u32,
|
||||||
pub kind: ObjRelocKind,
|
pub kind: ObjRelocKind,
|
||||||
pub symbol: usize,
|
pub symbol: u32,
|
||||||
pub addend: i32,
|
pub addend: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Hash, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct FunctionSignature {
|
pub struct FunctionSignature {
|
||||||
pub symbol: usize,
|
pub symbol: u32,
|
||||||
pub hash: String,
|
pub hash: String,
|
||||||
pub signature: String,
|
pub signature: String,
|
||||||
pub symbols: Vec<OutSymbol>,
|
pub symbols: Vec<OutSymbol>,
|
||||||
|
@ -92,12 +92,12 @@ pub fn check_signatures(
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
for signature in signatures {
|
for signature in signatures {
|
||||||
if name.is_none() {
|
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)? {
|
if check_signature(data, signature)? {
|
||||||
log::debug!(
|
log::debug!(
|
||||||
"Found {} @ {:#010X} (hash {})",
|
"Found {} @ {:#010X} (hash {})",
|
||||||
signature.symbols[signature.symbol].name,
|
signature.symbols[signature.symbol as usize].name,
|
||||||
addr,
|
addr,
|
||||||
signature.hash
|
signature.hash
|
||||||
);
|
);
|
||||||
|
@ -114,9 +114,9 @@ pub fn apply_symbol(
|
||||||
obj: &mut ObjInfo,
|
obj: &mut ObjInfo,
|
||||||
target: SectionAddress,
|
target: SectionAddress,
|
||||||
sig_symbol: &OutSymbol,
|
sig_symbol: &OutSymbol,
|
||||||
) -> Result<usize> {
|
) -> Result<SymbolIndex> {
|
||||||
let mut target_section_index =
|
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 {
|
if let Some(target_section_index) = target_section_index {
|
||||||
let target_section = &mut obj.sections[target_section_index];
|
let target_section = &mut obj.sections[target_section_index];
|
||||||
if !target_section.section_known {
|
if !target_section.section_known {
|
||||||
|
@ -154,7 +154,7 @@ pub fn apply_signature(
|
||||||
addr: SectionAddress,
|
addr: SectionAddress,
|
||||||
signature: &FunctionSignature,
|
signature: &FunctionSignature,
|
||||||
) -> Result<()> {
|
) -> 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 symbol_idx = apply_symbol(obj, addr, in_symbol)?;
|
||||||
let mut tracker = Tracker::new(obj);
|
let mut tracker = Tracker::new(obj);
|
||||||
for reloc in &signature.relocations {
|
for reloc in &signature.relocations {
|
||||||
|
@ -185,7 +185,7 @@ pub fn apply_signature(
|
||||||
}
|
}
|
||||||
_ => bail!("Relocation mismatch: {:?} != {:?}", reloc, sig_reloc.kind),
|
_ => 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);
|
// log::info!("Processing relocation {:#010X} {:?} -> {:#010X} {:?}", reloc_addr, reloc, target, sig_symbol);
|
||||||
let target_symbol_idx = apply_symbol(obj, target, sig_symbol)?;
|
let target_symbol_idx = apply_symbol(obj, target, sig_symbol)?;
|
||||||
let obj_reloc = ObjReloc {
|
let obj_reloc = ObjReloc {
|
||||||
|
@ -200,7 +200,7 @@ pub fn apply_signature(
|
||||||
for reloc in &signature.relocations {
|
for reloc in &signature.relocations {
|
||||||
let addr = addr + reloc.offset;
|
let addr = addr + reloc.offset;
|
||||||
if !tracker.relocations.contains_key(&addr) {
|
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);
|
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> {
|
where P: AsRef<Path> {
|
||||||
let mut out_symbols: Vec<OutSymbol> = Vec::new();
|
let mut out_symbols: Vec<OutSymbol> = Vec::new();
|
||||||
let mut out_relocs: Vec<OutReloc> = 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)?;
|
let mut obj = process_elf(path)?;
|
||||||
if obj.kind == ObjKind::Executable
|
if obj.kind == ObjKind::Executable
|
||||||
|
@ -312,7 +312,7 @@ where P: AsRef<Path> {
|
||||||
let symbol_idx = match symbol_map.entry(reloc.target_symbol) {
|
let symbol_idx = match symbol_map.entry(reloc.target_symbol) {
|
||||||
btree_map::Entry::Vacant(e) => {
|
btree_map::Entry::Vacant(e) => {
|
||||||
let target = &obj.symbols[reloc.target_symbol];
|
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);
|
e.insert(symbol_idx);
|
||||||
out_symbols.push(OutSymbol {
|
out_symbols.push(OutSymbol {
|
||||||
kind: target.kind,
|
kind: target.kind,
|
||||||
|
|
|
@ -15,7 +15,7 @@ use crate::{
|
||||||
obj::{
|
obj::{
|
||||||
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocations, ObjSection, ObjSectionKind,
|
ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocations, ObjSection, ObjSectionKind,
|
||||||
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope,
|
ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjSymbolScope,
|
||||||
ObjUnit,
|
ObjUnit, SectionIndex, SymbolIndex,
|
||||||
},
|
},
|
||||||
util::{align_up, comment::MWComment},
|
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.
|
/// 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<()> {
|
fn update_common_splits(obj: &mut ObjInfo, common_start: Option<u32>) -> Result<()> {
|
||||||
let Some((bss_section_index, common_bss_start)) = (match common_start {
|
let Some(common_bss_start) = (match common_start {
|
||||||
Some(addr) => Some((
|
Some(addr) => Some(SectionAddress::new(
|
||||||
obj.sections.by_name(".bss")?.ok_or_else(|| anyhow!("Failed to find .bss section"))?.0,
|
obj.sections.by_name(".bss")?.ok_or_else(|| anyhow!("Failed to find .bss section"))?.0,
|
||||||
addr,
|
addr,
|
||||||
)),
|
)),
|
||||||
|
@ -454,8 +454,8 @@ fn update_common_splits(obj: &mut ObjInfo, common_start: Option<u32>) -> Result<
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
log::debug!("Found common BSS start at {:#010X}", common_bss_start);
|
log::debug!("Found common BSS start at {:#010X}", common_bss_start);
|
||||||
let bss_section = &mut obj.sections[bss_section_index];
|
let bss_section = &mut obj.sections[common_bss_start.section];
|
||||||
for (addr, split) in bss_section.splits.for_range_mut(common_bss_start..) {
|
for (addr, split) in bss_section.splits.for_range_mut(common_bss_start.address..) {
|
||||||
if !split.common {
|
if !split.common {
|
||||||
split.common = true;
|
split.common = true;
|
||||||
log::debug!("Added common flag to split {} at {:#010X}", split.unit, addr);
|
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();
|
.peekable();
|
||||||
while let Some((_, symbol)) = iter.next() {
|
while let Some((_, symbol)) = iter.next() {
|
||||||
// Common BSS is allowed to have gaps and overlaps to accurately match the common BSS inflation bug
|
// 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
|
if matches!(common_bss, Some(addr) if
|
||||||
section_index == idx && symbol.address as u32 >= addr)
|
section_index == addr.section && symbol.address as u32 >= addr.address)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -933,11 +933,11 @@ fn resolve_link_order(obj: &ObjInfo) -> Result<Vec<ObjUnit>> {
|
||||||
#[instrument(level = "debug", skip(obj))]
|
#[instrument(level = "debug", skip(obj))]
|
||||||
pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo>> {
|
pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo>> {
|
||||||
let mut objects: Vec<ObjInfo> = vec![];
|
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();
|
let mut name_to_obj: HashMap<String, usize> = HashMap::new();
|
||||||
for unit in &obj.link_order {
|
for unit in &obj.link_order {
|
||||||
name_to_obj.insert(unit.name.clone(), objects.len());
|
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(
|
let mut split_obj = ObjInfo::new(
|
||||||
ObjKind::Relocatable,
|
ObjKind::Relocatable,
|
||||||
ObjArchitecture::PowerPc,
|
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)
|
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?
|
continue; // should never happen?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,7 +1092,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
|
||||||
continue;
|
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(),
|
name: symbol.name.clone(),
|
||||||
demangled_name: symbol.demangled_name.clone(),
|
demangled_name: symbol.demangled_name.clone(),
|
||||||
address: if split.common {
|
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,
|
data_kind: symbol.data_kind,
|
||||||
name_hash: symbol.name_hash,
|
name_hash: symbol.name_hash,
|
||||||
demangled_name_hash: symbol.demangled_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
|
// 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];
|
let symbol_idxs = &mut object_symbols[obj_idx];
|
||||||
for (_section_index, section) in out_obj.sections.iter_mut() {
|
for (_section_index, section) in out_obj.sections.iter_mut() {
|
||||||
for (reloc_address, reloc) in section.relocations.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) => {
|
Some(out_sym_idx) => {
|
||||||
reloc.target_symbol = 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));
|
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 {
|
out_obj.symbols.add_direct(ObjSymbol {
|
||||||
name: target_sym.name.clone(),
|
name: target_sym.name.clone(),
|
||||||
demangled_name: target_sym.demangled_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
|
// Upgrade local symbols to global if necessary
|
||||||
for (obj, symbol_map) in objects.iter_mut().zip(&object_symbols) {
|
for (obj, symbol_map) in objects.iter_mut().zip(&object_symbols) {
|
||||||
for (globalize_idx, new_name) in &globalize_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();
|
let mut symbol = obj.symbols[symbol_idx].clone();
|
||||||
symbol.name.clone_from(new_name);
|
symbol.name.clone_from(new_name);
|
||||||
if symbol.flags.is_local() {
|
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
|
// Extern linker generated symbols
|
||||||
for obj in &mut objects {
|
for obj in &mut objects {
|
||||||
let mut replace_symbols = vec![];
|
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() {
|
if is_linker_generated_label(&symbol.name) && symbol.section.is_some() {
|
||||||
log::debug!("Externing {:?} in {}", symbol, obj.name);
|
log::debug!("Externing {:?} in {}", symbol, obj.name);
|
||||||
replace_symbols.push((symbol_idx, ObjSymbol {
|
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
|
/// 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
|
let section = obj
|
||||||
.sections
|
.sections
|
||||||
.get(section_index)
|
.get(section_index)
|
||||||
|
|
Loading…
Reference in New Issue