diff options
author | pommicket <pommicket@gmail.com> | 2022-11-07 18:55:13 -0500 |
---|---|---|
committer | pommicket <pommicket@gmail.com> | 2022-11-07 18:55:13 -0500 |
commit | e02ed40851251064e907b91eec7cea6b89d3c186 (patch) | |
tree | adad90f37de0353a1055e027be21b8a283d0cbe7 | |
parent | 92d99e53620fa9d8ff8d2a8a453bb3089f78e661 (diff) |
working almost the same as before
-rw-r--r-- | src/elf.rs | 56 | ||||
-rw-r--r-- | src/linker.rs | 13 |
2 files changed, 42 insertions, 27 deletions
@@ -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(); |