| 11 | } |
| 12 | |
| 13 | fn main() { |
| 14 | let matches = App::new("hardliner") |
| 15 | .version("2.0.1") |
| 16 | .about("ESP stacktrace decoder") |
| 17 | .arg( |
| 18 | Arg::with_name("elf") |
| 19 | .value_name("binary_file") |
| 20 | .help( |
| 21 | "Specify the name of the .elf executable.", |
| 22 | ) |
| 23 | .required(true), |
| 24 | ) |
| 25 | .arg( |
| 26 | Arg::with_name("dump") |
| 27 | .value_name("stack_trace_file") |
| 28 | .help("Stack trace file."), |
| 29 | ) |
| 30 | .get_matches(); |
| 31 | |
| 32 | let binary_file = matches.value_of("elf").unwrap(); |
| 33 | let mut binary_file = File::open(binary_file).unwrap(); |
| 34 | let mut binary_buf = Vec::<u8>::new(); |
| 35 | let _ = binary_file.read_to_end(&mut binary_buf); |
| 36 | |
| 37 | let stdin = std::io::stdin(); |
| 38 | let stack_trace_source = matches |
| 39 | .value_of("dump") |
| 40 | .map(DumpSource::FilePath) |
| 41 | .unwrap_or_else(|| DumpSource::Stdin(stdin)); |
| 42 | |
| 43 | let stack_trace = match stack_trace_source { |
| 44 | DumpSource::FilePath(file) => { |
| 45 | let mut file = File::open(file).unwrap(); |
| 46 | let mut stack_trace = String::new(); |
| 47 | let _ = file.read_to_string(&mut stack_trace).unwrap(); |
| 48 | stack_trace |
| 49 | }, |
| 50 | DumpSource::Stdin(stdin) => { |
| 51 | let mut stdin_buffer = Vec::<u8>::new(); |
| 52 | let _ = stdin.lock().read_to_end(&mut stdin_buffer).unwrap(); |
| 53 | let stack_trace = String::from_utf8(stdin_buffer).unwrap(); |
| 54 | stack_trace |
| 55 | } |
| 56 | }; |
| 57 | |
| 58 | let decoded_addresses = decode(&binary_buf, &stack_trace); |
| 59 | for address in decoded_addresses { |
| 60 | println!("0x{:04x}: {} at {}", |
| 61 | address.address, |
| 62 | address.function_name.bold(), |
| 63 | address.location.blue() |
| 64 | ); |
| 65 | } |
| 66 | } |