Skip to content

Commit

Permalink
Augment BPF binary dumps to resolve call instruction targets
Browse files Browse the repository at this point in the history
  • Loading branch information
dmakarov committed Apr 12, 2021
1 parent 7ba3e71 commit 78d1d59
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 15 deletions.
21 changes: 7 additions & 14 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions sdk/cargo-build-bpf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
103 changes: 102 additions & 1 deletion sdk/cargo-build-bpf/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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!();
Expand Down

0 comments on commit 78d1d59

Please sign in to comment.