diff options
Diffstat (limited to 'vendor/addr2line/examples/addr2line.rs')
-rw-r--r-- | vendor/addr2line/examples/addr2line.rs | 317 |
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(); - } -} |