SN GCC DWARF improvements
Now emits all DWARF tags for Spongebob Squarepants: Creature from the Krusty Krab properly. Resolves #46
This commit is contained in:
parent
61cd72cd11
commit
d63111466b
|
@ -697,7 +697,7 @@ pub struct BitData {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct StructureMember {
|
pub struct StructureMember {
|
||||||
pub name: String,
|
pub name: Option<String>,
|
||||||
pub kind: Type,
|
pub kind: Type,
|
||||||
pub offset: u32,
|
pub offset: u32,
|
||||||
pub bit: Option<BitData>,
|
pub bit: Option<BitData>,
|
||||||
|
@ -732,7 +732,7 @@ pub struct StructureBase {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub base_type: Type,
|
pub base_type: Type,
|
||||||
pub offset: u32,
|
pub offset: u32,
|
||||||
pub visibility: Visibility,
|
pub visibility: Option<Visibility>,
|
||||||
pub virtual_base: bool,
|
pub virtual_base: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -780,17 +780,11 @@ pub struct SubroutineLabel {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct SubroutineBlock {
|
pub struct SubroutineBlock {
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub start_address: u32,
|
pub start_address: Option<u32>,
|
||||||
pub end_address: u32,
|
pub end_address: Option<u32>,
|
||||||
pub variables: Vec<SubroutineVariable>,
|
pub variables: Vec<SubroutineVariable>,
|
||||||
pub blocks: Vec<SubroutineBlock>,
|
pub blocks: Vec<SubroutineBlock>,
|
||||||
}
|
pub inlines: Vec<SubroutineType>,
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct SubroutineInline {
|
|
||||||
pub specification: u32,
|
|
||||||
pub start_address: u32,
|
|
||||||
pub end_address: u32,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
@ -805,10 +799,11 @@ pub struct SubroutineType {
|
||||||
pub member_of: Option<u32>,
|
pub member_of: Option<u32>,
|
||||||
pub variables: Vec<SubroutineVariable>,
|
pub variables: Vec<SubroutineVariable>,
|
||||||
pub inline: bool,
|
pub inline: bool,
|
||||||
|
pub virtual_: bool,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub labels: Vec<SubroutineLabel>,
|
pub labels: Vec<SubroutineLabel>,
|
||||||
pub blocks: Vec<SubroutineBlock>,
|
pub blocks: Vec<SubroutineBlock>,
|
||||||
pub inlines: Vec<SubroutineInline>,
|
pub inlines: Vec<SubroutineType>,
|
||||||
pub start_address: Option<u32>,
|
pub start_address: Option<u32>,
|
||||||
pub end_address: Option<u32>,
|
pub end_address: Option<u32>,
|
||||||
}
|
}
|
||||||
|
@ -1349,6 +1344,9 @@ pub fn subroutine_def_string(
|
||||||
if t.inline {
|
if t.inline {
|
||||||
out.push_str("inline ");
|
out.push_str("inline ");
|
||||||
}
|
}
|
||||||
|
if t.virtual_ {
|
||||||
|
out.push_str("virtual ");
|
||||||
|
}
|
||||||
out.push_str(&rt.prefix);
|
out.push_str(&rt.prefix);
|
||||||
out.push(' ');
|
out.push(' ');
|
||||||
|
|
||||||
|
@ -1461,18 +1459,8 @@ pub fn subroutine_def_string(
|
||||||
if !t.inlines.is_empty() {
|
if !t.inlines.is_empty() {
|
||||||
writeln!(out, "\n // Inlines")?;
|
writeln!(out, "\n // Inlines")?;
|
||||||
for inline in &t.inlines {
|
for inline in &t.inlines {
|
||||||
let spec_tag = info
|
let inline_str = subroutine_def_string(info, typedefs, inline, is_erased)?;
|
||||||
.tags
|
out.push_str(&indent_all_by(4, inline_str));
|
||||||
.get(&inline.specification)
|
|
||||||
.ok_or_else(|| anyhow!("Failed to locate inline tag {}", inline.specification))?;
|
|
||||||
let subroutine = process_subroutine_tag(info, spec_tag)?;
|
|
||||||
writeln!(
|
|
||||||
out,
|
|
||||||
" // -> {} ({:#X} - {:#X})",
|
|
||||||
subroutine_type_string(info, typedefs, &subroutine)?,
|
|
||||||
inline.start_address,
|
|
||||||
inline.end_address,
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1491,7 +1479,10 @@ fn subroutine_block_string(
|
||||||
} else {
|
} else {
|
||||||
out.push_str("/* anonymous block */ ");
|
out.push_str("/* anonymous block */ ");
|
||||||
}
|
}
|
||||||
writeln!(out, "{{\n // Range: {:#X} -> {:#X}", block.start_address, block.end_address)?;
|
out.push_str("{\n");
|
||||||
|
if let (Some(start), Some(end)) = (block.start_address, block.end_address) {
|
||||||
|
writeln!(out, " // Range: {:#X} -> {:#X}", start, end)?;
|
||||||
|
}
|
||||||
let mut var_out = String::new();
|
let mut var_out = String::new();
|
||||||
for variable in &block.variables {
|
for variable in &block.variables {
|
||||||
let ts = type_string(info, typedefs, &variable.kind, true)?;
|
let ts = type_string(info, typedefs, &variable.kind, true)?;
|
||||||
|
@ -1508,6 +1499,13 @@ fn subroutine_block_string(
|
||||||
writeln!(var_out)?;
|
writeln!(var_out)?;
|
||||||
}
|
}
|
||||||
write!(out, "{}", indent_all_by(4, var_out))?;
|
write!(out, "{}", indent_all_by(4, var_out))?;
|
||||||
|
if !block.inlines.is_empty() {
|
||||||
|
writeln!(out, "\n // Inlines")?;
|
||||||
|
for inline in &block.inlines {
|
||||||
|
let inline_str = subroutine_def_string(info, typedefs, inline, false)?;
|
||||||
|
out.push_str(&indent_all_by(4, inline_str));
|
||||||
|
}
|
||||||
|
}
|
||||||
for block in &block.blocks {
|
for block in &block.blocks {
|
||||||
let block_str = subroutine_block_string(info, typedefs, block)?;
|
let block_str = subroutine_block_string(info, typedefs, block)?;
|
||||||
out.push_str(&indent_all_by(4, block_str));
|
out.push_str(&indent_all_by(4, block_str));
|
||||||
|
@ -1649,9 +1647,10 @@ pub fn struct_def_string(
|
||||||
out.push_str(", ");
|
out.push_str(", ");
|
||||||
}
|
}
|
||||||
match base.visibility {
|
match base.visibility {
|
||||||
Visibility::Private => out.push_str("private "),
|
Some(Visibility::Private) => out.push_str("private "),
|
||||||
Visibility::Protected => out.push_str("protected "),
|
Some(Visibility::Protected) => out.push_str("protected "),
|
||||||
Visibility::Public => out.push_str("public "),
|
Some(Visibility::Public) => out.push_str("public "),
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
if base.virtual_base {
|
if base.virtual_base {
|
||||||
out.push_str("virtual ");
|
out.push_str("virtual ");
|
||||||
|
@ -1720,7 +1719,11 @@ pub fn struct_def_string(
|
||||||
}
|
}
|
||||||
let mut var_out = String::new();
|
let mut var_out = String::new();
|
||||||
let ts = type_string(info, typedefs, &member.kind, true)?;
|
let ts = type_string(info, typedefs, &member.kind, true)?;
|
||||||
write!(var_out, "{} {}{}", ts.prefix, member.name, ts.suffix)?;
|
if let Some(name) = &member.name {
|
||||||
|
write!(var_out, "{} {}{}", ts.prefix, name, ts.suffix)?;
|
||||||
|
} else {
|
||||||
|
write!(var_out, "{}{}", ts.prefix, ts.suffix)?;
|
||||||
|
}
|
||||||
if let Some(bit) = &member.bit {
|
if let Some(bit) = &member.bit {
|
||||||
write!(var_out, " : {}", bit.bit_size)?;
|
write!(var_out, " : {}", bit.bit_size)?;
|
||||||
}
|
}
|
||||||
|
@ -1774,7 +1777,11 @@ pub fn union_def_string(info: &DwarfInfo, typedefs: &TypedefMap, t: &UnionType)
|
||||||
let mut var_out = String::new();
|
let mut var_out = String::new();
|
||||||
for member in t.members.iter() {
|
for member in t.members.iter() {
|
||||||
let ts = type_string(info, typedefs, &member.kind, true)?;
|
let ts = type_string(info, typedefs, &member.kind, true)?;
|
||||||
write!(var_out, "{} {}{};", ts.prefix, member.name, ts.suffix)?;
|
if let Some(name) = &member.name {
|
||||||
|
write!(var_out, "{} {}{};", ts.prefix, name, ts.suffix)?;
|
||||||
|
} else {
|
||||||
|
write!(var_out, "{}{};", ts.prefix, ts.suffix)?;
|
||||||
|
}
|
||||||
let size = if let Some(size) = member.byte_size { size } else { member.kind.size(info)? };
|
let size = if let Some(size) = member.byte_size { size } else { member.kind.size(info)? };
|
||||||
write!(var_out, " // offset {:#X}, size {:#X}", member.offset, size)?;
|
write!(var_out, " // offset {:#X}, size {:#X}", member.offset, size)?;
|
||||||
writeln!(var_out)?;
|
writeln!(var_out)?;
|
||||||
|
@ -1888,8 +1895,6 @@ fn process_inheritance_tag(info: &DwarfInfo, tag: &Tag) -> Result<StructureBase>
|
||||||
|
|
||||||
let base_type = base_type.ok_or_else(|| anyhow!("Inheritance without base type: {:?}", tag))?;
|
let base_type = base_type.ok_or_else(|| anyhow!("Inheritance without base type: {:?}", tag))?;
|
||||||
let offset = offset.ok_or_else(|| anyhow!("Inheritance without offset: {:?}", tag))?;
|
let offset = offset.ok_or_else(|| anyhow!("Inheritance without offset: {:?}", tag))?;
|
||||||
let visibility =
|
|
||||||
visibility.ok_or_else(|| anyhow!("Inheritance without visibility: {:?}", tag))?;
|
|
||||||
Ok(StructureBase { name, base_type, offset, visibility, virtual_base })
|
Ok(StructureBase { name, base_type, offset, visibility, virtual_base })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1936,8 +1941,7 @@ fn process_structure_member_tag(info: &DwarfInfo, tag: &Tag) -> Result<Structure
|
||||||
bail!("Unhandled Member child {:?}", child.kind);
|
bail!("Unhandled Member child {:?}", child.kind);
|
||||||
}
|
}
|
||||||
|
|
||||||
let name = name.ok_or_else(|| anyhow!("Member without name: {:?}", tag))?;
|
let kind = member_type.ok_or_else(|| anyhow!("Member without type: {:?}", tag))?;
|
||||||
let member_type = member_type.ok_or_else(|| anyhow!("Member without type: {:?}", tag))?;
|
|
||||||
let offset = offset.ok_or_else(|| anyhow!("Member without offset: {:?}", tag))?;
|
let offset = offset.ok_or_else(|| anyhow!("Member without offset: {:?}", tag))?;
|
||||||
let bit = match (bit_size, bit_offset) {
|
let bit = match (bit_size, bit_offset) {
|
||||||
(Some(bit_size), Some(bit_offset)) => Some(BitData { bit_size, bit_offset }),
|
(Some(bit_size), Some(bit_offset)) => Some(BitData { bit_size, bit_offset }),
|
||||||
|
@ -1945,14 +1949,7 @@ fn process_structure_member_tag(info: &DwarfInfo, tag: &Tag) -> Result<Structure
|
||||||
_ => bail!("Mismatched bit attributes in Member: {tag:?}"),
|
_ => bail!("Mismatched bit attributes in Member: {tag:?}"),
|
||||||
};
|
};
|
||||||
let visibility = visibility.unwrap_or(Visibility::Public);
|
let visibility = visibility.unwrap_or(Visibility::Public);
|
||||||
Ok(StructureMember {
|
Ok(StructureMember { name, kind, offset, bit, visibility, byte_size })
|
||||||
name: name.clone(),
|
|
||||||
kind: member_type,
|
|
||||||
offset,
|
|
||||||
bit,
|
|
||||||
visibility,
|
|
||||||
byte_size,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_structure_tag(info: &DwarfInfo, tag: &Tag) -> Result<StructureType> {
|
fn process_structure_tag(info: &DwarfInfo, tag: &Tag) -> Result<StructureType> {
|
||||||
|
@ -1991,6 +1988,9 @@ fn process_structure_tag(info: &DwarfInfo, tag: &Tag) -> Result<StructureType> {
|
||||||
TagKind::Subroutine | TagKind::GlobalSubroutine => {
|
TagKind::Subroutine | TagKind::GlobalSubroutine => {
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
TagKind::GlobalVariable => {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
TagKind::StructureType
|
TagKind::StructureType
|
||||||
| TagKind::ArrayType
|
| TagKind::ArrayType
|
||||||
| TagKind::EnumerationType
|
| TagKind::EnumerationType
|
||||||
|
@ -2130,6 +2130,9 @@ fn process_enumeration_tag(info: &DwarfInfo, tag: &Tag) -> Result<EnumerationTyp
|
||||||
members.push(EnumerationMember { name, value });
|
members.push(EnumerationMember { name, value });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
(AttributeKind::Member, &AttributeValue::Reference(_key)) => {
|
||||||
|
// Pointer to parent structure, ignore
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bail!("Unhandled EnumerationType attribute {:?}", attr);
|
bail!("Unhandled EnumerationType attribute {:?}", attr);
|
||||||
}
|
}
|
||||||
|
@ -2174,7 +2177,8 @@ fn process_union_tag(info: &DwarfInfo, tag: &Tag) -> Result<UnionType> {
|
||||||
| TagKind::UnionType
|
| TagKind::UnionType
|
||||||
| TagKind::ClassType
|
| TagKind::ClassType
|
||||||
| TagKind::SubroutineType
|
| TagKind::SubroutineType
|
||||||
| TagKind::PtrToMemberType => {
|
| TagKind::PtrToMemberType
|
||||||
|
| TagKind::Typedef => {
|
||||||
// Variable type, ignore
|
// Variable type, ignore
|
||||||
}
|
}
|
||||||
kind => bail!("Unhandled UnionType child {:?}", kind),
|
kind => bail!("Unhandled UnionType child {:?}", kind),
|
||||||
|
@ -2189,7 +2193,10 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
ensure!(
|
ensure!(
|
||||||
matches!(
|
matches!(
|
||||||
tag.kind,
|
tag.kind,
|
||||||
TagKind::SubroutineType | TagKind::GlobalSubroutine | TagKind::Subroutine
|
TagKind::SubroutineType
|
||||||
|
| TagKind::GlobalSubroutine
|
||||||
|
| TagKind::Subroutine
|
||||||
|
| TagKind::InlinedSubroutine
|
||||||
),
|
),
|
||||||
"{:?} is not a Subroutine tag",
|
"{:?} is not a Subroutine tag",
|
||||||
tag.kind
|
tag.kind
|
||||||
|
@ -2206,6 +2213,7 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
let mut inline = false;
|
let mut inline = false;
|
||||||
let mut start_address = None;
|
let mut start_address = None;
|
||||||
let mut end_address = None;
|
let mut end_address = None;
|
||||||
|
let mut virtual_ = false;
|
||||||
for attr in &tag.attributes {
|
for attr in &tag.attributes {
|
||||||
match (attr.kind, &attr.value) {
|
match (attr.kind, &attr.value) {
|
||||||
(AttributeKind::Sibling, _) => {}
|
(AttributeKind::Sibling, _) => {}
|
||||||
|
@ -2271,6 +2279,7 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
// Restore register
|
// Restore register
|
||||||
}
|
}
|
||||||
(AttributeKind::Inline, _) => inline = true,
|
(AttributeKind::Inline, _) => inline = true,
|
||||||
|
(AttributeKind::Virtual, _) => virtual_ = true,
|
||||||
(AttributeKind::Specification, &AttributeValue::Reference(key)) => {
|
(AttributeKind::Specification, &AttributeValue::Reference(key)) => {
|
||||||
let spec_tag = info
|
let spec_tag = info
|
||||||
.tags
|
.tags
|
||||||
|
@ -2287,6 +2296,7 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
references.extend(spec.references);
|
references.extend(spec.references);
|
||||||
member_of = member_of.or(spec.member_of);
|
member_of = member_of.or(spec.member_of);
|
||||||
inline = inline || spec.inline;
|
inline = inline || spec.inline;
|
||||||
|
virtual_ = virtual_ || spec.virtual_;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bail!("Unhandled SubroutineType attribute {:?}", attr);
|
bail!("Unhandled SubroutineType attribute {:?}", attr);
|
||||||
|
@ -2299,7 +2309,6 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
let mut inlines = Vec::new();
|
let mut inlines = Vec::new();
|
||||||
for child in tag.children(&info.tags) {
|
for child in tag.children(&info.tags) {
|
||||||
ensure!(!var_args, "{:?} after UnspecifiedParameters", child.kind);
|
|
||||||
match child.kind {
|
match child.kind {
|
||||||
TagKind::FormalParameter => {
|
TagKind::FormalParameter => {
|
||||||
parameters.push(process_subroutine_parameter_tag(info, child)?)
|
parameters.push(process_subroutine_parameter_tag(info, child)?)
|
||||||
|
@ -2310,17 +2319,20 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
// TODO GlobalVariable refs?
|
// TODO GlobalVariable refs?
|
||||||
}
|
}
|
||||||
TagKind::Label => labels.push(process_subroutine_label_tag(info, child)?),
|
TagKind::Label => labels.push(process_subroutine_label_tag(info, child)?),
|
||||||
TagKind::LexicalBlock => blocks.push(process_subroutine_block_tag(info, child)?),
|
TagKind::LexicalBlock => {
|
||||||
TagKind::InlinedSubroutine => {
|
if let Some(block) = process_subroutine_block_tag(info, child)? {
|
||||||
inlines.push(process_inlined_subroutine_tag(info, child)?)
|
blocks.push(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
TagKind::InlinedSubroutine => inlines.push(process_subroutine_tag(info, child)?),
|
||||||
TagKind::StructureType
|
TagKind::StructureType
|
||||||
| TagKind::ArrayType
|
| TagKind::ArrayType
|
||||||
| TagKind::EnumerationType
|
| TagKind::EnumerationType
|
||||||
| TagKind::UnionType
|
| TagKind::UnionType
|
||||||
| TagKind::ClassType
|
| TagKind::ClassType
|
||||||
| TagKind::SubroutineType
|
| TagKind::SubroutineType
|
||||||
| TagKind::PtrToMemberType => {
|
| TagKind::PtrToMemberType
|
||||||
|
| TagKind::Typedef => {
|
||||||
// Variable type, ignore
|
// Variable type, ignore
|
||||||
}
|
}
|
||||||
kind => bail!("Unhandled SubroutineType child {:?}", kind),
|
kind => bail!("Unhandled SubroutineType child {:?}", kind),
|
||||||
|
@ -2341,6 +2353,7 @@ fn process_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineType>
|
||||||
member_of,
|
member_of,
|
||||||
variables,
|
variables,
|
||||||
inline,
|
inline,
|
||||||
|
virtual_,
|
||||||
local,
|
local,
|
||||||
labels,
|
labels,
|
||||||
blocks,
|
blocks,
|
||||||
|
@ -2373,7 +2386,7 @@ fn process_subroutine_label_tag(info: &DwarfInfo, tag: &Tag) -> Result<Subroutin
|
||||||
Ok(SubroutineLabel { name, address })
|
Ok(SubroutineLabel { name, address })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_subroutine_block_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineBlock> {
|
fn process_subroutine_block_tag(info: &DwarfInfo, tag: &Tag) -> Result<Option<SubroutineBlock>> {
|
||||||
ensure!(tag.kind == TagKind::LexicalBlock, "{:?} is not a LexicalBlock tag", tag.kind);
|
ensure!(tag.kind == TagKind::LexicalBlock, "{:?} is not a LexicalBlock tag", tag.kind);
|
||||||
|
|
||||||
let mut name = None;
|
let mut name = None;
|
||||||
|
@ -2391,13 +2404,21 @@ fn process_subroutine_block_tag(info: &DwarfInfo, tag: &Tag) -> Result<Subroutin
|
||||||
|
|
||||||
let mut variables = Vec::new();
|
let mut variables = Vec::new();
|
||||||
let mut blocks = Vec::new();
|
let mut blocks = Vec::new();
|
||||||
|
let mut inlines = Vec::new();
|
||||||
for child in tag.children(&info.tags) {
|
for child in tag.children(&info.tags) {
|
||||||
match child.kind {
|
match child.kind {
|
||||||
TagKind::LocalVariable => variables.push(process_local_variable_tag(info, child)?),
|
TagKind::LocalVariable => variables.push(process_local_variable_tag(info, child)?),
|
||||||
TagKind::GlobalVariable => {
|
TagKind::GlobalVariable => {
|
||||||
// TODO GlobalVariable refs?
|
// TODO GlobalVariable refs?
|
||||||
}
|
}
|
||||||
TagKind::LexicalBlock => blocks.push(process_subroutine_block_tag(info, child)?),
|
TagKind::LexicalBlock => {
|
||||||
|
if let Some(block) = process_subroutine_block_tag(info, child)? {
|
||||||
|
blocks.push(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TagKind::InlinedSubroutine => {
|
||||||
|
inlines.push(process_subroutine_tag(info, child)?);
|
||||||
|
}
|
||||||
TagKind::StructureType
|
TagKind::StructureType
|
||||||
| TagKind::ArrayType
|
| TagKind::ArrayType
|
||||||
| TagKind::EnumerationType
|
| TagKind::EnumerationType
|
||||||
|
@ -2411,51 +2432,7 @@ fn process_subroutine_block_tag(info: &DwarfInfo, tag: &Tag) -> Result<Subroutin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_address =
|
Ok(Some(SubroutineBlock { name, start_address, end_address, variables, blocks, inlines }))
|
||||||
start_address.ok_or_else(|| anyhow!("LexicalBlock without start address: {:?}", tag))?;
|
|
||||||
let end_address =
|
|
||||||
end_address.ok_or_else(|| anyhow!("LexicalBlock without end address: {:?}", tag))?;
|
|
||||||
Ok(SubroutineBlock { name, start_address, end_address, variables, blocks })
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_inlined_subroutine_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineInline> {
|
|
||||||
ensure!(
|
|
||||||
tag.kind == TagKind::InlinedSubroutine,
|
|
||||||
"{:?} is not an InlinedSubroutine tag",
|
|
||||||
tag.kind
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut specification = None;
|
|
||||||
let mut start_address = None;
|
|
||||||
let mut end_address = None;
|
|
||||||
for attr in &tag.attributes {
|
|
||||||
match (attr.kind, &attr.value) {
|
|
||||||
(AttributeKind::Sibling, _) => {}
|
|
||||||
(AttributeKind::Specification, &AttributeValue::Reference(key)) => {
|
|
||||||
specification = Some(key)
|
|
||||||
}
|
|
||||||
(AttributeKind::LowPc, &AttributeValue::Address(addr)) => start_address = Some(addr),
|
|
||||||
(AttributeKind::HighPc, &AttributeValue::Address(addr)) => end_address = Some(addr),
|
|
||||||
_ => bail!("Unhandled InlinedSubroutine attribute {:?}", attr),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for child in tag.children(&info.tags) {
|
|
||||||
match child.kind {
|
|
||||||
TagKind::GlobalVariable => {
|
|
||||||
// TODO GlobalVariable refs?
|
|
||||||
}
|
|
||||||
kind => bail!("Unhandled InlinedSubroutine child {:?}", kind),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let specification = specification
|
|
||||||
.ok_or_else(|| anyhow!("InlinedSubroutine without specification: {:?}", tag))?;
|
|
||||||
let start_address = start_address
|
|
||||||
.ok_or_else(|| anyhow!("InlinedSubroutine without start address: {:?}", tag))?;
|
|
||||||
let end_address =
|
|
||||||
end_address.ok_or_else(|| anyhow!("InlinedSubroutine without end address: {:?}", tag))?;
|
|
||||||
Ok(SubroutineInline { specification, start_address, end_address })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_subroutine_parameter_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineParameter> {
|
fn process_subroutine_parameter_tag(info: &DwarfInfo, tag: &Tag) -> Result<SubroutineParameter> {
|
||||||
|
@ -2476,15 +2453,21 @@ fn process_subroutine_parameter_tag(info: &DwarfInfo, tag: &Tag) -> Result<Subro
|
||||||
_,
|
_,
|
||||||
) => kind = Some(process_type(attr, info.e)?),
|
) => kind = Some(process_type(attr, info.e)?),
|
||||||
(AttributeKind::Location, AttributeValue::Block(block)) => {
|
(AttributeKind::Location, AttributeValue::Block(block)) => {
|
||||||
location = Some(process_variable_location(
|
if !block.is_empty() {
|
||||||
block,
|
location = Some(process_variable_location(
|
||||||
if tag.is_erased { Endian::Little } else { info.e },
|
block,
|
||||||
)?)
|
if tag.is_erased { Endian::Little } else { info.e },
|
||||||
|
)?);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
(AttributeKind::MwDwarf2Location, AttributeValue::Block(_block)) => {
|
(AttributeKind::MwDwarf2Location, AttributeValue::Block(_block)) => {
|
||||||
// TODO?
|
// TODO?
|
||||||
// info!("MwDwarf2Location: {:?} in {:?}", block, tag);
|
// info!("MwDwarf2Location: {:?} in {:?}", block, tag);
|
||||||
}
|
}
|
||||||
|
(AttributeKind::ConstValueBlock2 | AttributeKind::ConstValueBlock4, _) => {
|
||||||
|
// TODO?
|
||||||
|
// info!("ConstValueBlock: {:?} in {:?}", block, tag);
|
||||||
|
}
|
||||||
(AttributeKind::Specification, &AttributeValue::Reference(key)) => {
|
(AttributeKind::Specification, &AttributeValue::Reference(key)) => {
|
||||||
let spec_tag = info
|
let spec_tag = info
|
||||||
.tags
|
.tags
|
||||||
|
@ -2869,6 +2852,9 @@ fn process_variable_tag(info: &DwarfInfo, tag: &Tag) -> Result<VariableTag> {
|
||||||
(AttributeKind::Location, AttributeValue::Block(block)) => {
|
(AttributeKind::Location, AttributeValue::Block(block)) => {
|
||||||
address = Some(process_address(block, info.e)?)
|
address = Some(process_address(block, info.e)?)
|
||||||
}
|
}
|
||||||
|
(AttributeKind::Member, &AttributeValue::Reference(_key)) => {
|
||||||
|
// Pointer to parent structure, ignore
|
||||||
|
}
|
||||||
_ => {
|
_ => {
|
||||||
bail!("Unhandled Variable attribute {:?}", attr);
|
bail!("Unhandled Variable attribute {:?}", attr);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue