summaryrefslogtreecommitdiffstats
path: root/vendor/gimli-0.26.2/examples/simple_line.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gimli-0.26.2/examples/simple_line.rs')
-rw-r--r--vendor/gimli-0.26.2/examples/simple_line.rs106
1 files changed, 106 insertions, 0 deletions
diff --git a/vendor/gimli-0.26.2/examples/simple_line.rs b/vendor/gimli-0.26.2/examples/simple_line.rs
new file mode 100644
index 000000000..87b224cda
--- /dev/null
+++ b/vendor/gimli-0.26.2/examples/simple_line.rs
@@ -0,0 +1,106 @@
+//! A simple example of parsing `.debug_line`.
+
+use object::{Object, ObjectSection};
+use std::{borrow, env, fs, path};
+
+fn main() {
+ for path in env::args().skip(1) {
+ let file = fs::File::open(&path).unwrap();
+ let mmap = unsafe { memmap2::Mmap::map(&file).unwrap() };
+ let object = object::File::parse(&*mmap).unwrap();
+ let endian = if object.is_little_endian() {
+ gimli::RunTimeEndian::Little
+ } else {
+ gimli::RunTimeEndian::Big
+ };
+ dump_file(&object, endian).unwrap();
+ }
+}
+
+fn dump_file(object: &object::File, endian: gimli::RunTimeEndian) -> Result<(), gimli::Error> {
+ // Load a section and return as `Cow<[u8]>`.
+ let load_section = |id: gimli::SectionId| -> Result<borrow::Cow<[u8]>, gimli::Error> {
+ match object.section_by_name(id.name()) {
+ Some(ref section) => Ok(section
+ .uncompressed_data()
+ .unwrap_or(borrow::Cow::Borrowed(&[][..]))),
+ None => Ok(borrow::Cow::Borrowed(&[][..])),
+ }
+ };
+
+ // Load all of the sections.
+ let dwarf_cow = gimli::Dwarf::load(&load_section)?;
+
+ // Borrow a `Cow<[u8]>` to create an `EndianSlice`.
+ let borrow_section: &dyn for<'a> Fn(
+ &'a borrow::Cow<[u8]>,
+ ) -> gimli::EndianSlice<'a, gimli::RunTimeEndian> =
+ &|section| gimli::EndianSlice::new(&*section, endian);
+
+ // Create `EndianSlice`s for all of the sections.
+ let dwarf = dwarf_cow.borrow(&borrow_section);
+
+ // Iterate over the compilation units.
+ let mut iter = dwarf.units();
+ while let Some(header) = iter.next()? {
+ println!(
+ "Line number info for unit at <.debug_info+0x{:x}>",
+ header.offset().as_debug_info_offset().unwrap().0
+ );
+ let unit = dwarf.unit(header)?;
+
+ // Get the line program for the compilation unit.
+ if let Some(program) = unit.line_program.clone() {
+ let comp_dir = if let Some(ref dir) = unit.comp_dir {
+ path::PathBuf::from(dir.to_string_lossy().into_owned())
+ } else {
+ path::PathBuf::new()
+ };
+
+ // Iterate over the line program rows.
+ let mut rows = program.rows();
+ while let Some((header, row)) = rows.next_row()? {
+ if row.end_sequence() {
+ // End of sequence indicates a possible gap in addresses.
+ println!("{:x} end-sequence", row.address());
+ } else {
+ // Determine the path. Real applications should cache this for performance.
+ let mut path = path::PathBuf::new();
+ if let Some(file) = row.file(header) {
+ path = comp_dir.clone();
+
+ // The directory index 0 is defined to correspond to the compilation unit directory.
+ if file.directory_index() != 0 {
+ if let Some(dir) = file.directory(header) {
+ path.push(
+ dwarf.attr_string(&unit, dir)?.to_string_lossy().as_ref(),
+ );
+ }
+ }
+
+ path.push(
+ dwarf
+ .attr_string(&unit, file.path_name())?
+ .to_string_lossy()
+ .as_ref(),
+ );
+ }
+
+ // Determine line/column. DWARF line/column is never 0, so we use that
+ // but other applications may want to display this differently.
+ let line = match row.line() {
+ Some(line) => line.get(),
+ None => 0,
+ };
+ let column = match row.column() {
+ gimli::ColumnType::LeftEdge => 0,
+ gimli::ColumnType::Column(column) => column.get(),
+ };
+
+ println!("{:x} {}:{}:{}", row.address(), path.display(), line, column);
+ }
+ }
+ }
+ }
+ Ok(())
+}