summaryrefslogtreecommitdiff
path: root/rust/examples/dwarf/dwarf_import/src/helpers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/examples/dwarf/dwarf_import/src/helpers.rs')
-rw-r--r--rust/examples/dwarf/dwarf_import/src/helpers.rs236
1 files changed, 106 insertions, 130 deletions
diff --git a/rust/examples/dwarf/dwarf_import/src/helpers.rs b/rust/examples/dwarf/dwarf_import/src/helpers.rs
index f3b7dd81..05cf6f82 100644
--- a/rust/examples/dwarf/dwarf_import/src/helpers.rs
+++ b/rust/examples/dwarf/dwarf_import/src/helpers.rs
@@ -12,12 +12,15 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+use crate::DebugInfoBuilderContext;
+
use gimli::{
constants, Attribute, AttributeValue,
- AttributeValue::{DebugInfoRef, DebugInfoRefSup, UnitRef},
- DebuggingInformationEntry, Dwarf, Operation, Reader, Unit, UnitOffset, UnitSectionOffset,
+ AttributeValue::{DebugInfoRef, UnitRef},
+ DebuggingInformationEntry, Operation, Reader, Unit, UnitOffset, UnitSectionOffset,
};
+use log::warn;
use std::ffi::CString;
pub(crate) fn get_uid<R: Reader<Offset = usize>>(
@@ -33,182 +36,136 @@ pub(crate) fn get_uid<R: Reader<Offset = usize>>(
////////////////////////////////////
// DIE attr convenience functions
-pub(crate) enum DieReference<R: Reader<Offset = usize>> {
- Offset(UnitOffset),
- UnitAndOffset((Unit<R>, UnitOffset)),
-}
-
-fn get_unit_copy<'a, R: Reader<Offset = usize>>(dwarf: &'a Dwarf<R>, unit: &'a Unit<R>) -> Unit<R> {
- let mut iter = dwarf.units();
- while let Ok(Some(header)) = iter.next() {
- if header.offset() == unit.header.offset() {
- return dwarf.unit(header).unwrap();
- }
- }
- unreachable!()
+pub(crate) enum DieReference<'a, R: Reader<Offset = usize>> {
+ UnitAndOffset((&'a Unit<R>, UnitOffset)),
+ Err,
}
pub(crate) fn get_attr_die<'a, R: Reader<Offset = usize>>(
- dwarf: &'a Dwarf<R>,
- _unit: &'a Unit<R>,
- entry: &'a DebuggingInformationEntry<R>,
+ unit: &'a Unit<R>,
+ entry: &DebuggingInformationEntry<R>,
+ debug_info_builder_context: &'a DebugInfoBuilderContext<R>,
attr: constants::DwAt,
-) -> Option<DieReference<R>> {
+) -> Option<DieReference<'a, R>> {
match entry.attr_value(attr) {
- Ok(Some(UnitRef(offset))) => Some(DieReference::Offset(offset)),
- Ok(Some(DebugInfoRef(offset))) | Ok(Some(DebugInfoRefSup(offset))) => {
- let mut iter = dwarf.units();
- while let Ok(Some(header)) = iter.next() {
- if let Some(new_offset) = offset.to_unit_offset(&header) {
- return Some(DieReference::UnitAndOffset((
- dwarf.unit(header).unwrap(),
- new_offset,
- )));
+ Ok(Some(UnitRef(offset))) => Some(DieReference::UnitAndOffset((unit, offset))),
+ Ok(Some(DebugInfoRef(offset))) => {
+ for source_unit in debug_info_builder_context.units() {
+ if let Some(new_offset) = offset.to_unit_offset(&source_unit.header) {
+ return Some(DieReference::UnitAndOffset((source_unit, new_offset)));
}
}
- unreachable!() //None
+ warn!("Failed to fetch DIE. Debug information may be incomplete.");
+ None
}
+ // Ok(Some(DebugInfoRefSup(offset))) TODO - dwarf 5 stuff
_ => None,
}
}
pub(crate) fn resolve_specification<'a, R: Reader<Offset = usize>>(
- dwarf: &'a Dwarf<R>,
unit: &'a Unit<R>,
- entry: &'a DebuggingInformationEntry<R>,
-) -> DieReference<R> {
- if let Some(die_reference) = get_attr_die(dwarf, unit, entry, constants::DW_AT_specification) {
- match die_reference {
- DieReference::Offset(entry_offset) => {
- resolve_specification(dwarf, unit, &unit.entry(entry_offset).unwrap())
- }
- DieReference::UnitAndOffset((entry_unit, entry_offset)) => {
- resolve_specification_slowpath(
- dwarf,
- &entry_unit,
- &entry_unit.entry(entry_offset).unwrap(),
- )
- }
- }
- } else if let Some(die_reference) =
- get_attr_die(dwarf, unit, entry, constants::DW_AT_abstract_origin)
- {
- match die_reference {
- DieReference::Offset(entry_offset) => {
- resolve_specification(dwarf, unit, &unit.entry(entry_offset).unwrap())
- }
- DieReference::UnitAndOffset((entry_unit, entry_offset)) => {
- resolve_specification_slowpath(
- dwarf,
- &entry_unit,
- &entry_unit.entry(entry_offset).unwrap(),
- )
- }
- }
- } else {
- DieReference::Offset(entry.offset())
- }
-}
-
-fn resolve_specification_slowpath<'a, R: Reader<Offset = usize>>(
- dwarf: &'a Dwarf<R>,
- unit: &'a Unit<R>,
- entry: &'a DebuggingInformationEntry<R>,
-) -> DieReference<R> {
- if let Some(die_reference) = get_attr_die(dwarf, unit, entry, constants::DW_AT_specification) {
+ entry: &DebuggingInformationEntry<R>,
+ debug_info_builder_context: &'a DebugInfoBuilderContext<R>,
+) -> DieReference<'a, R> {
+ if let Some(die_reference) = get_attr_die(
+ unit,
+ entry,
+ debug_info_builder_context,
+ constants::DW_AT_specification,
+ ) {
match die_reference {
- DieReference::Offset(entry_offset) => {
- resolve_specification_slowpath(dwarf, unit, &unit.entry(entry_offset).unwrap())
- }
DieReference::UnitAndOffset((entry_unit, entry_offset)) => {
- resolve_specification_slowpath(
- dwarf,
- &entry_unit,
- &entry_unit.entry(entry_offset).unwrap(),
- )
+ if let Ok(entry) = entry_unit.entry(entry_offset) {
+ resolve_specification(entry_unit, &entry, debug_info_builder_context)
+ } else {
+ warn!("Failed to fetch DIE. Debug information may be incomplete.");
+ DieReference::Err
+ }
}
+ DieReference::Err => DieReference::Err,
}
- } else if let Some(die_reference) =
- get_attr_die(dwarf, unit, entry, constants::DW_AT_abstract_origin)
- {
+ } else if let Some(die_reference) = get_attr_die(
+ unit,
+ entry,
+ debug_info_builder_context,
+ constants::DW_AT_abstract_origin,
+ ) {
match die_reference {
- DieReference::Offset(entry_offset) => {
- resolve_specification_slowpath(dwarf, unit, &unit.entry(entry_offset).unwrap())
- }
DieReference::UnitAndOffset((entry_unit, entry_offset)) => {
- resolve_specification_slowpath(
- dwarf,
- &entry_unit,
- &entry_unit.entry(entry_offset).unwrap(),
- )
+ if let Ok(entry) = entry_unit.entry(entry_offset) {
+ resolve_specification(entry_unit, &entry, debug_info_builder_context)
+ } else {
+ warn!("Failed to fetch DIE. Debug information may be incomplete.");
+ DieReference::Err
+ }
}
+ DieReference::Err => DieReference::Err,
}
} else {
- DieReference::UnitAndOffset((get_unit_copy(dwarf, unit), entry.offset()))
+ DieReference::UnitAndOffset((unit, entry.offset()))
}
}
// Get name from DIE, or referenced dependencies
pub(crate) fn get_name<R: Reader<Offset = usize>>(
- dwarf: &Dwarf<R>,
unit: &Unit<R>,
entry: &DebuggingInformationEntry<R>,
+ debug_info_builder_context: &DebugInfoBuilderContext<R>,
) -> Option<CString> {
- match resolve_specification(dwarf, unit, entry) {
- DieReference::Offset(entry_offset) => {
- if let Ok(Some(attr_val)) = unit
- .entry(entry_offset)
- .unwrap()
- .attr_value(constants::DW_AT_name)
- {
- if let Ok(attr_string) = dwarf.attr_string(unit, attr_val) {
- if let Ok(attr_string) = attr_string.to_string() {
- return Some(CString::new(attr_string.to_string()).unwrap());
- }
- }
- }
- None
- }
+ match resolve_specification(unit, entry, debug_info_builder_context) {
DieReference::UnitAndOffset((entry_unit, entry_offset)) => {
if let Ok(Some(attr_val)) = entry_unit
.entry(entry_offset)
.unwrap()
.attr_value(constants::DW_AT_name)
{
- if let Ok(attr_string) = dwarf.attr_string(&entry_unit, attr_val) {
+ if let Ok(attr_string) = debug_info_builder_context
+ .dwarf()
+ .attr_string(entry_unit, attr_val)
+ {
if let Ok(attr_string) = attr_string.to_string() {
return Some(CString::new(attr_string.to_string()).unwrap());
}
}
}
+
+ // if let Some(raw_name) = get_raw_name(unit, entry, debug_info_builder_context) {
+ // if let Some(arch) = debug_info_builder_context.default_architecture() {
+ // if let Ok((_, names)) = demangle_gnu3(&arch, raw_name, true) {
+ // return Some(CString::new(names.join("::")).unwrap());
+ // }
+ // }
+ // }
None
}
+ DieReference::Err => None,
}
}
// Get raw name from DIE, or referenced dependencies
-pub(crate) fn get_raw_name<R: Reader>(
- dwarf: &Dwarf<R>,
+pub(crate) fn get_raw_name<R: Reader<Offset = usize>>(
unit: &Unit<R>,
entry: &DebuggingInformationEntry<R>,
+ debug_info_builder_context: &DebugInfoBuilderContext<R>,
) -> Option<CString> {
if let Ok(Some(attr_val)) = entry.attr_value(constants::DW_AT_linkage_name) {
- if let Ok(attr_string) = dwarf.attr_string(unit, attr_val) {
+ if let Ok(attr_string) = debug_info_builder_context
+ .dwarf()
+ .attr_string(unit, attr_val)
+ {
if let Ok(attr_string) = attr_string.to_string() {
- Some(CString::new(attr_string.to_string()).unwrap())
- } else {
- None
+ return Some(CString::new(attr_string.to_string()).unwrap());
}
- } else {
- None
}
- } else {
- None
}
+ None
}
// Get the size of an object as a usize
-pub(crate) fn get_size_as_usize<R: Reader>(entry: &DebuggingInformationEntry<R>) -> Option<usize> {
+pub(crate) fn get_size_as_usize<R: Reader<Offset = usize>>(
+ entry: &DebuggingInformationEntry<R>,
+) -> Option<usize> {
if let Ok(Some(attr)) = entry.attr(constants::DW_AT_byte_size) {
get_attr_as_usize(attr)
} else if let Ok(Some(attr)) = entry.attr(constants::DW_AT_bit_size) {
@@ -219,7 +176,9 @@ pub(crate) fn get_size_as_usize<R: Reader>(entry: &DebuggingInformationEntry<R>)
}
// Get the size of an object as a u64
-pub(crate) fn get_size_as_u64<R: Reader>(entry: &DebuggingInformationEntry<R>) -> Option<u64> {
+pub(crate) fn get_size_as_u64<R: Reader<Offset = usize>>(
+ entry: &DebuggingInformationEntry<R>,
+) -> Option<u64> {
if let Ok(Some(attr)) = entry.attr(constants::DW_AT_byte_size) {
get_attr_as_u64(&attr)
} else if let Ok(Some(attr)) = entry.attr(constants::DW_AT_bit_size) {
@@ -230,7 +189,9 @@ pub(crate) fn get_size_as_u64<R: Reader>(entry: &DebuggingInformationEntry<R>) -
}
// Get the size of a subrange as a u64
-pub(crate) fn get_subrange_size<R: Reader>(entry: &DebuggingInformationEntry<R>) -> u64 {
+pub(crate) fn get_subrange_size<R: Reader<Offset = usize>>(
+ entry: &DebuggingInformationEntry<R>,
+) -> u64 {
if let Ok(Some(attr)) = entry.attr(constants::DW_AT_upper_bound) {
get_attr_as_u64(&attr).map_or(0, |v| v + 1)
} else if let Ok(Some(attr)) = entry.attr(constants::DW_AT_count) {
@@ -243,24 +204,36 @@ pub(crate) fn get_subrange_size<R: Reader>(entry: &DebuggingInformationEntry<R>)
}
// Get the start address of a function
-pub(crate) fn get_start_address<R: Reader>(
- dwarf: &Dwarf<R>,
+pub(crate) fn get_start_address<R: Reader<Offset = usize>>(
unit: &Unit<R>,
entry: &DebuggingInformationEntry<R>,
+ debug_info_builder_context: &DebugInfoBuilderContext<R>,
) -> Option<u64> {
if let Ok(Some(attr_val)) = entry.attr_value(constants::DW_AT_low_pc) {
- match dwarf.attr_address(unit, attr_val) {
+ match debug_info_builder_context
+ .dwarf()
+ .attr_address(unit, attr_val)
+ {
Ok(Some(val)) => Some(val),
_ => None,
}
} else if let Ok(Some(attr_val)) = entry.attr_value(constants::DW_AT_entry_pc) {
- match dwarf.attr_address(unit, attr_val) {
+ match debug_info_builder_context
+ .dwarf()
+ .attr_address(unit, attr_val)
+ {
Ok(Some(val)) => Some(val),
_ => None,
}
} else if let Ok(Some(attr_value)) = entry.attr_value(constants::DW_AT_ranges) {
- if let Ok(Some(ranges_offset)) = dwarf.attr_ranges_offset(unit, attr_value) {
- if let Ok(mut ranges) = dwarf.ranges(unit, ranges_offset) {
+ if let Ok(Some(ranges_offset)) = debug_info_builder_context
+ .dwarf()
+ .attr_ranges_offset(unit, attr_value)
+ {
+ if let Ok(mut ranges) = debug_info_builder_context
+ .dwarf()
+ .ranges(unit, ranges_offset)
+ {
if let Ok(Some(range)) = ranges.next() {
return Some(range.begin);
}
@@ -273,7 +246,7 @@ pub(crate) fn get_start_address<R: Reader>(
}
// Get an attribute value as a u64 if it can be coerced
-pub(crate) fn get_attr_as_u64<R: Reader>(attr: &Attribute<R>) -> Option<u64> {
+pub(crate) fn get_attr_as_u64<R: Reader<Offset = usize>>(attr: &Attribute<R>) -> Option<u64> {
if let Some(value) = attr.u8_value() {
Some(value.into())
} else if let Some(value) = attr.u16_value() {
@@ -286,7 +259,7 @@ pub(crate) fn get_attr_as_u64<R: Reader>(attr: &Attribute<R>) -> Option<u64> {
}
// Get an attribute value as a usize if it can be coerced
-pub(crate) fn get_attr_as_usize<R: Reader>(attr: Attribute<R>) -> Option<usize> {
+pub(crate) fn get_attr_as_usize<R: Reader<Offset = usize>>(attr: Attribute<R>) -> Option<usize> {
if let Some(value) = attr.u8_value() {
Some(value.into())
} else if let Some(value) = attr.u16_value() {
@@ -300,7 +273,10 @@ pub(crate) fn get_attr_as_usize<R: Reader>(attr: Attribute<R>) -> Option<usize>
// Get an attribute value as a usize if it can be coerced
// Parses DW_OP_address, DW_OP_const
-pub(crate) fn get_expr_value<R: Reader>(unit: &Unit<R>, attr: Attribute<R>) -> Option<u64> {
+pub(crate) fn get_expr_value<R: Reader<Offset = usize>>(
+ unit: &Unit<R>,
+ attr: Attribute<R>,
+) -> Option<u64> {
if let AttributeValue::Exprloc(mut expression) = attr.value() {
match Operation::parse(&mut expression.0, unit.encoding()) {
Ok(Operation::PlusConstant { value }) => Some(value),