aboutsummaryrefslogtreecommitdiff
path: root/vendor/addr2line/examples/addr2line.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/addr2line/examples/addr2line.rs')
-rw-r--r--vendor/addr2line/examples/addr2line.rs317
1 files changed, 0 insertions, 317 deletions
diff --git a/vendor/addr2line/examples/addr2line.rs b/vendor/addr2line/examples/addr2line.rs
deleted file mode 100644
index 97fc802..0000000
--- a/vendor/addr2line/examples/addr2line.rs
+++ /dev/null
@@ -1,317 +0,0 @@
-use std::borrow::Cow;
-use std::fs::File;
-use std::io::{BufRead, Lines, StdinLock, Write};
-use std::path::{Path, PathBuf};
-
-use clap::{Arg, ArgAction, Command};
-use fallible_iterator::FallibleIterator;
-use object::{Object, ObjectSection, SymbolMap, SymbolMapName};
-use typed_arena::Arena;
-
-use addr2line::{Context, Location};
-
-fn parse_uint_from_hex_string(string: &str) -> Option<u64> {
- if string.len() > 2 && string.starts_with("0x") {
- u64::from_str_radix(&string[2..], 16).ok()
- } else {
- u64::from_str_radix(string, 16).ok()
- }
-}
-
-enum Addrs<'a> {
- Args(clap::parser::ValuesRef<'a, String>),
- Stdin(Lines<StdinLock<'a>>),
-}
-
-impl<'a> Iterator for Addrs<'a> {
- type Item = Option<u64>;
-
- fn next(&mut self) -> Option<Option<u64>> {
- let text = match *self {
- Addrs::Args(ref mut vals) => vals.next().map(Cow::from),
- Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from),
- };
- text.as_ref()
- .map(Cow::as_ref)
- .map(parse_uint_from_hex_string)
- }
-}
-
-fn print_loc(loc: Option<&Location<'_>>, basenames: bool, llvm: bool) {
- if let Some(loc) = loc {
- if let Some(ref file) = loc.file.as_ref() {
- let path = if basenames {
- Path::new(Path::new(file).file_name().unwrap())
- } else {
- Path::new(file)
- };
- print!("{}:", path.display());
- } else {
- print!("??:");
- }
- if llvm {
- print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0));
- } else if let Some(line) = loc.line {
- print!("{}", line);
- } else {
- print!("?");
- }
- println!();
- } else if llvm {
- println!("??:0:0");
- } else {
- println!("??:0");
- }
-}
-
-fn print_function(name: Option<&str>, language: Option<gimli::DwLang>, demangle: bool) {
- if let Some(name) = name {
- if demangle {
- print!("{}", addr2line::demangle_auto(Cow::from(name), language));
- } else {
- print!("{}", name);
- }
- } else {
- print!("??");
- }
-}
-
-fn load_file_section<'input, 'arena, Endian: gimli::Endianity>(
- id: gimli::SectionId,
- file: &object::File<'input>,
- endian: Endian,
- arena_data: &'arena Arena<Cow<'input, [u8]>>,
-) -> Result<gimli::EndianSlice<'arena, Endian>, ()> {
- // TODO: Unify with dwarfdump.rs in gimli.
- let name = id.name();
- match file.section_by_name(name) {
- Some(section) => match section.uncompressed_data().unwrap() {
- Cow::Borrowed(b) => Ok(gimli::EndianSlice::new(b, endian)),
- Cow::Owned(b) => Ok(gimli::EndianSlice::new(arena_data.alloc(b.into()), endian)),
- },
- None => Ok(gimli::EndianSlice::new(&[][..], endian)),
- }
-}
-
-fn find_name_from_symbols<'a>(
- symbols: &'a SymbolMap<SymbolMapName<'_>>,
- probe: u64,
-) -> Option<&'a str> {
- symbols.get(probe).map(|x| x.name())
-}
-
-struct Options<'a> {
- do_functions: bool,
- do_inlines: bool,
- pretty: bool,
- print_addrs: bool,
- basenames: bool,
- demangle: bool,
- llvm: bool,
- exe: &'a PathBuf,
- sup: Option<&'a PathBuf>,
-}
-
-fn main() {
- let matches = Command::new("addr2line")
- .version(env!("CARGO_PKG_VERSION"))
- .about("A fast addr2line Rust port")
- .max_term_width(100)
- .args(&[
- Arg::new("exe")
- .short('e')
- .long("exe")
- .value_name("filename")
- .value_parser(clap::value_parser!(PathBuf))
- .help(
- "Specify the name of the executable for which addresses should be translated.",
- )
- .required(true),
- Arg::new("sup")
- .long("sup")
- .value_name("filename")
- .value_parser(clap::value_parser!(PathBuf))
- .help("Path to supplementary object file."),
- Arg::new("functions")
- .short('f')
- .long("functions")
- .action(ArgAction::SetTrue)
- .help("Display function names as well as file and line number information."),
- Arg::new("pretty").short('p').long("pretty-print")
- .action(ArgAction::SetTrue)
- .help(
- "Make the output more human friendly: each location are printed on one line.",
- ),
- Arg::new("inlines").short('i').long("inlines")
- .action(ArgAction::SetTrue)
- .help(
- "If the address belongs to a function that was inlined, the source information for \
- all enclosing scopes back to the first non-inlined function will also be printed.",
- ),
- Arg::new("addresses").short('a').long("addresses")
- .action(ArgAction::SetTrue)
- .help(
- "Display the address before the function name, file and line number information.",
- ),
- Arg::new("basenames")
- .short('s')
- .long("basenames")
- .action(ArgAction::SetTrue)
- .help("Display only the base of each file name."),
- Arg::new("demangle").short('C').long("demangle")
- .action(ArgAction::SetTrue)
- .help(
- "Demangle function names. \
- Specifying a specific demangling style (like GNU addr2line) is not supported. \
- (TODO)"
- ),
- Arg::new("llvm")
- .long("llvm")
- .action(ArgAction::SetTrue)
- .help("Display output in the same format as llvm-symbolizer."),
- Arg::new("addrs")
- .action(ArgAction::Append)
- .help("Addresses to use instead of reading from stdin."),
- ])
- .get_matches();
-
- let arena_data = Arena::new();
-
- let opts = Options {
- do_functions: matches.get_flag("functions"),
- do_inlines: matches.get_flag("inlines"),
- pretty: matches.get_flag("pretty"),
- print_addrs: matches.get_flag("addresses"),
- basenames: matches.get_flag("basenames"),
- demangle: matches.get_flag("demangle"),
- llvm: matches.get_flag("llvm"),
- exe: matches.get_one::<PathBuf>("exe").unwrap(),
- sup: matches.get_one::<PathBuf>("sup"),
- };
-
- let file = File::open(opts.exe).unwrap();
- let map = unsafe { memmap2::Mmap::map(&file).unwrap() };
- let object = &object::File::parse(&*map).unwrap();
-
- let endian = if object.is_little_endian() {
- gimli::RunTimeEndian::Little
- } else {
- gimli::RunTimeEndian::Big
- };
-
- let mut load_section = |id: gimli::SectionId| -> Result<_, _> {
- load_file_section(id, object, endian, &arena_data)
- };
-
- let sup_map;
- let sup_object = if let Some(sup_path) = opts.sup {
- let sup_file = File::open(sup_path).unwrap();
- sup_map = unsafe { memmap2::Mmap::map(&sup_file).unwrap() };
- Some(object::File::parse(&*sup_map).unwrap())
- } else {
- None
- };
-
- let symbols = object.symbol_map();
- let mut dwarf = gimli::Dwarf::load(&mut load_section).unwrap();
- if let Some(ref sup_object) = sup_object {
- let mut load_sup_section = |id: gimli::SectionId| -> Result<_, _> {
- load_file_section(id, sup_object, endian, &arena_data)
- };
- dwarf.load_sup(&mut load_sup_section).unwrap();
- }
-
- let mut split_dwarf_loader = addr2line::builtin_split_dwarf_loader::SplitDwarfLoader::new(
- |data, endian| {
- gimli::EndianSlice::new(arena_data.alloc(Cow::Owned(data.into_owned())), endian)
- },
- Some(opts.exe.clone()),
- );
- let ctx = Context::from_dwarf(dwarf).unwrap();
-
- let stdin = std::io::stdin();
- let addrs = matches
- .get_many::<String>("addrs")
- .map(Addrs::Args)
- .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines()));
-
- for probe in addrs {
- if opts.print_addrs {
- let addr = probe.unwrap_or(0);
- if opts.llvm {
- print!("0x{:x}", addr);
- } else {
- print!("0x{:016x}", addr);
- }
- if opts.pretty {
- print!(": ");
- } else {
- println!();
- }
- }
-
- if opts.do_functions || opts.do_inlines {
- let mut printed_anything = false;
- if let Some(probe) = probe {
- let frames = ctx.find_frames(probe);
- let frames = split_dwarf_loader.run(frames).unwrap();
- let mut frames = frames.enumerate();
- while let Some((i, frame)) = frames.next().unwrap() {
- if opts.pretty && i != 0 {
- print!(" (inlined by) ");
- }
-
- if opts.do_functions {
- if let Some(func) = frame.function {
- print_function(
- func.raw_name().ok().as_ref().map(AsRef::as_ref),
- func.language,
- opts.demangle,
- );
- } else {
- let name = find_name_from_symbols(&symbols, probe);
- print_function(name, None, opts.demangle);
- }
-
- if opts.pretty {
- print!(" at ");
- } else {
- println!();
- }
- }
-
- print_loc(frame.location.as_ref(), opts.basenames, opts.llvm);
-
- printed_anything = true;
-
- if !opts.do_inlines {
- break;
- }
- }
- }
-
- if !printed_anything {
- if opts.do_functions {
- let name = probe.and_then(|probe| find_name_from_symbols(&symbols, probe));
- print_function(name, None, opts.demangle);
-
- if opts.pretty {
- print!(" at ");
- } else {
- println!();
- }
- }
-
- print_loc(None, opts.basenames, opts.llvm);
- }
- } else {
- let loc = probe.and_then(|probe| ctx.find_location(probe).unwrap());
- print_loc(loc.as_ref(), opts.basenames, opts.llvm);
- }
-
- if opts.llvm {
- println!();
- }
- std::io::stdout().flush().unwrap();
- }
-}