Augment BPF binary dumps to resolve call instruction targets
This commit is contained in:
parent
7ba3e710d3
commit
78d1d59889
|
@ -1,5 +1,7 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "Inflector"
|
||||
version = "0.11.4"
|
||||
|
@ -3298,14 +3300,13 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.3.9"
|
||||
version = "1.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c3780fcf44b193bc4d09f36d2a3c87b251da4a046c87795a0d35f4f927ad8e6"
|
||||
checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr 2.3.3",
|
||||
"regex-syntax",
|
||||
"thread_local",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3319,9 +3320,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.18"
|
||||
version = "0.6.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26412eb97c6b088a6997e05f69403a802a92d520de2f8e63c2b65f9e0f47c4e8"
|
||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||
|
||||
[[package]]
|
||||
name = "remove_dir_all"
|
||||
|
@ -4066,6 +4067,7 @@ dependencies = [
|
|||
"bzip2",
|
||||
"cargo_metadata",
|
||||
"clap",
|
||||
"regex",
|
||||
"solana-download-utils",
|
||||
"solana-sdk",
|
||||
"tar",
|
||||
|
@ -5785,15 +5787,6 @@ version = "1.0.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99"
|
||||
|
||||
[[package]]
|
||||
name = "thread_local"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
|
|
|
@ -12,6 +12,7 @@ publish = false
|
|||
[dependencies]
|
||||
bzip2 = "0.3.3"
|
||||
clap = "2.33.3"
|
||||
regex = "1.4.5"
|
||||
cargo_metadata = "0.12.0"
|
||||
solana-sdk = { path = "..", version = "=1.7.0" }
|
||||
solana-download-utils = { path = "../../download-utils", version = "=1.7.0" }
|
||||
|
|
|
@ -3,16 +3,19 @@ use {
|
|||
clap::{
|
||||
crate_description, crate_name, crate_version, value_t, value_t_or_exit, values_t, App, Arg,
|
||||
},
|
||||
regex::Regex,
|
||||
solana_download_utils::download_file,
|
||||
solana_sdk::signature::{write_keypair_file, Keypair},
|
||||
std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
ffi::OsStr,
|
||||
fs::{self, File},
|
||||
io::BufReader,
|
||||
io::{prelude::*, BufReader, BufWriter},
|
||||
path::{Path, PathBuf},
|
||||
process::exit,
|
||||
process::{Command, Stdio},
|
||||
str::FromStr,
|
||||
},
|
||||
tar::Archive,
|
||||
};
|
||||
|
@ -150,6 +153,103 @@ fn install_if_missing(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
// Process dump file attributing call instructions with callee function names
|
||||
fn postprocess_dump(program_dump: &Path) {
|
||||
if !program_dump.exists() {
|
||||
return;
|
||||
}
|
||||
let postprocessed_dump = program_dump.with_extension("postprocessed");
|
||||
let head_re = Regex::new(r"(^[0-9a-f]{16}) (.+)").unwrap();
|
||||
let insn_re = Regex::new(r"^ +([0-9]+)((\s[0-9a-f]{2})+)\s.+").unwrap();
|
||||
let call_re = Regex::new(r"^ +([0-9]+)(\s[0-9a-f]{2})+\scall (-?)0x([0-9a-f]+)").unwrap();
|
||||
let relo_re = Regex::new(r"^([0-9a-f]{16}) [0-9a-f]{16} R_BPF_64_32 +0{16} (.+)").unwrap();
|
||||
let mut a2n: HashMap<i64, String> = HashMap::new();
|
||||
let mut rel: HashMap<u64, String> = HashMap::new();
|
||||
let mut name = String::from("");
|
||||
let mut state = 0;
|
||||
let file = match File::open(program_dump) {
|
||||
Ok(x) => x,
|
||||
_ => return,
|
||||
};
|
||||
for line_result in BufReader::new(file).lines() {
|
||||
let line = line_result.unwrap();
|
||||
let line = line.trim_end();
|
||||
if line == "Disassembly of section .text" {
|
||||
state = 1;
|
||||
}
|
||||
if state == 0 {
|
||||
if relo_re.is_match(line) {
|
||||
let captures = relo_re.captures(line).unwrap();
|
||||
let address = u64::from_str_radix(&captures[1], 16).unwrap();
|
||||
let symbol = captures[2].to_string();
|
||||
rel.insert(address, symbol);
|
||||
}
|
||||
} else if state == 1 {
|
||||
if head_re.is_match(line) {
|
||||
state = 2;
|
||||
let captures = head_re.captures(line).unwrap();
|
||||
name = captures[2].to_string();
|
||||
}
|
||||
} else if state == 2 {
|
||||
state = 1;
|
||||
if insn_re.is_match(line) {
|
||||
let captures = insn_re.captures(line).unwrap();
|
||||
let address = i64::from_str(&captures[1]).unwrap();
|
||||
a2n.insert(address, name.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
let file = match File::create(&postprocessed_dump) {
|
||||
Ok(x) => x,
|
||||
_ => return,
|
||||
};
|
||||
let mut out = BufWriter::new(file);
|
||||
let file = match File::open(program_dump) {
|
||||
Ok(x) => x,
|
||||
_ => return,
|
||||
};
|
||||
let mut pc = 0u64;
|
||||
let mut step = 0u64;
|
||||
for line_result in BufReader::new(file).lines() {
|
||||
let line = line_result.unwrap();
|
||||
let line = line.trim_end();
|
||||
if head_re.is_match(line) {
|
||||
let captures = head_re.captures(line).unwrap();
|
||||
pc = u64::from_str_radix(&captures[1], 16).unwrap();
|
||||
writeln!(out, "{}", line).unwrap();
|
||||
continue;
|
||||
}
|
||||
if insn_re.is_match(line) {
|
||||
let captures = insn_re.captures(line).unwrap();
|
||||
step = if captures[2].len() > 24 { 16 } else { 8 };
|
||||
}
|
||||
if call_re.is_match(line) {
|
||||
if rel.contains_key(&pc) {
|
||||
writeln!(out, "{} ; {}", line, rel[&pc]).unwrap();
|
||||
} else {
|
||||
let captures = call_re.captures(line).unwrap();
|
||||
let pc = i64::from_str(&captures[1]).unwrap().checked_add(1).unwrap();
|
||||
let offset = i64::from_str_radix(&captures[4], 16).unwrap();
|
||||
let offset = if &captures[3] == "-" {
|
||||
offset.checked_neg().unwrap()
|
||||
} else {
|
||||
offset
|
||||
};
|
||||
let address = pc.checked_add(offset).unwrap();
|
||||
if a2n.contains_key(&address) {
|
||||
writeln!(out, "{} ; {}", line, a2n[&address]).unwrap();
|
||||
} else {
|
||||
writeln!(out, "{}", line).unwrap();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
writeln!(out, "{}", line).unwrap();
|
||||
}
|
||||
pc = pc.checked_add(step).unwrap();
|
||||
}
|
||||
fs::rename(postprocessed_dump, program_dump).unwrap();
|
||||
}
|
||||
|
||||
// check whether custom BPF toolchain is linked, and link it if it is not.
|
||||
fn link_bpf_toolchain(config: &Config) {
|
||||
let toolchain_path = config
|
||||
|
@ -366,6 +466,7 @@ fn build_bpf_package(config: &Config, target_directory: &Path, package: &cargo_m
|
|||
&config.bpf_sdk.join("scripts").join("dump.sh"),
|
||||
&[&program_unstripped_so, &program_dump],
|
||||
);
|
||||
postprocess_dump(&program_dump);
|
||||
}
|
||||
|
||||
println!();
|
||||
|
|
Loading…
Reference in New Issue