diff --git a/examples/nm.rs b/examples/nm.rs index c13d867..ff6dd0d 100644 --- a/examples/nm.rs +++ b/examples/nm.rs @@ -1,4 +1,5 @@ -use object::{Object, SectionKind, Symbol, SymbolKind}; +use object::{Object, ObjectSection, SectionIndex, SectionKind, Symbol, SymbolKind}; +use std::collections::HashMap; use std::{env, fs, process}; fn main() { @@ -36,25 +37,30 @@ fn main() { } }; + let section_kinds = file.sections().map(|s| (s.index(), s.kind())).collect(); + println!("Debugging symbols:"); for symbol in file.symbols() { - print_symbol(&symbol); + print_symbol(&symbol, §ion_kinds); } println!(); println!("Dynamic symbols:"); for symbol in file.dynamic_symbols() { - print_symbol(&symbol); + print_symbol(&symbol, §ion_kinds); } } } -fn print_symbol(symbol: &Symbol<'_>) { +fn print_symbol(symbol: &Symbol<'_>, section_kinds: &HashMap) { if let SymbolKind::Section | SymbolKind::File = symbol.kind() { return; } - let mut kind = match symbol.section_kind() { + let mut kind = match symbol + .section_index() + .and_then(|index| section_kinds.get(&index)) + { Some(SectionKind::Unknown) => '?', Some(SectionKind::Text) => 't', Some(SectionKind::Data) => 'd', diff --git a/src/elf.rs b/src/elf.rs index 75f0fbc..fdf2ce4 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -74,7 +74,6 @@ where { strtab: &'file strtab::Strtab<'data>, symbols: elf::sym::SymIterator<'data>, - section_kinds: Vec, } /// An iterator over the relocations in an `ElfSection`. @@ -193,18 +192,16 @@ where } fn symbol_by_index(&self, index: u64) -> Option> { - // TODO: determine section_kind too self.elf .syms .get(index as usize) - .map(|symbol| parse_symbol(&symbol, &self.elf.strtab, &[])) + .map(|symbol| parse_symbol(&symbol, &self.elf.strtab)) } fn symbols(&'file self) -> ElfSymbolIterator<'data, 'file> { ElfSymbolIterator { strtab: &self.elf.strtab, symbols: self.elf.syms.iter(), - section_kinds: self.sections().map(|x| x.kind()).collect(), } } @@ -212,7 +209,6 @@ where ElfSymbolIterator { strtab: &self.elf.dynstrtab, symbols: self.elf.dynsyms.iter(), - section_kinds: self.sections().map(|x| x.kind()).collect(), } } @@ -498,15 +494,11 @@ impl<'data, 'file> Iterator for ElfSymbolIterator<'data, 'file> { fn next(&mut self) -> Option { self.symbols .next() - .map(|symbol| parse_symbol(&symbol, self.strtab, &self.section_kinds)) + .map(|symbol| parse_symbol(&symbol, self.strtab)) } } -fn parse_symbol<'data>( - symbol: &elf::sym::Sym, - strtab: &strtab::Strtab<'data>, - section_kinds: &[SectionKind], -) -> Symbol<'data> { +fn parse_symbol<'data>(symbol: &elf::sym::Sym, strtab: &strtab::Strtab<'data>) -> Symbol<'data> { let name = strtab.get(symbol.st_name).and_then(Result::ok); let kind = match elf::sym::st_type(symbol.st_info) { elf::sym::STT_OBJECT => SymbolKind::Data, @@ -517,26 +509,20 @@ fn parse_symbol<'data>( elf::sym::STT_TLS => SymbolKind::Tls, _ => SymbolKind::Unknown, }; - let section_index = if symbol.st_shndx == elf::section_header::SHN_UNDEF as usize - || symbol.st_shndx >= elf::section_header::SHN_LORESERVE as usize - { - None - } else { - Some(SectionIndex(symbol.st_shndx)) - }; - let section_kind = section_index.map(|index| { - section_kinds - .get(index.0) - .cloned() - .unwrap_or(SectionKind::Unknown) - }); + let undefined = symbol.st_shndx == elf::section_header::SHN_UNDEF as usize; + let section_index = + if undefined || symbol.st_shndx >= elf::section_header::SHN_LORESERVE as usize { + None + } else { + Some(SectionIndex(symbol.st_shndx)) + }; Symbol { name, address: symbol.st_value, size: symbol.st_size, kind, section_index, - section_kind, + undefined, global: elf::sym::st_bind(symbol.st_info) != elf::sym::STB_LOCAL, } } diff --git a/src/lib.rs b/src/lib.rs index 6bf90fc..4c29e72 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -231,7 +231,7 @@ where pub struct Symbol<'data> { kind: SymbolKind, section_index: Option, - section_kind: Option, + undefined: bool, global: bool, name: Option<&'data str>, address: u64, @@ -636,16 +636,10 @@ impl<'data> Symbol<'data> { self.section_index } - /// Returns the section kind for the symbol, or `None` if the symbol is undefined. - #[inline] - pub fn section_kind(&self) -> Option { - self.section_kind - } - /// Return true if the symbol is undefined. #[inline] pub fn is_undefined(&self) -> bool { - self.section_kind.is_none() + self.undefined } /// Return true if the symbol is global. diff --git a/src/macho.rs b/src/macho.rs index b4db4d8..0edfaff 100644 --- a/src/macho.rs +++ b/src/macho.rs @@ -66,7 +66,6 @@ where /// An iterator over the symbols of a `MachOFile`. pub struct MachOSymbolIterator<'data> { symbols: mach::symbols::SymbolIterator<'data>, - section_kinds: Vec, } /// An iterator over the relocations in an `MachOSection`. @@ -161,12 +160,11 @@ where } fn symbol_by_index(&self, index: u64) -> Option> { - // TODO: determine section_kind too self.macho .symbols .as_ref() .and_then(|symbols| symbols.get(index as usize).ok()) - .and_then(|(name, nlist)| parse_symbol(name, &nlist, &[])) + .and_then(|(name, nlist)| parse_symbol(name, &nlist)) } fn symbols(&'file self) -> MachOSymbolIterator<'data> { @@ -175,12 +173,7 @@ where None => mach::symbols::SymbolIterator::default(), }; - let section_kinds = self.sections().map(|section| section.kind()).collect(); - - MachOSymbolIterator { - symbols, - section_kinds, - } + MachOSymbolIterator { symbols } } fn dynamic_symbols(&'file self) -> MachOSymbolIterator<'data> { @@ -200,7 +193,7 @@ where size: 0, kind: SymbolKind::Section, section_index: None, - section_kind: None, + undefined: false, global: false, }); } @@ -401,7 +394,7 @@ impl<'data> Iterator for MachOSymbolIterator<'data> { fn next(&mut self) -> Option { while let Some(Ok((name, nlist))) = self.symbols.next() { - let symbol = parse_symbol(name, &nlist, &self.section_kinds); + let symbol = parse_symbol(name, &nlist); if symbol.is_some() { return symbol; } @@ -410,11 +403,7 @@ impl<'data> Iterator for MachOSymbolIterator<'data> { } } -fn parse_symbol<'data>( - name: &'data str, - nlist: &mach::symbols::Nlist, - section_kinds: &[SectionKind], -) -> Option> { +fn parse_symbol<'data>(name: &'data str, nlist: &mach::symbols::Nlist) -> Option> { if nlist.n_type & mach::symbols::N_STAB != 0 { return None; } @@ -429,27 +418,14 @@ fn parse_symbol<'data>( // TODO: better handling for other n_type values None }; - let section_kind = section_index.map(|index| { - section_kinds - .get(index.0 - 1) - .cloned() - .unwrap_or(SectionKind::Unknown) - }); - let kind = match section_kind { - Some(SectionKind::Text) => SymbolKind::Text, - Some(SectionKind::Data) - | Some(SectionKind::ReadOnlyData) - | Some(SectionKind::UninitializedData) => SymbolKind::Data, - _ => SymbolKind::Unknown, - }; Some(Symbol { name: Some(name), address: nlist.n_value, // Only calculated for symbol maps size: 0, - kind, + kind: SymbolKind::Unknown, section_index, - section_kind, + undefined: nlist.is_undefined(), global: nlist.is_global(), }) } diff --git a/src/pe.rs b/src/pe.rs index 5752e1b..a13989e 100644 --- a/src/pe.rs +++ b/src/pe.rs @@ -298,7 +298,7 @@ impl<'data, 'file> Iterator for PeSymbolIterator<'data, 'file> { kind: SymbolKind::Unknown, // TODO: can we find a section? section_index: None, - section_kind: Some(SectionKind::Unknown), + undefined: false, global: true, name: export.name, address: export.rva as u64, @@ -313,7 +313,7 @@ impl<'data, 'file> Iterator for PeSymbolIterator<'data, 'file> { return Some(Symbol { kind: SymbolKind::Unknown, section_index: None, - section_kind: None, + undefined: true, global: true, name, address: 0,