Remove need to process shared library and remove some unneeded metadata

This commit is contained in:
Brendan Hansknecht 2021-08-27 18:06:41 -07:00
parent 79bd82d51e
commit 428b77c568
2 changed files with 31 additions and 75 deletions

View file

@ -121,13 +121,6 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
let time = matches.is_present(FLAG_TIME); let time = matches.is_present(FLAG_TIME);
let total_start = SystemTime::now(); let total_start = SystemTime::now();
let shared_lib_processing_start = SystemTime::now();
let app_functions = roc_application_functions(&matches.value_of(SHARED_LIB).unwrap())?;
if verbose {
println!("Found roc app functions: {:?}", app_functions);
}
let shared_lib_processing_duration = shared_lib_processing_start.elapsed().unwrap();
let exec_parsing_start = SystemTime::now(); let exec_parsing_start = SystemTime::now();
let exec_file = fs::File::open(&matches.value_of(EXEC).unwrap())?; let exec_file = fs::File::open(&matches.value_of(EXEC).unwrap())?;
let exec_mmap = unsafe { Mmap::map(&exec_file)? }; let exec_mmap = unsafe { Mmap::map(&exec_file)? };
@ -238,11 +231,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
let app_syms: Vec<Symbol> = exec_obj let app_syms: Vec<Symbol> = exec_obj
.dynamic_symbols() .dynamic_symbols()
.filter(|sym| { .filter(|sym| {
let name = sym.name(); sym.is_undefined() && sym.name().is_ok() && sym.name().unwrap().starts_with("roc_")
// Note: We are scrapping version information like '@GLIBC_2.2.5'
// We probably never need to remedy this due to the focus on Roc only.
name.is_ok()
&& app_functions.contains(&name.unwrap().split('@').next().unwrap().to_string())
}) })
.collect(); .collect();
for sym in app_syms.iter() { for sym in app_syms.iter() {
@ -476,7 +465,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
.unwrap(); .unwrap();
let mut dyn_lib_index = 0; let mut dyn_lib_index = 0;
let mut shared_lib_found = false; let mut shared_lib_index = None;
loop { loop {
let dyn_tag = u64::from_le_bytes( let dyn_tag = u64::from_le_bytes(
<[u8; 8]>::try_from( <[u8; 8]>::try_from(
@ -497,8 +486,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
let c_buf: *const c_char = dynstr_data[dynstr_off..].as_ptr() as *const i8; let c_buf: *const c_char = dynstr_data[dynstr_off..].as_ptr() as *const i8;
let c_str = unsafe { CStr::from_ptr(c_buf) }.to_str().unwrap(); let c_str = unsafe { CStr::from_ptr(c_buf) }.to_str().unwrap();
if c_str == shared_lib_name { if c_str == shared_lib_name {
shared_lib_found = true; shared_lib_index = Some(dyn_lib_index);
md.shared_lib_index = dyn_lib_index as u64;
if verbose { if verbose {
println!( println!(
"Found shared lib in dynamic table at index: {}", "Found shared lib in dynamic table at index: {}",
@ -510,12 +498,13 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
dyn_lib_index += 1; dyn_lib_index += 1;
} }
md.dynamic_lib_count = dyn_lib_index as u64; let dynamic_lib_count = dyn_lib_index as usize;
if !shared_lib_found { if shared_lib_index.is_none() {
println!("Shared lib not found as a dependency of the executable"); println!("Shared lib not found as a dependency of the executable");
return Ok(-1); return Ok(-1);
} }
let shared_lib_index = shared_lib_index.unwrap();
let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed().unwrap(); let scanning_dynamic_deps_duration = scanning_dynamic_deps_start.elapsed().unwrap();
@ -596,7 +585,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
md.added_byte_count = md.added_byte_count md.added_byte_count = md.added_byte_count
+ (MIN_FUNC_ALIGNMENT as u64 - md.added_byte_count % MIN_FUNC_ALIGNMENT as u64); + (MIN_FUNC_ALIGNMENT as u64 - md.added_byte_count % MIN_FUNC_ALIGNMENT as u64);
let ph_end = ph_offset as usize + ph_num as usize * ph_ent_size as usize; let ph_end = ph_offset as usize + ph_num as usize * ph_ent_size as usize;
md.physical_shift_start = ph_end as u64; let physical_shift_start = ph_end as u64;
md.exec_len = exec_data.len() as u64 + md.added_byte_count; md.exec_len = exec_data.len() as u64 + md.added_byte_count;
let out_file = fs::OpenOptions::new() let out_file = fs::OpenOptions::new()
@ -616,12 +605,13 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
ph_num as usize, ph_num as usize,
); );
let mut first_load_found = false; let mut first_load_found = false;
let mut virtual_shift_start = 0;
for ph in program_headers.iter() { for ph in program_headers.iter() {
let p_type = ph.p_type.get(NativeEndian); let p_type = ph.p_type.get(NativeEndian);
if p_type == elf::PT_LOAD && ph.p_offset.get(NativeEndian) == 0 { if p_type == elf::PT_LOAD && ph.p_offset.get(NativeEndian) == 0 {
first_load_found = true; first_load_found = true;
md.load_align_constraint = ph.p_align.get(NativeEndian); md.load_align_constraint = ph.p_align.get(NativeEndian);
md.virtual_shift_start = md.physical_shift_start + ph.p_vaddr.get(NativeEndian); virtual_shift_start = physical_shift_start + ph.p_vaddr.get(NativeEndian);
} }
} }
if !first_load_found { if !first_load_found {
@ -632,7 +622,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
if verbose { if verbose {
println!( println!(
"Shifting all data after: 0x{:x}(0x{:x})", "Shifting all data after: 0x{:x}(0x{:x})",
md.physical_shift_start, md.virtual_shift_start physical_shift_start, virtual_shift_start
); );
} }
@ -662,11 +652,11 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
); );
} else { } else {
// Shift if needed. // Shift if needed.
if md.physical_shift_start <= p_offset { if physical_shift_start <= p_offset {
ph.p_offset = endian::U64::new(LittleEndian, p_offset + md.added_byte_count); ph.p_offset = endian::U64::new(LittleEndian, p_offset + md.added_byte_count);
} }
let p_vaddr = ph.p_vaddr.get(NativeEndian); let p_vaddr = ph.p_vaddr.get(NativeEndian);
if md.virtual_shift_start <= p_vaddr { if virtual_shift_start <= p_vaddr {
ph.p_vaddr = endian::U64::new(LittleEndian, p_vaddr + md.added_byte_count); ph.p_vaddr = endian::U64::new(LittleEndian, p_vaddr + md.added_byte_count);
ph.p_paddr = endian::U64::new(LittleEndian, p_vaddr + md.added_byte_count); ph.p_paddr = endian::U64::new(LittleEndian, p_vaddr + md.added_byte_count);
} }
@ -682,8 +672,8 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
.unwrap(); .unwrap();
// Copy the rest of the file shifted as needed. // Copy the rest of the file shifted as needed.
out_mmap[md.physical_shift_start as usize + md.added_byte_count as usize..] out_mmap[physical_shift_start as usize + md.added_byte_count as usize..]
.copy_from_slice(&exec_data[md.physical_shift_start as usize..]); .copy_from_slice(&exec_data[physical_shift_start as usize..]);
// Update all sections for shift for extra program headers. // Update all sections for shift for extra program headers.
let section_headers = load_structs_inplace_mut::<elf::SectionHeader64<LittleEndian>>( let section_headers = load_structs_inplace_mut::<elf::SectionHeader64<LittleEndian>>(
@ -697,10 +687,10 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
for sh in section_headers.iter_mut() { for sh in section_headers.iter_mut() {
let sh_offset = sh.sh_offset.get(NativeEndian); let sh_offset = sh.sh_offset.get(NativeEndian);
let sh_addr = sh.sh_addr.get(NativeEndian); let sh_addr = sh.sh_addr.get(NativeEndian);
if md.physical_shift_start <= sh_offset { if physical_shift_start <= sh_offset {
sh.sh_offset = endian::U64::new(LittleEndian, sh_offset + md.added_byte_count); sh.sh_offset = endian::U64::new(LittleEndian, sh_offset + md.added_byte_count);
} }
if md.virtual_shift_start <= sh_addr { if virtual_shift_start <= sh_addr {
sh.sh_addr = endian::U64::new(LittleEndian, sh_addr + md.added_byte_count); sh.sh_addr = endian::U64::new(LittleEndian, sh_addr + md.added_byte_count);
} }
@ -734,7 +724,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
); );
for rel in relocations.iter_mut() { for rel in relocations.iter_mut() {
let r_offset = rel.r_offset.get(NativeEndian); let r_offset = rel.r_offset.get(NativeEndian);
if md.virtual_shift_start <= r_offset { if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LittleEndian, r_offset + md.added_byte_count); rel.r_offset = endian::U64::new(LittleEndian, r_offset + md.added_byte_count);
} }
} }
@ -747,7 +737,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
); );
for rel in relocations.iter_mut() { for rel in relocations.iter_mut() {
let r_offset = rel.r_offset.get(NativeEndian); let r_offset = rel.r_offset.get(NativeEndian);
if md.virtual_shift_start <= r_offset { if virtual_shift_start <= r_offset {
rel.r_offset = endian::U64::new(LittleEndian, r_offset + md.added_byte_count); rel.r_offset = endian::U64::new(LittleEndian, r_offset + md.added_byte_count);
// Deal with potential adjusts to absolute jumps. // Deal with potential adjusts to absolute jumps.
match rel.r_type(LittleEndian, false) { match rel.r_type(LittleEndian, false) {
@ -765,13 +755,11 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
// Update dynamic table entries for shift for extra program headers. // Update dynamic table entries for shift for extra program headers.
let dyn_offset = md.dynamic_section_offset + md.added_byte_count; let dyn_offset = md.dynamic_section_offset + md.added_byte_count;
let dyn_lib_count = md.dynamic_lib_count as usize;
let shared_index = md.shared_lib_index as usize;
let dyns = load_structs_inplace_mut::<elf::Dyn64<LittleEndian>>( let dyns = load_structs_inplace_mut::<elf::Dyn64<LittleEndian>>(
&mut out_mmap, &mut out_mmap,
dyn_offset as usize, dyn_offset as usize,
dyn_lib_count, dynamic_lib_count,
); );
for mut d in dyns { for mut d in dyns {
match d.d_tag.get(NativeEndian) as u32 { match d.d_tag.get(NativeEndian) as u32 {
@ -806,7 +794,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
| elf::DT_VERDEF | elf::DT_VERDEF
| elf::DT_VERNEED => { | elf::DT_VERNEED => {
let d_addr = d.d_val.get(NativeEndian); let d_addr = d.d_val.get(NativeEndian);
if md.virtual_shift_start <= d_addr { if virtual_shift_start <= d_addr {
d.d_val = endian::U64::new(LittleEndian, d_addr + md.added_byte_count); d.d_val = endian::U64::new(LittleEndian, d_addr + md.added_byte_count);
} }
} }
@ -826,7 +814,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
for sym in symbols { for sym in symbols {
let addr = sym.st_value.get(NativeEndian); let addr = sym.st_value.get(NativeEndian);
if md.virtual_shift_start <= addr { if virtual_shift_start <= addr {
sym.st_value = endian::U64::new(LittleEndian, addr + md.added_byte_count); sym.st_value = endian::U64::new(LittleEndian, addr + md.added_byte_count);
} }
} }
@ -840,7 +828,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
); );
for go in global_offsets.iter_mut() { for go in global_offsets.iter_mut() {
let go_addr = go.get(NativeEndian); let go_addr = go.get(NativeEndian);
if md.physical_shift_start <= go_addr { if physical_shift_start <= go_addr {
go.set(LittleEndian, go_addr + md.added_byte_count); go.set(LittleEndian, go_addr + md.added_byte_count);
} }
} }
@ -852,9 +840,9 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
let out_ptr = out_mmap.as_mut_ptr(); let out_ptr = out_mmap.as_mut_ptr();
unsafe { unsafe {
std::ptr::copy( std::ptr::copy(
out_ptr.offset((dyn_offset as usize + 16 * (shared_index + 1)) as isize), out_ptr.offset((dyn_offset as usize + 16 * (shared_lib_index + 1)) as isize),
out_ptr.offset((dyn_offset as usize + 16 * shared_index) as isize), out_ptr.offset((dyn_offset as usize + 16 * shared_lib_index) as isize),
16 * (dyn_lib_count - shared_index), 16 * (dynamic_lib_count - shared_lib_index),
); );
} }
@ -866,7 +854,7 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
file_header.e_shoff.get(NativeEndian) + md.added_byte_count, file_header.e_shoff.get(NativeEndian) + md.added_byte_count,
); );
let e_entry = file_header.e_entry.get(NativeEndian); let e_entry = file_header.e_entry.get(NativeEndian);
if md.virtual_shift_start <= e_entry { if virtual_shift_start <= e_entry {
file_header.e_entry = endian::U64::new(LittleEndian, e_entry + md.added_byte_count); file_header.e_entry = endian::U64::new(LittleEndian, e_entry + md.added_byte_count);
} }
file_header.e_phnum = endian::U16::new(LittleEndian, ph_num + added_header_count as u16); file_header.e_phnum = endian::U16::new(LittleEndian, ph_num + added_header_count as u16);
@ -896,7 +884,6 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
if verbose || time { if verbose || time {
println!(); println!();
println!("Timings"); println!("Timings");
report_timing("Shared Library Processing", shared_lib_processing_duration);
report_timing("Executable Parsing", exec_parsing_duration); report_timing("Executable Parsing", exec_parsing_duration);
report_timing( report_timing(
"Symbol and PLT Processing", "Symbol and PLT Processing",
@ -910,7 +897,6 @@ pub fn preprocess(matches: &ArgMatches) -> io::Result<i32> {
report_timing( report_timing(
"Other", "Other",
total_duration total_duration
- shared_lib_processing_duration
- exec_parsing_duration - exec_parsing_duration
- symbol_and_plt_processing_duration - symbol_and_plt_processing_duration
- text_disassembly_duration - text_disassembly_duration
@ -1473,29 +1459,3 @@ fn load_structs_inplace_mut<'a, T>(
assert!(tail.is_empty(), "End of data was not aligned"); assert!(tail.is_empty(), "End of data was not aligned");
body body
} }
fn roc_application_functions(shared_lib_name: &str) -> io::Result<Vec<String>> {
let shared_file = fs::File::open(&shared_lib_name)?;
let shared_mmap = unsafe { Mmap::map(&shared_file)? };
let shared_obj = object::File::parse(&*shared_mmap).map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Failed to parse shared library file: {}", err),
)
})?;
Ok(shared_obj
.exports()
.unwrap()
.into_iter()
.map(|export| String::from_utf8(export.name().to_vec()))
.collect::<Result<Vec<_>, _>>()
.map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Failed to load function names from shared library: {}", err),
)
})?
.into_iter()
.filter(|name| name.starts_with("roc_"))
.collect::<Vec<_>>())
}

View file

@ -20,16 +20,12 @@ pub struct Metadata {
pub surgeries: MutMap<String, Vec<SurgeryEntry>>, pub surgeries: MutMap<String, Vec<SurgeryEntry>>,
pub dynamic_symbol_indices: MutMap<String, u64>, pub dynamic_symbol_indices: MutMap<String, u64>,
pub roc_symbol_vaddresses: MutMap<String, u64>, pub roc_symbol_vaddresses: MutMap<String, u64>,
pub exec_len: u64,
pub load_align_constraint: u64,
pub added_byte_count: u64,
pub last_vaddr: u64,
pub dynamic_section_offset: u64, pub dynamic_section_offset: u64,
pub dynamic_lib_count: u64, pub dynamic_symbol_table_section_offset: u64,
pub shared_lib_index: u64,
pub symbol_table_section_offset: u64, pub symbol_table_section_offset: u64,
pub symbol_table_size: u64, pub symbol_table_size: u64,
pub dynamic_symbol_table_section_offset: u64,
pub load_align_constraint: u64,
pub physical_shift_start: u64,
pub virtual_shift_start: u64,
pub added_byte_count: u64,
pub exec_len: u64,
pub last_vaddr: u64,
} }