Add support for MwOverlayBranch (#24)
* Add support for MwOverlayBranch * Make clippy happy * cargo fmt
This commit is contained in:
parent
59fe8069f8
commit
6b59c677d4
161
src/cmd/dwarf.rs
161
src/cmd/dwarf.rs
|
@ -15,8 +15,8 @@ use syntect::{
|
||||||
|
|
||||||
use crate::util::{
|
use crate::util::{
|
||||||
dwarf::{
|
dwarf::{
|
||||||
process_cu_tag, process_root_tag, read_debug_section, should_skip_tag, tag_type_string,
|
process_compile_unit, process_cu_tag, process_overlay_branch, read_debug_section,
|
||||||
AttributeKind, TagKind,
|
should_skip_tag, tag_type_string, AttributeKind, TagKind,
|
||||||
},
|
},
|
||||||
file::{buf_writer, map_file},
|
file::{buf_writer, map_file},
|
||||||
};
|
};
|
||||||
|
@ -163,74 +163,109 @@ where
|
||||||
let mut units = Vec::<String>::new();
|
let mut units = Vec::<String>::new();
|
||||||
if let Some((_, mut tag)) = info.tags.first_key_value() {
|
if let Some((_, mut tag)) = info.tags.first_key_value() {
|
||||||
loop {
|
loop {
|
||||||
let unit = process_root_tag(tag)?;
|
match tag.kind {
|
||||||
if units.contains(&unit.name) {
|
TagKind::Padding => {
|
||||||
// log::warn!("Duplicate unit '{}'", unit.name);
|
// TODO
|
||||||
} else {
|
|
||||||
units.push(unit.name.clone());
|
|
||||||
}
|
|
||||||
writeln!(w, "\n/*\n Compile unit: {}", unit.name)?;
|
|
||||||
if let Some(producer) = unit.producer {
|
|
||||||
writeln!(w, " Producer: {}", producer)?;
|
|
||||||
}
|
|
||||||
if let Some(language) = unit.language {
|
|
||||||
writeln!(w, " Language: {}", language)?;
|
|
||||||
}
|
|
||||||
if let (Some(start), Some(end)) = (unit.start_address, unit.end_address) {
|
|
||||||
writeln!(w, " Code range: {:#010X} -> {:#010X}", start, end)?;
|
|
||||||
}
|
|
||||||
writeln!(w, "*/")?;
|
|
||||||
|
|
||||||
let children = tag.children(&info.tags);
|
|
||||||
let mut typedefs = BTreeMap::<u32, Vec<u32>>::new();
|
|
||||||
for child in children {
|
|
||||||
let tag_type = match process_cu_tag(&info, child) {
|
|
||||||
Ok(tag_type) => tag_type,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!(
|
|
||||||
"Failed to process tag {} (unit {}): {}",
|
|
||||||
child.key,
|
|
||||||
unit.name,
|
|
||||||
e
|
|
||||||
);
|
|
||||||
writeln!(
|
|
||||||
w,
|
|
||||||
"// ERROR: Failed to process tag {} ({:?})",
|
|
||||||
child.key, child.kind
|
|
||||||
)?;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if should_skip_tag(&tag_type) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
match tag_type_string(&info, &typedefs, &tag_type) {
|
|
||||||
Ok(s) => writeln!(w, "{}", s)?,
|
|
||||||
Err(e) => {
|
|
||||||
log::error!("Failed to emit tag {} (unit {}): {}", child.key, unit.name, e);
|
|
||||||
writeln!(
|
|
||||||
w,
|
|
||||||
"// ERROR: Failed to emit tag {} ({:?})",
|
|
||||||
child.key, child.kind
|
|
||||||
)?;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
TagKind::MwOverlayBranch => {
|
||||||
|
let branch = process_overlay_branch(tag)?;
|
||||||
|
writeln!(w, "\n/*\n Overlay: {}", branch.name)?;
|
||||||
|
writeln!(w, " Overlay ID: {}", branch.id)?;
|
||||||
|
writeln!(
|
||||||
|
w,
|
||||||
|
" Code range: {:#010X} -> {:#010X}",
|
||||||
|
branch.start_address, branch.end_address
|
||||||
|
)?;
|
||||||
|
|
||||||
if let TagKind::Typedef = child.kind {
|
if let Some(unit_addr) = branch.compile_unit {
|
||||||
// TODO fundamental typedefs?
|
let tag = info
|
||||||
if let Some(ud_type_ref) = child.reference_attribute(AttributeKind::UserDefType)
|
.tags
|
||||||
{
|
.get(&unit_addr)
|
||||||
match typedefs.entry(ud_type_ref) {
|
.ok_or_else(|| anyhow!("Failed to get CompileUnit"))?;
|
||||||
btree_map::Entry::Vacant(e) => {
|
let unit = process_compile_unit(tag)?;
|
||||||
e.insert(vec![child.key]);
|
writeln!(w, " Compile unit: {}", unit.name)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
writeln!(w, "*/")?;
|
||||||
|
}
|
||||||
|
TagKind::CompileUnit => {
|
||||||
|
let unit = process_compile_unit(tag)?;
|
||||||
|
if units.contains(&unit.name) {
|
||||||
|
// log::warn!("Duplicate unit '{}'", unit.name);
|
||||||
|
} else {
|
||||||
|
units.push(unit.name.clone());
|
||||||
|
}
|
||||||
|
writeln!(w, "\n/*\n Compile unit: {}", unit.name)?;
|
||||||
|
if let Some(producer) = unit.producer {
|
||||||
|
writeln!(w, " Producer: {}", producer)?;
|
||||||
|
}
|
||||||
|
if let Some(language) = unit.language {
|
||||||
|
writeln!(w, " Language: {}", language)?;
|
||||||
|
}
|
||||||
|
if let (Some(start), Some(end)) = (unit.start_address, unit.end_address) {
|
||||||
|
writeln!(w, " Code range: {:#010X} -> {:#010X}", start, end)?;
|
||||||
|
}
|
||||||
|
writeln!(w, "*/")?;
|
||||||
|
|
||||||
|
let children = tag.children(&info.tags);
|
||||||
|
let mut typedefs = BTreeMap::<u32, Vec<u32>>::new();
|
||||||
|
for child in children {
|
||||||
|
let tag_type = match process_cu_tag(&info, child) {
|
||||||
|
Ok(tag_type) => tag_type,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"Failed to process tag {} (unit {}): {}",
|
||||||
|
child.key,
|
||||||
|
unit.name,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
writeln!(
|
||||||
|
w,
|
||||||
|
"// ERROR: Failed to process tag {} ({:?})",
|
||||||
|
child.key, child.kind
|
||||||
|
)?;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
btree_map::Entry::Occupied(e) => {
|
};
|
||||||
e.into_mut().push(child.key);
|
if should_skip_tag(&tag_type) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
match tag_type_string(&info, &typedefs, &tag_type) {
|
||||||
|
Ok(s) => writeln!(w, "{}", s)?,
|
||||||
|
Err(e) => {
|
||||||
|
log::error!(
|
||||||
|
"Failed to emit tag {} (unit {}): {}",
|
||||||
|
child.key,
|
||||||
|
unit.name,
|
||||||
|
e
|
||||||
|
);
|
||||||
|
writeln!(
|
||||||
|
w,
|
||||||
|
"// ERROR: Failed to emit tag {} ({:?})",
|
||||||
|
child.key, child.kind
|
||||||
|
)?;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let TagKind::Typedef = child.kind {
|
||||||
|
// TODO fundamental typedefs?
|
||||||
|
if let Some(ud_type_ref) =
|
||||||
|
child.reference_attribute(AttributeKind::UserDefType)
|
||||||
|
{
|
||||||
|
match typedefs.entry(ud_type_ref) {
|
||||||
|
btree_map::Entry::Vacant(e) => {
|
||||||
|
e.insert(vec![child.key]);
|
||||||
|
}
|
||||||
|
btree_map::Entry::Occupied(e) => {
|
||||||
|
e.into_mut().push(child.key);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
kind => bail!("Unhandled root tag type {:?}", kind),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(next) = tag.next_sibling(&info.tags) {
|
if let Some(next) = tag.next_sibling(&info.tags) {
|
||||||
|
|
|
@ -799,6 +799,15 @@ pub struct CompileUnit {
|
||||||
pub end_address: Option<u32>,
|
pub end_address: Option<u32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct OverlayBranch {
|
||||||
|
pub name: String,
|
||||||
|
pub id: u32,
|
||||||
|
pub start_address: u32,
|
||||||
|
pub end_address: u32,
|
||||||
|
pub compile_unit: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
impl UserDefinedType {
|
impl UserDefinedType {
|
||||||
pub fn name(&self) -> Option<String> {
|
pub fn name(&self) -> Option<String> {
|
||||||
match self {
|
match self {
|
||||||
|
@ -2343,7 +2352,7 @@ pub fn process_type(attr: &Attribute, e: Endian) -> Result<Type> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_root_tag(tag: &Tag) -> Result<CompileUnit> {
|
pub fn process_compile_unit(tag: &Tag) -> Result<CompileUnit> {
|
||||||
ensure!(tag.kind == TagKind::CompileUnit, "{:?} is not a CompileUnit tag", tag.kind);
|
ensure!(tag.kind == TagKind::CompileUnit, "{:?} is not a CompileUnit tag", tag.kind);
|
||||||
|
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
|
@ -2374,6 +2383,35 @@ pub fn process_root_tag(tag: &Tag) -> Result<CompileUnit> {
|
||||||
Ok(CompileUnit { name, producer, language, start_address, end_address })
|
Ok(CompileUnit { name, producer, language, start_address, end_address })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn process_overlay_branch(tag: &Tag) -> Result<OverlayBranch> {
|
||||||
|
ensure!(tag.kind == TagKind::MwOverlayBranch, "{:?} is not an OverlayBranch tag", tag.kind);
|
||||||
|
|
||||||
|
let mut name = None;
|
||||||
|
let mut id = None;
|
||||||
|
let mut start_address = None;
|
||||||
|
let mut end_address = None;
|
||||||
|
let mut compile_unit = None;
|
||||||
|
for attr in &tag.attributes {
|
||||||
|
match (attr.kind, &attr.value) {
|
||||||
|
(AttributeKind::Sibling, _) => {}
|
||||||
|
(AttributeKind::Member, AttributeValue::Reference(addr)) => compile_unit = Some(*addr),
|
||||||
|
(AttributeKind::MwOverlayName, AttributeValue::String(s)) => name = Some(s.clone()),
|
||||||
|
(AttributeKind::MwOverlayId, AttributeValue::Data4(value)) => id = Some(*value),
|
||||||
|
(AttributeKind::LowPc, &AttributeValue::Address(addr)) => start_address = Some(addr),
|
||||||
|
(AttributeKind::HighPc, &AttributeValue::Address(addr)) => end_address = Some(addr),
|
||||||
|
_ => bail!("Unhandled OverlayBranch attribute {:?}", attr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let name = name.ok_or_else(|| anyhow!("OverlayBranch without Name: {:?}", tag))?;
|
||||||
|
let id = id.ok_or_else(|| anyhow!("OverlayBranch without Id: {:?}", tag))?;
|
||||||
|
let start_address =
|
||||||
|
start_address.ok_or_else(|| anyhow!("OverlayBranch without LowPc: {:?}", tag))?;
|
||||||
|
let end_address =
|
||||||
|
end_address.ok_or_else(|| anyhow!("OverlayBranch without HighPc: {:?}", tag))?;
|
||||||
|
Ok(OverlayBranch { name, id, start_address, end_address, compile_unit })
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_cu_tag(info: &DwarfInfo, tag: &Tag) -> Result<TagType> {
|
pub fn process_cu_tag(info: &DwarfInfo, tag: &Tag) -> Result<TagType> {
|
||||||
match tag.kind {
|
match tag.kind {
|
||||||
TagKind::Typedef => Ok(TagType::Typedef(process_typedef_tag(info, tag)?)),
|
TagKind::Typedef => Ok(TagType::Typedef(process_typedef_tag(info, tag)?)),
|
||||||
|
|
Loading…
Reference in New Issue