Support duplicate filenames in ELF loader

This commit is contained in:
Luke Street 2022-12-27 18:22:27 -05:00
parent 9f4cc2f542
commit d76c554d31
1 changed files with 20 additions and 4 deletions

View File

@ -1,4 +1,8 @@
use std::{collections::BTreeMap, fs::File, path::Path};
use std::{
collections::{hash_map, BTreeMap, HashMap},
fs::File,
path::Path,
};
use anyhow::{Context, Error, Result};
use cwdemangle::demangle;
@ -74,6 +78,7 @@ pub fn process_elf<P: AsRef<Path>>(path: P) -> Result<ObjInfo> {
relocations: vec![],
original_address: 0, // TODO load from abs symbol
file_offset: section.file_range().map(|(v, _)| v).unwrap_or_default(),
section_known: true,
});
}
@ -81,6 +86,7 @@ pub fn process_elf<P: AsRef<Path>>(path: P) -> Result<ObjInfo> {
let mut symbol_indexes: Vec<Option<usize>> = vec![];
let mut current_file: Option<String> = None;
let mut section_starts = IndexMap::<String, Vec<(u64, String)>>::new();
let mut name_to_index = HashMap::<String, usize>::new(); // for resolving duplicate names
for symbol in obj_file.symbols() {
// Locate linker-generated symbols
let symbol_name = symbol.name()?;
@ -106,15 +112,25 @@ pub fn process_elf<P: AsRef<Path>>(path: P) -> Result<ObjInfo> {
match symbol.kind() {
// Detect file boundaries
SymbolKind::File => {
let file_name = symbol_name.to_string();
let mut file_name = symbol_name.to_string();
if kind == ObjKind::Relocatable {
obj_name = file_name.clone();
}
match section_starts.entry(file_name.clone()) {
indexmap::map::Entry::Occupied(_) => {
return Err(Error::msg(format!("Duplicate file name: {file_name}")));
let index = match name_to_index.entry(file_name.clone()) {
hash_map::Entry::Occupied(mut e) => e.into_mut(),
hash_map::Entry::Vacant(e) => e.insert(0),
};
*index += 1;
let new_name = format!("{}_{}", file_name, index);
log::info!("Renaming {} to {}", file_name, new_name);
section_starts.insert(new_name.clone(), Default::default());
file_name = new_name;
}
indexmap::map::Entry::Vacant(e) => {
e.insert(Default::default());
}
indexmap::map::Entry::Vacant(e) => e.insert(Default::default()),
};
current_file = Some(file_name);
}