Skip to content

Commit

Permalink
Reuse find_the_answer_fn() logic more
Browse files Browse the repository at this point in the history
Split the find_the_answer_fn() function into a zip variant and a
"regular" ELF one. Then use the ELF variant in tests that copied the
same logic in-line.

Signed-off-by: Daniel Müller <deso@posteo.net>
  • Loading branch information
d-e-s-o committed Jun 5, 2024
1 parent 7961f17 commit 08270df
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 71 deletions.
56 changes: 6 additions & 50 deletions src/normalize/normalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,13 +285,10 @@ impl Normalizer {
mod tests {
use super::*;

use std::mem::transmute;
use std::path::Path;

use test_log::test;

use crate::elf::ElfParser;
use crate::inspect::FindAddrOpts;
use crate::mmap::Mmap;
use crate::normalize::buildid::read_elf_build_id;
use crate::normalize::Apk;
Expand All @@ -301,8 +298,8 @@ mod tests {
use crate::normalize::UserMeta;
use crate::symbolize;
use crate::symbolize::Symbolizer;
use crate::test_helper::find_the_answer_fn;
use crate::zip;
use crate::SymType;


/// Check that we detect unsorted input addresses.
Expand Down Expand Up @@ -400,25 +397,7 @@ mod tests {
.join("libtest-so.so");

let mmap = Mmap::builder().exec().open(&test_so).unwrap();
// Look up the address of the `the_answer` function inside of the shared
// object.
let elf_parser = ElfParser::from_mmap(mmap.clone(), Some(test_so));
let opts = FindAddrOpts {
sym_type: SymType::Function,
..Default::default()
};
let syms = elf_parser.find_addr("the_answer", &opts).unwrap();
// There is only one symbol with this address in there.
assert_eq!(syms.len(), 1);
let sym = syms.first().unwrap();

let the_answer_addr = unsafe { mmap.as_ptr().add(sym.addr as usize) };
// Now just double check that everything worked out and the function
// is actually where it was meant to be.
let the_answer_fn =
unsafe { transmute::<_, extern "C" fn() -> libc::c_int>(the_answer_addr) };
let answer = the_answer_fn();
assert_eq!(answer, 42);
let (sym, the_answer_addr) = find_the_answer_fn(&mmap);

let opts = NormalizeOpts {
sorted_addrs: true,
Expand All @@ -434,12 +413,9 @@ mod tests {
let output = normalized.outputs[0];
assert_eq!(output.0, sym.addr);
let meta = &normalized.meta[output.1];
let so_path = Path::new(&env!("CARGO_MANIFEST_DIR"))
.join("data")
.join("libtest-so.so");
let expected_elf = Elf {
build_id: Some(read_elf_build_id(&so_path).unwrap().unwrap()),
path: so_path,
build_id: Some(read_elf_build_id(&test_so).unwrap().unwrap()),
path: test_so.clone(),
_non_exhaustive: (),
};
assert_eq!(meta, &UserMeta::Elf(expected_elf));
Expand Down Expand Up @@ -467,26 +443,7 @@ mod tests {
let elf_mmap = mmap
.constrain(so.data_offset..so.data_offset + so.data.len() as u64)
.unwrap();

// Look up the address of the `the_answer` function inside of the shared
// object.
let elf_parser = ElfParser::from_mmap(elf_mmap.clone(), Some(test_zip.clone()));
let opts = FindAddrOpts {
sym_type: SymType::Function,
offset_in_file: true,
};
let syms = elf_parser.find_addr("the_answer", &opts).unwrap();
// There is only one symbol with this address in there.
assert_eq!(syms.len(), 1);
let sym = syms.first().unwrap();

let the_answer_addr = unsafe { elf_mmap.as_ptr().add(sym.addr as usize) };
// Now just double check that everything worked out and the function
// is actually where it was meant to be.
let the_answer_fn =
unsafe { transmute::<_, extern "C" fn() -> libc::c_int>(the_answer_addr) };
let answer = the_answer_fn();
assert_eq!(answer, 42);
let (sym, the_answer_addr) = find_the_answer_fn(&elf_mmap);

let opts = NormalizeOpts {
sorted_addrs: true,
Expand All @@ -499,8 +456,7 @@ mod tests {
assert_eq!(normalized.outputs.len(), 1);
assert_eq!(normalized.meta.len(), 1);

let expected_offset =
so.data_offset + elf_parser.find_file_offset(sym.addr).unwrap().unwrap();
let expected_offset = so.data_offset + sym.file_offset.unwrap();
let output = normalized.outputs[0];
assert_eq!(output.0, expected_offset);
let meta = &normalized.meta[output.1];
Expand Down
8 changes: 4 additions & 4 deletions src/symbolize/symbolizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,7 +1376,7 @@ mod tests {

use crate::symbolize;
use crate::symbolize::CodeInfo;
use crate::test_helper::find_the_answer_fn;
use crate::test_helper::find_the_answer_fn_in_zip;

use test_log::test;

Expand Down Expand Up @@ -1522,7 +1522,7 @@ mod tests {
.join("test.zip");

let mmap = Mmap::builder().exec().open(test_zip).unwrap();
let (sym, the_answer_addr) = find_the_answer_fn(&mmap);
let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap);

// Symbolize the address we just looked up. It should be correctly
// mapped to the `the_answer` function within our process.
Expand Down Expand Up @@ -1564,7 +1564,7 @@ mod tests {
.join("test.zip");

let mmap = Mmap::builder().exec().open(test_zip).unwrap();
let (sym, the_answer_addr) = find_the_answer_fn(&mmap);
let (sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap);

let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf));
let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build();
Expand Down Expand Up @@ -1621,7 +1621,7 @@ mod tests {
.join("test.zip");

let mmap = Mmap::builder().exec().open(test_zip).unwrap();
let (_sym, the_answer_addr) = find_the_answer_fn(&mmap);
let (_sym, the_answer_addr) = find_the_answer_fn_in_zip(&mmap);

let src = symbolize::Source::Process(symbolize::Process::new(Pid::Slf));
let symbolizer = Symbolizer::builder().set_apk_dispatcher(dispatcher).build();
Expand Down
44 changes: 27 additions & 17 deletions src/test_helper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,33 +10,25 @@ use crate::Mmap;
use crate::SymType;


pub(crate) fn find_the_answer_fn(mmap: &Mmap) -> (inspect::SymInfo<'_>, Addr) {
let archive = zip::Archive::with_mmap(mmap.clone()).unwrap();
let so = archive
.entries()
.find_map(|entry| {
let entry = entry.unwrap();
(entry.path == Path::new("libtest-so.so")).then_some(entry)
})
.unwrap();

let elf_mmap = mmap
.constrain(so.data_offset..so.data_offset + so.data.len() as u64)
.unwrap();

/// Find the `the_answer` function inside the provided `mmap`, which is
/// expected to be the memory mapped `libtest-so.so`.
///
/// This function returns the symbol information of the function along
/// with it's absolute address in the memory mapped region.
pub(crate) fn find_the_answer_fn(mmap: &Mmap) -> (inspect::SymInfo<'static>, Addr) {
// Look up the address of the `the_answer` function inside of the shared
// object.
let elf_parser = ElfParser::from_mmap(elf_mmap.clone(), Some(PathBuf::from("libtest-so.so")));
let elf_parser = ElfParser::from_mmap(mmap.clone(), Some(PathBuf::from("libtest-so.so")));
let opts = inspect::FindAddrOpts {
offset_in_file: true,
sym_type: SymType::Function,
..Default::default()
};
let syms = elf_parser.find_addr("the_answer", &opts).unwrap();
// There is only one symbol with this address in there.
assert_eq!(syms.len(), 1);
let sym = syms.first().unwrap();

let the_answer_addr = unsafe { elf_mmap.as_ptr().add(sym.addr as usize) };
let the_answer_addr = unsafe { mmap.as_ptr().add(sym.addr as usize) };
// Now just double check that everything worked out and the function
// is actually where it was meant to be.
let the_answer_fn = unsafe { transmute::<_, extern "C" fn() -> libc::c_int>(the_answer_addr) };
Expand All @@ -45,3 +37,21 @@ pub(crate) fn find_the_answer_fn(mmap: &Mmap) -> (inspect::SymInfo<'_>, Addr) {

(sym.to_owned(), the_answer_addr as Addr)
}

pub(crate) fn find_the_answer_fn_in_zip(mmap: &Mmap) -> (inspect::SymInfo<'static>, Addr) {
let archive = zip::Archive::with_mmap(mmap.clone()).unwrap();
let so = archive
.entries()
.find_map(|entry| {
let entry = entry.unwrap();
(entry.path == Path::new("libtest-so.so")).then_some(entry)
})
.unwrap();

let elf_mmap = mmap
.constrain(so.data_offset..so.data_offset + so.data.len() as u64)
.unwrap();

let (sym, the_answer_addr) = find_the_answer_fn(&elf_mmap);
(sym, the_answer_addr)
}

0 comments on commit 08270df

Please sign in to comment.