Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/cmd/dol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ fn apply_selfile(obj: &mut ObjInfo, buf: &[u8]) -> Result<()> {
name: symbol.name.clone(),
demangled_name: symbol.demangled_name.clone(),
address: address as u64,
virtual_address: None,
section,
size: existing_symbol.size,
size_known: existing_symbol.size_known,
Expand Down Expand Up @@ -2017,6 +2018,7 @@ fn apply(args: ApplyArgs) -> Result<()> {
name: linked_sym.name.clone(),
demangled_name: linked_sym.demangled_name.clone(),
address: linked_sym.address,
virtual_address: None,
section: Some(orig_section_index),
size: linked_sym.size,
size_known: linked_sym.size_known,
Expand Down
2 changes: 2 additions & 0 deletions src/cmd/rel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,7 @@ fn merge(args: MergeArgs) -> Result<()> {
elf_index: mod_section.elf_index,
relocations: Default::default(),
virtual_address: mod_section.virtual_address,
virtual_address_passed_in: false,
file_offset: mod_section.file_offset,
section_known: mod_section.section_known,
splits: mod_section.splits.clone(),
Expand All @@ -529,6 +530,7 @@ fn merge(args: MergeArgs) -> Result<()> {
name: mod_symbol.name.clone(),
demangled_name: mod_symbol.demangled_name.clone(),
address: mod_symbol.address + offset as u64,
virtual_address: None,
section: Some(section_idx),
size: mod_symbol.size,
size_known: mod_symbol.size_known,
Expand Down
2 changes: 2 additions & 0 deletions src/obj/sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub struct ObjSection {
pub elf_index: SectionIndex,
pub relocations: ObjRelocations,
pub virtual_address: Option<u64>,
// This exists for virtual address support in symbols/splits.txt.
pub virtual_address_passed_in: bool,
pub file_offset: u64,
pub section_known: bool,
pub splits: ObjSplits,
Expand Down
3 changes: 3 additions & 0 deletions src/obj/symbols.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ pub struct ObjSymbol {
pub name: String,
pub demangled_name: Option<String>,
pub address: u64,
pub virtual_address: Option<u64>, // Added for REL virtual address support
pub section: Option<SectionIndex>,
pub size: u64,
pub size_known: bool,
Expand Down Expand Up @@ -297,6 +298,7 @@ impl ObjSymbols {
name: in_symbol.name,
demangled_name: in_symbol.demangled_name,
address: in_symbol.address,
virtual_address: in_symbol.virtual_address,
section: in_symbol.section,
size,
size_known: existing.size_known || in_symbol.size != 0,
Expand All @@ -321,6 +323,7 @@ impl ObjSymbols {
name: in_symbol.name,
demangled_name: in_symbol.demangled_name,
address: in_symbol.address,
virtual_address: in_symbol.virtual_address,
section: in_symbol.section,
size: in_symbol.size,
size_known: in_symbol.size != 0,
Expand Down
1 change: 1 addition & 0 deletions src/util/alf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ impl AlfSymbol {
name,
demangled_name,
address: self.address as u64,
virtual_address: None,
section: Some(self.section as SectionIndex - 1),
size: self.size as u64,
size_known: true,
Expand Down
45 changes: 41 additions & 4 deletions src/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,19 @@ pub fn parse_symbol_line(line: &str, obj: &mut ObjInfo) -> Result<Option<ObjSymb
} else {
bail!("Section {} not found", section_name)
};

// Adjust read in symbol if its section's virtual address was user defined
let section_obj = obj.sections.get(section.unwrap()).unwrap();
let (adjusted_addr, sym_vaddr) = if section_obj.virtual_address_passed_in {
let section_virtual_offset = section_obj.virtual_address.unwrap() as u32;
(addr.saturating_sub(section_virtual_offset), Some(addr as u64))
} else {
(addr, None)
};

let demangled_name = demangle(&name, &DemangleOptions::default());
let mut symbol =
ObjSymbol { name, demangled_name, address: addr as u64, section, ..Default::default() };
ObjSymbol { name, demangled_name, address: adjusted_addr as u64, virtual_address: sym_vaddr, section, ..Default::default() };
// TODO move somewhere common
if symbol.name.starts_with("..") {
symbol.flags.0 |= ObjSymbolFlags::Exported;
Expand Down Expand Up @@ -267,7 +277,7 @@ where W: Write + ?Sized {
if let Some(section) = section {
write!(w, "{}:", section.name)?;
}
write!(w, "{:#010X}; //", symbol.address)?;
write!(w, "{:#010X}; //", symbol.virtual_address.unwrap_or(symbol.address))?;
write!(w, " type:{}", symbol_kind_to_str(symbol.kind))?;
if symbol.size_known && symbol.size > 0 {
write!(w, " size:{:#X}", symbol.size)?;
Expand Down Expand Up @@ -434,6 +444,9 @@ where W: Write + ?Sized {
if section.align > 0 {
write!(w, " align:{}", section.align)?;
}
if section.virtual_address_passed_in {
write!(w, " virtual_address:{:#X}", section.virtual_address.unwrap())?;
}
writeln!(w)?;
}
for unit in obj.link_order.iter().filter(|unit| all || !unit.autogenerated) {
Expand All @@ -455,6 +468,14 @@ where W: Write + ?Sized {
} else {
split_iter.peek().map(|&(_, _, addr, _)| addr).unwrap_or(0)
};

let (addr, end) = if section.virtual_address_passed_in {
let section_virtual_offset = section.virtual_address.unwrap() as u32;
(addr + section_virtual_offset, end + section_virtual_offset)
} else {
(addr, end)
};

write!(w, "\t{:<11} start:{:#010X} end:{:#010X}", section.name, addr, end)?;
if let Some(align) = split.align {
if align != default_section_align(section) as u32 {
Expand Down Expand Up @@ -499,6 +520,7 @@ pub struct SectionDef {
pub name: String,
pub kind: Option<ObjSectionKind>,
pub align: Option<u32>,
pub virtual_address: Option<u32>,
}

enum SplitLine {
Expand Down Expand Up @@ -553,7 +575,7 @@ fn parse_unit_line(captures: Captures) -> Result<SplitLine> {
fn parse_section_line(captures: Captures, state: &SplitState) -> Result<SplitLine> {
if matches!(state, SplitState::Sections(_)) {
let name = &captures["name"];
let mut section = SectionDef { name: name.to_string(), kind: None, align: None };
let mut section = SectionDef { name: name.to_string(), kind: None, align: None, virtual_address: None, };

for attr in captures["attrs"].split(' ').filter(|&s| !s.is_empty()) {
if let Some((attr, value)) = attr.split_once(':') {
Expand All @@ -567,6 +589,9 @@ fn parse_section_line(captures: Captures, state: &SplitState) -> Result<SplitLin
"align" => {
section.align = Some(parse_u32(value)?);
}
"virtual_address" => {
section.virtual_address = Some(parse_u32(value)?);
}
_ => bail!("Unknown section attribute '{attr}'"),
}
} else {
Expand Down Expand Up @@ -665,7 +690,7 @@ where R: BufRead + ?Sized {
(SplitState::None | SplitState::Unit(_), SplitLine::SectionsStart) => {
state = SplitState::Sections(0);
}
(SplitState::Sections(index), SplitLine::Section(SectionDef { name, kind, align })) => {
(SplitState::Sections(index), SplitLine::Section(SectionDef { name, kind, align, virtual_address })) => {
let Some(obj_section) = obj.sections.get_mut(*index) else {
bail!(
"Section out of bounds: {} (index {}), object has {} sections",
Expand All @@ -684,6 +709,10 @@ where R: BufRead + ?Sized {
if let Some(align) = align {
obj_section.align = align as u64;
}
if let Some(virtual_address) = virtual_address {
obj_section.virtual_address = Some(virtual_address as u64);
obj_section.virtual_address_passed_in = true;
}
*index += 1;
}
(
Expand All @@ -710,6 +739,14 @@ where R: BufRead + ?Sized {
}
}?;
let section = obj.sections.get_mut(section_index).unwrap();

// If splits/symbols use virtual addresses, subtract by the section offset to get rel addresses.
let (start, end) = if section.virtual_address_passed_in {
let section_virtual_offset = section.virtual_address.unwrap_or(0) as u32;
(start.saturating_sub(section_virtual_offset), end.saturating_sub(section_virtual_offset))
} else {
(start, end)
};
let section_end = (section.address + section.size) as u32;
ensure!(
section.contains_range(start..end)
Expand Down
6 changes: 6 additions & 0 deletions src/util/dol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(addr as u64),
virtual_address_passed_in: false,
file_offset: file_offset as u64,
section_known: known,
splits: Default::default(),
Expand Down Expand Up @@ -417,6 +418,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(dol_section.address as u64),
virtual_address_passed_in: false,
file_offset: dol_section.file_offset as u64,
section_known: known,
splits: Default::default(),
Expand Down Expand Up @@ -449,6 +451,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(addr as u64),
virtual_address_passed_in: false,
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand All @@ -469,6 +472,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(bss_section.address as u64),
virtual_address_passed_in: false,
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand Down Expand Up @@ -496,6 +500,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(bss_sections[0].0 as u64),
virtual_address_passed_in: false,
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand All @@ -510,6 +515,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: Some(bss_sections[1].0 as u64),
virtual_address_passed_in: false,
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand Down
6 changes: 5 additions & 1 deletion src/util/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ pub fn process_elf(path: &Utf8NativePath) -> Result<ObjInfo> {
elf_index: section.index().0 as ObjSectionIndex,
relocations: Default::default(),
virtual_address: None, // Loaded from section symbol
virtual_address_passed_in: false,
file_offset: section.file_range().map(|(v, _)| v).unwrap_or_default(),
section_known: true,
splits: Default::default(),
Expand Down Expand Up @@ -628,7 +629,10 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
if let Some(virtual_addresses) =
split_meta.as_mut().and_then(|(m, _)| m.virtual_addresses.as_mut())
{
if let Some(section_vaddr) = section.and_then(|s| s.virtual_address) {
if symbol.virtual_address.is_some() {
virtual_addresses.push((symbol.virtual_address.unwrap()).into());
}
else if let Some(section_vaddr) = section.and_then(|s| s.virtual_address) {
virtual_addresses.push(section_vaddr + symbol.address);
} else {
virtual_addresses.push(0);
Expand Down
1 change: 1 addition & 0 deletions src/util/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -917,6 +917,7 @@ pub fn create_obj(result: &MapInfo) -> Result<ObjInfo> {
elf_index: 0,
relocations: Default::default(),
virtual_address: None,
virtual_address_passed_in: false,
file_offset,
section_known: true,
splits: Default::default(),
Expand Down
1 change: 1 addition & 0 deletions src/util/rel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ where R: Read + Seek + ?Sized {
elf_index: idx as SectionIndex,
relocations: Default::default(),
virtual_address: None, // TODO option to set?
virtual_address_passed_in: false,
file_offset: offset as u64,
section_known,
splits: Default::default(),
Expand Down
1 change: 1 addition & 0 deletions src/util/rso.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,7 @@ where R: Read + Seek + ?Sized {
elf_index: idx as SectionIndex,
relocations: Default::default(),
virtual_address: None, // TODO option to set?
virtual_address_passed_in: false,
file_offset: offset as u64,
section_known: false,
splits: Default::default(),
Expand Down
2 changes: 2 additions & 0 deletions src/util/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1163,6 +1163,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
} else {
symbol.address - current_address.address as u64
},
virtual_address: symbol.virtual_address,
section: if split.common { None } else { Some(out_section_idx) },
size: symbol.size,
size_known: symbol.size_known,
Expand Down Expand Up @@ -1203,6 +1204,7 @@ pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo
elf_index: out_section_idx + 1,
relocations: ObjRelocations::new(out_relocations)?,
virtual_address: Some(current_address.address as u64),
virtual_address_passed_in: section.virtual_address_passed_in,
file_offset: section.file_offset
+ (current_address.address as u64 - section.address),
section_known: true,
Expand Down