summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-11-07 18:55:13 -0500
committerpommicket <pommicket@gmail.com>2022-11-07 18:55:13 -0500
commite02ed40851251064e907b91eec7cea6b89d3c186 (patch)
treeadad90f37de0353a1055e027be21b8a283d0cbe7
parent92d99e53620fa9d8ff8d2a8a453bb3089f78e661 (diff)
working almost the same as before
-rw-r--r--src/elf.rs56
-rw-r--r--src/linker.rs13
2 files changed, 42 insertions, 27 deletions
diff --git a/src/elf.rs b/src/elf.rs
index 6e4dcbc..e9b3c98 100644
--- a/src/elf.rs
+++ b/src/elf.rs
@@ -396,7 +396,7 @@ pub enum SymbolValue {
#[derive(Debug, Clone)]
pub struct Symbol {
- name: u64, // offset into .strtab
+ name: String,
pub size: u64,
pub value: SymbolValue,
pub bind: SymbolBind,
@@ -467,8 +467,6 @@ pub struct Reader32LE {
ehdr: Ehdr32,
shdrs: Vec<Shdr32>,
symbols: Vec<Symbol>,
- /// index of .strtab section
- strtab_idx: Option<u16>,
/// All data in the file.
/// We put it all in memory.
/// Object files usually aren't huge or anything.
@@ -528,6 +526,9 @@ impl Reader for Reader32LE {
let mut symbols = vec![];
let mut strtab_idx = None;
+ let mut section_names = Vec::with_capacity(ehdr.shnum.into());
+
+ // read section names, find .strtab
for (s_idx, shdr) in shdrs.iter().enumerate() {
if let Some(shstrhdr) = shdrs.get(ehdr.shstrndx as usize) {
// get name
@@ -538,13 +539,16 @@ impl Reader for Reader32LE {
reader.read_until(0, &mut bytes)?;
bytes.pop(); // remove terminating \0
let name = bytes_to_string(bytes)?;
-
if name == ".strtab" {
- // since shdrs.len() == ehdr.shnum, this should never panic.
- strtab_idx = Some(s_idx.try_into().unwrap());
+ strtab_idx = Some(s_idx);
}
- }
+
+ section_names.push(name);
+ }
+ }
+
+ for shdr in shdrs.iter() {
let mut symtab = vec![];
if shdr.r#type == SHT_SYMTAB && shdr.entsize as usize >= mem::size_of::<Sym32>() {
// read symbol table
@@ -566,15 +570,36 @@ impl Reader for Reader32LE {
// section symbols have a size of 0, it seems.
// i don't know why they don't just use the size of the section.
// i'm replacing it here. it makes the code easier to write.
- size = shdrs[idx as usize].size.into();
+ size = shdrs[usize::from(idx)].size.into();
}
SymbolValue::SectionOffset(idx, sym.value.into())
}
x => return Err(BadSymShNdx(x)),
};
-
+
+ let mut name = {
+ let strtab_offset = shdrs[strtab_idx.ok_or(Error::NoStrtab)?].offset;
+ let strtab = &data.get(strtab_offset as usize..)
+ .ok_or(Error::NoStrtab)?;
+ let i = sym.name as usize;
+ let mut end = i;
+ while end < strtab.len() && strtab[end] != b'\0' {
+ end += 1;
+ }
+ bytes_to_string(strtab[i..end].to_vec())?
+ };
+
+ if name.is_empty() {
+ if r#type == SymbolType::Section {
+ // section symbols have empty names.
+ // this makes sense, since you don't want to repeat the strings in .strtab and .shstrtab
+ // but i don't know why .strtab and .shstrtab are separate....
+ name = section_names[usize::from(sym.shndx)].clone();
+ }
+ }
+
let symbol = Symbol {
- name: sym.name.into(),
+ name,
value,
r#type,
bind,
@@ -652,7 +677,6 @@ impl Reader for Reader32LE {
ehdr,
shdrs,
symbols,
- strtab_idx,
relocations,
data,
})
@@ -679,15 +703,7 @@ impl Reader for Reader32LE {
}
fn symbol_name(&self, sym: &Symbol) -> Result<String> {
- let strtab_offset = self.shdrs[usize::from(self.strtab_idx.ok_or(Error::NoStrtab)?)].offset;
- let strtab = &self.data.get(strtab_offset as usize..)
- .ok_or(Error::NoStrtab)?;
- let i = sym.name as usize;
- let mut end = i;
- while end < strtab.len() && strtab[end] != b'\0' {
- end += 1;
- }
- bytes_to_string(strtab[i..end].to_vec())
+ Ok(sym.name.clone())
}
fn section_type(&self, idx: u16) -> Option<SectionType> {
diff --git a/src/linker.rs b/src/linker.rs
index 9666a87..2a7ef42 100644
--- a/src/linker.rs
+++ b/src/linker.rs
@@ -857,16 +857,17 @@ impl<'a> Linker<'a> {
symbol: &elf::Symbol,
) -> Result<(), ObjectError> {
let name = elf.symbol_name(symbol)?;
+// let dbg_name = name.clone();
let name_id = self.symbol_names.add(name);
let size = symbol.size;
let value = match symbol.value {
elf::SymbolValue::Undefined => None,
elf::SymbolValue::Absolute(n) => Some(SymbolValue::Absolute(n)),
- elf::SymbolValue::SectionOffset(shndx, offset) => {
+ elf::SymbolValue::SectionOffset(shndx, sec_offset) => {
match elf.section_type(shndx) {
Some(elf::SectionType::ProgBits) => {
- let offset = elf.section_offset(shndx).unwrap() + offset;
+ let offset = elf.section_offset(shndx).unwrap() + sec_offset;
Some(SymbolValue::Data { source, offset, size })
}
Some(elf::SectionType::NoBits) => {
@@ -1117,6 +1118,7 @@ impl<'a> Linker<'a> {
if let Some(symbol) = self.get_symbol_id(rel.r#where.0, rel.sym) {
let value = &self.symbols.get_info_from_id(symbol).value;
if let SymbolValue::Data { source: req_source, offset: req_offset, size: req_size } = value {
+ // @TODO: check addend
self.require_range(ranges, *req_source, *req_offset, *req_size)
} // else, it's okay, it's a bss relocation or something hopefully
} // else, we'll deal with it in apply_relocation
@@ -1166,15 +1168,13 @@ impl<'a> Linker<'a> {
let dest_end = dest_start + size as usize;
let src_start = src_offset as usize;
let src_end = src_start + size as usize;
- let dest_addr = dest_offset + exec.data_addr();
- println!("{source:?}@{src_offset:x} => {:x}..{:x}", dest_addr,dest_addr+size);
+ //let dest_addr = dest_offset + exec.data_addr();
+ //println!("{source:?}@{src_offset:x} => {:x}..{:x}", dest_addr,dest_addr+size);
data_section[dest_start..dest_end].copy_from_slice(
&self.source_data[source.0 as usize][src_start..src_end]
);
});
- println!("{:?}", data_section);
-
exec.set_data(data_section);
for rel_map in self.relocations.iter() {
@@ -1182,7 +1182,6 @@ impl<'a> Linker<'a> {
self.apply_relocation(&mut exec, &offset_map, rel)?;
}
}
- println!("{:?}", exec.data);
// this should never panic, since we did require_range on the entry point.
let entry_addr = offset_map.translate_offset(entry_source, entry_offset).unwrap() + exec.data_addr();