dwarf dump: More register names, fix padding handling

This commit is contained in:
Luke Street 2023-08-02 18:29:03 -04:00
parent 08663e8c3e
commit 6b81faa5e1
2 changed files with 56 additions and 21 deletions

View File

@ -169,13 +169,6 @@ fn dump_debug_section<W: Write>(
TagKind::LocalVariable => {} TagKind::LocalVariable => {}
_ => continue, _ => continue,
} }
let address = if let Some(location) =
tag.block_attribute(AttributeKind::Location)
{
process_variable_location(location)?
} else {
"[unknown]".to_string()
};
let type_attr = tag.type_attribute().ok_or_else(|| { let type_attr = tag.type_attribute().ok_or_else(|| {
anyhow!("LocalVariable without type attr") anyhow!("LocalVariable without type attr")
})?; })?;
@ -184,11 +177,19 @@ fn dump_debug_section<W: Write>(
let name = tag let name = tag
.string_attribute(AttributeKind::Name) .string_attribute(AttributeKind::Name)
.ok_or_else(|| anyhow!("LocalVariable without name"))?; .ok_or_else(|| anyhow!("LocalVariable without name"))?;
writeln!( write!(w, "\t{} {}{};", ts.prefix, name, ts.suffix)?;
w, if let Some(location) =
"\t{} {}{}; // {}", tag.block_attribute(AttributeKind::Location)
ts.prefix, name, ts.suffix, address {
)?; if !location.is_empty() {
write!(
w,
" // {}",
process_variable_location(location)?
)?;
}
}
writeln!(w)?;
} }
writeln!(w, "}}")?; writeln!(w, "}}")?;
} }

View File

@ -10,6 +10,8 @@ use anyhow::{anyhow, bail, ensure, Context, Result};
use byteorder::{BigEndian, ReadBytesExt}; use byteorder::{BigEndian, ReadBytesExt};
use num_enum::{IntoPrimitive, TryFromPrimitive}; use num_enum::{IntoPrimitive, TryFromPrimitive};
use crate::array_ref;
#[derive(Debug, Eq, PartialEq, Copy, Clone, IntoPrimitive, TryFromPrimitive)] #[derive(Debug, Eq, PartialEq, Copy, Clone, IntoPrimitive, TryFromPrimitive)]
#[repr(u16)] #[repr(u16)]
pub enum TagKind { pub enum TagKind {
@ -413,6 +415,7 @@ fn read_tag<R: BufRead + Seek>(reader: &mut R) -> Result<Tag> {
let position = reader.stream_position()?; let position = reader.stream_position()?;
let size = reader.read_u32::<BigEndian>()?; let size = reader.read_u32::<BigEndian>()?;
if size < 8 { if size < 8 {
// Null entry
if size > 4 { if size > 4 {
reader.seek(SeekFrom::Current(size as i64 - 4))?; reader.seek(SeekFrom::Current(size as i64 - 4))?;
} }
@ -422,8 +425,13 @@ fn read_tag<R: BufRead + Seek>(reader: &mut R) -> Result<Tag> {
let tag = let tag =
TagKind::try_from(reader.read_u16::<BigEndian>()?).context("Unknown DWARF tag type")?; TagKind::try_from(reader.read_u16::<BigEndian>()?).context("Unknown DWARF tag type")?;
let mut attributes = Vec::new(); let mut attributes = Vec::new();
while reader.stream_position()? < position + size as u64 { if tag == TagKind::Padding {
attributes.push(read_attribute(reader)?); reader.seek(SeekFrom::Start(position + size as u64))?; // Skip padding
} else {
while reader.stream_position()? < position + size as u64 {
let attribute = read_attribute(reader)?;
attributes.push(attribute);
}
} }
Ok(Tag { key: position as u32, kind: tag, attributes }) Ok(Tag { key: position as u32, kind: tag, attributes })
} }
@ -848,7 +856,7 @@ pub fn fund_type_string(ft: FundType) -> Result<&'static str> {
pub fn process_offset(block: &[u8]) -> Result<u32> { pub fn process_offset(block: &[u8]) -> Result<u32> {
if block.len() == 6 && block[0] == LocationOp::Const as u8 && block[5] == LocationOp::Add as u8 if block.len() == 6 && block[0] == LocationOp::Const as u8 && block[5] == LocationOp::Add as u8
{ {
Ok(u32::from_be_bytes(block[1..5].try_into()?)) Ok(u32::from_be_bytes(*array_ref!(block, 1, 4)))
} else { } else {
Err(anyhow!("Unhandled location data, expected offset")) Err(anyhow!("Unhandled location data, expected offset"))
} }
@ -856,25 +864,51 @@ pub fn process_offset(block: &[u8]) -> Result<u32> {
pub fn process_address(block: &[u8]) -> Result<u32> { pub fn process_address(block: &[u8]) -> Result<u32> {
if block.len() == 5 && block[0] == LocationOp::Address as u8 { if block.len() == 5 && block[0] == LocationOp::Address as u8 {
Ok(u32::from_be_bytes(block[1..].try_into()?)) Ok(u32::from_be_bytes(*array_ref!(block, 1, 4)))
} else { } else {
Err(anyhow!("Unhandled location data, expected address")) Err(anyhow!("Unhandled location data, expected address"))
} }
} }
pub const REGISTER_NAMES: [&str; 109] = [
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", // 0-7
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", // 8-15
"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", // 16-23
"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", // 24-31
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", // 32-39
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", // 40-47
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", // 48-55
"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", // 56-63
"mq", "lr", "ctr", "ap", "cr0", "cr1", "cr2", "cr3", // 64-71
"cr4", "cr5", "cr6", "cr7", "xer", "v0", "v1", "v2", // 72-79
"v3", "v4", "v5", "v6", "v7", "v8", "v9", "v10", // 80-87
"v11", "v12", "v13", "v14", "v15", "v16", "v17", "v18", // 88-95
"v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", // 96-103
"v27", "v28", "v29", "v30", "v31", // 104-108
];
pub const fn register_name(reg: u32) -> &'static str {
if reg < REGISTER_NAMES.len() as u32 {
REGISTER_NAMES[reg as usize]
} else {
"[invalid]"
}
}
pub fn process_variable_location(block: &[u8]) -> Result<String> { pub fn process_variable_location(block: &[u8]) -> Result<String> {
// TODO: float regs
if block.len() == 5 && block[0] == LocationOp::Register as u8 { if block.len() == 5 && block[0] == LocationOp::Register as u8 {
Ok(format!("r{}", u32::from_be_bytes(block[1..].try_into()?))) Ok(register_name(u32::from_be_bytes(*array_ref!(block, 1, 4))).to_string())
} else if block.len() == 5 && block[0] == LocationOp::Address as u8 {
Ok(format!("@ {:#010X}", u32::from_be_bytes(*array_ref!(block, 1, 4))))
} else if block.len() == 11 } else if block.len() == 11
&& block[0] == LocationOp::BaseRegister as u8 && block[0] == LocationOp::BaseRegister as u8
&& block[5] == LocationOp::Const as u8 && block[5] == LocationOp::Const as u8
&& block[10] == LocationOp::Add as u8 && block[10] == LocationOp::Add as u8
{ {
Ok(format!( Ok(format!(
"r{}+{:#X}", "{}+{:#X}",
u32::from_be_bytes(block[1..5].try_into()?), register_name(u32::from_be_bytes(*array_ref!(block, 1, 4))),
u32::from_be_bytes(block[6..10].try_into()?) u32::from_be_bytes(*array_ref!(block, 6, 4))
)) ))
} else { } else {
Err(anyhow!("Unhandled location data {:?}, expected variable loc", block)) Err(anyhow!("Unhandled location data {:?}, expected variable loc", block))