Skip to content

Commit

Permalink
Merge pull request #342 from philipc/version
Browse files Browse the repository at this point in the history
read/elf: version improvements
  • Loading branch information
philipc authored Aug 7, 2021
2 parents 69776ec + ff64ae2 commit ab39161
Show file tree
Hide file tree
Showing 9 changed files with 521 additions and 144 deletions.
150 changes: 103 additions & 47 deletions examples/readobj.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ mod elf {
use super::*;
use object::elf::*;
use object::read::elf::*;
use object::read::{SectionIndex, StringTable};

pub(super) fn print_elf32(p: &mut Printer<impl Write>, data: &[u8]) {
if let Ok(elf) = FileHeader32::<Endianness>::parse(data) {
Expand Down Expand Up @@ -434,10 +435,10 @@ mod elf {
strsz = d.d_val(endian).into();
}
}
let mut dynstr = object::StringTable::default();
let mut dynstr = StringTable::default();
for s in segments {
if let Ok(Some(data)) = s.data_range(endian, data, strtab, strsz) {
dynstr = object::StringTable::new(data, 0, data.len() as u64);
dynstr = StringTable::new(data, 0, data.len() as u64);
break;
}
}
Expand Down Expand Up @@ -492,8 +493,9 @@ mod elf {
sections: &SectionTable<Elf>,
) {
for (index, section) in sections.iter().enumerate() {
let index = SectionIndex(index);
p.group("SectionHeader", |p| {
p.field("Index", index);
p.field("Index", index.0);
p.field_string(
"Name",
section.sh_name(endian),
Expand Down Expand Up @@ -563,10 +565,15 @@ mod elf {
data: &[u8],
elf: &Elf,
sections: &SectionTable<Elf>,
section_index: usize,
section_index: SectionIndex,
section: &Elf::SectionHeader,
) {
if let Ok(Some(symbols)) = section.symbols(endian, data, sections, section_index) {
let versions = if section.sh_type(endian) == SHT_DYNSYM {
sections.versions(endian, data).ok()
} else {
None
};
let os_stt = match elf.e_ident().os_abi {
ELFOSABI_GNU => FLAGS_STT_GNU,
ELFOSABI_HPUX => FLAGS_STT_HP,
Expand Down Expand Up @@ -599,6 +606,13 @@ mod elf {
symbol.st_name(endian),
symbol.name(endian, symbols.strings()).ok(),
);
if let Some(versions) = versions.as_ref() {
let version_index = versions.version_index(endian, index);
if let Some(version) = versions.version(version_index) {
p.field_string("Version", version_index.0, Some(version.name()));
p.flags(version_index.0, 0, FLAGS_VERSYM);
}
}
p.field_hex("Value", symbol.st_value(endian).into());
p.field_hex("Size", symbol.st_size(endian).into());
p.field_enums("Type", symbol.st_type(), &[FLAGS_STT, os_stt, proc_stt]);
Expand Down Expand Up @@ -643,8 +657,8 @@ mod elf {
sections: &SectionTable<Elf>,
section: &Elf::SectionHeader,
) {
if let Ok(Some(relocations)) = section.rel(endian, data) {
let symbols = section.relocation_symbols(endian, data, sections).ok();
if let Ok(Some((relocations, link))) = section.rel(endian, data) {
let symbols = sections.symbol_table_by_index(endian, data, link).ok();
let proc = rel_flag_type(endian, elf);
for relocation in relocations {
p.group("Relocation", |p| {
Expand All @@ -665,8 +679,8 @@ mod elf {
sections: &SectionTable<Elf>,
section: &Elf::SectionHeader,
) {
if let Ok(Some(relocations)) = section.rela(endian, data) {
let symbols = section.relocation_symbols(endian, data, sections).ok();
if let Ok(Some((relocations, link))) = section.rela(endian, data) {
let symbols = sections.symbol_table_by_index(endian, data, link).ok();
let proc = rel_flag_type(endian, elf);
for relocation in relocations {
p.group("Relocation", |p| {
Expand Down Expand Up @@ -755,7 +769,7 @@ mod elf {
for member in members {
let index = member.get(endian);
p.print_indent();
if let Ok(section) = sections.section(index as usize) {
if let Ok(section) = sections.section(SectionIndex(index as usize)) {
if let Ok(name) = sections.section_name(endian, section) {
p.print_string(name);
writeln!(p.w, " ({})", index).unwrap();
Expand Down Expand Up @@ -811,17 +825,23 @@ mod elf {
});
}
/* TODO: add this in a test somewhere
if let Ok(Some(hash_table)) = section.hash(endian, data) {
if let Ok(symbols) = _sections.symbols(endian, data, SHT_DYNSYM) {
for symbol in symbols.symbols() {
let name = symbols.symbol_name(endian, symbol).unwrap();
if !symbol.is_definition(endian) {
continue;
if let Ok(Some((hash_table, link))) = section.hash(endian, data) {
if let Ok(symbols) = _sections.symbol_table_by_index(endian, data, link) {
if let Ok(versions) = _sections.versions(endian, data) {
for (index, symbol) in symbols.symbols().iter().enumerate() {
let name = symbols.symbol_name(endian, symbol).unwrap();
if !symbol.is_definition(endian) {
continue;
}
let hash = hash(name);
let version = versions.version(versions.version_index(endian, index));
let (hash_index, hash_symbol) = hash_table
.find(endian, name, hash, version, &symbols, &versions)
.unwrap();
let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
assert_eq!(name, hash_name);
assert_eq!(index, hash_index);
}
let hash = hash(name);
let hash_symbol = hash_table.find(endian, name, hash, &symbols).unwrap();
let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
assert_eq!(name, hash_name);
}
}
}
Expand All @@ -845,14 +865,25 @@ mod elf {
});
}
/* TODO: add this in a test somewhere
if let Ok(Some(hash_table)) = section.gnu_hash(endian, data) {
if let Ok(symbols) = _sections.symbols(endian, data, SHT_DYNSYM) {
for symbol in &symbols.symbols()[hash_table.symbol_base() as usize..] {
let name = symbols.symbol_name(endian, symbol).unwrap();
let hash = gnu_hash(name);
let hash_symbol = hash_table.find(endian, name, hash, &symbols).unwrap();
let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
assert_eq!(name, hash_name);
if let Ok(Some((hash_table, link))) = section.gnu_hash(endian, data) {
if let Ok(symbols) = _sections.symbol_table_by_index(endian, data, link) {
if let Ok(versions) = _sections.versions(endian, data) {
for (index, symbol) in symbols
.symbols()
.iter()
.enumerate()
.skip(hash_table.symbol_base() as usize)
{
let name = symbols.symbol_name(endian, symbol).unwrap();
let hash = gnu_hash(name);
let version = versions.version(versions.version_index(endian, index));
let (hash_index, hash_symbol) = hash_table
.find(endian, name, hash, version, &symbols, &versions)
.unwrap();
let hash_name = symbols.symbol_name(endian, hash_symbol).unwrap();
assert_eq!(name, hash_name);
assert_eq!(index, hash_index);
}
}
}
}
Expand All @@ -864,25 +895,30 @@ mod elf {
endian: Elf::Endian,
data: &[u8],
_elf: &Elf,
_sections: &SectionTable<Elf>,
sections: &SectionTable<Elf>,
section: &Elf::SectionHeader,
) {
if let Ok(Some(mut verdefs)) = section.gnu_verdef(endian, data) {
if let Ok(Some((mut verdefs, link))) = section.gnu_verdef(endian, data) {
let strings = sections
.strings(endian, data, link)
.unwrap_or(StringTable::default());
while let Ok(Some((verdef, mut verdauxs))) = verdefs.next() {
p.group("VersionDefinition", |p| {
// TODO: names
p.field("Version", verdef.vd_version.get(endian));
p.field_hex("Flags", verdef.vd_flags.get(endian));
p.flags(verdef.vd_flags.get(endian), 0, FLAGS_VER_FLG);
p.field("Index", verdef.vd_ndx.get(endian) & !VER_NDX_HIDDEN);
p.flags(verdef.vd_ndx.get(endian), 0, FLAGS_VER_NDX);
p.field("Index", verdef.vd_ndx.get(endian));
p.field("AuxCount", verdef.vd_cnt.get(endian));
p.field_hex("Hash", verdef.vd_hash.get(endian));
p.field("AuxOffset", verdef.vd_aux.get(endian));
p.field("NextOffset", verdef.vd_next.get(endian));
while let Ok(Some(verdaux)) = verdauxs.next() {
p.group("Aux", |p| {
p.field_hex("Name", verdaux.vda_name.get(endian));
p.field_string(
"Name",
verdaux.vda_name.get(endian),
verdaux.name(endian, strings).ok(),
);
p.field("NextOffset", verdaux.vda_next.get(endian));
});
}
Expand All @@ -896,26 +932,35 @@ mod elf {
endian: Elf::Endian,
data: &[u8],
_elf: &Elf,
_sections: &SectionTable<Elf>,
sections: &SectionTable<Elf>,
section: &Elf::SectionHeader,
) {
if let Ok(Some(mut verneeds)) = section.gnu_verneed(endian, data) {
if let Ok(Some((mut verneeds, link))) = section.gnu_verneed(endian, data) {
let strings = sections
.strings(endian, data, link)
.unwrap_or(StringTable::default());
while let Ok(Some((verneed, mut vernauxs))) = verneeds.next() {
p.group("VersionNeed", |p| {
// TODO: names
p.field("Version", verneed.vn_version.get(endian));
p.field("AuxCount", verneed.vn_cnt.get(endian));
p.field_hex("Filename", verneed.vn_file.get(endian));
p.field_string(
"Filename",
verneed.vn_file.get(endian),
verneed.file(endian, strings).ok(),
);
p.field("AuxOffset", verneed.vn_aux.get(endian));
p.field("NextOffset", verneed.vn_next.get(endian));
while let Ok(Some(vernaux)) = vernauxs.next() {
p.group("Aux", |p| {
p.field_hex("Hash", vernaux.vna_hash.get(endian));
p.field_hex("Flags", vernaux.vna_flags.get(endian));
p.flags(vernaux.vna_flags.get(endian), 0, FLAGS_VER_FLG);
p.field("Index", vernaux.vna_other.get(endian) & !VER_NDX_HIDDEN);
p.flags(vernaux.vna_other.get(endian), 0, FLAGS_VER_NDX);
p.field_hex("Name", vernaux.vna_name.get(endian));
p.field("Index", vernaux.vna_other.get(endian));
p.field_string(
"Name",
vernaux.vna_name.get(endian),
vernaux.name(endian, strings).ok(),
);
p.field("NextOffset", vernaux.vna_next.get(endian));
});
}
Expand All @@ -929,15 +974,25 @@ mod elf {
endian: Elf::Endian,
data: &[u8],
_elf: &Elf,
_sections: &SectionTable<Elf>,
sections: &SectionTable<Elf>,
section: &Elf::SectionHeader,
) {
if let Ok(Some(syms)) = section.gnu_versym(endian, data) {
for sym in syms {
if let Ok(Some((syms, _link))) = section.gnu_versym(endian, data) {
let versions = sections.versions(endian, data).ok();
for (index, sym) in syms.iter().enumerate() {
let sym = VersionIndex(sym.0.get(endian));
p.group("VersionSymbol", |p| {
p.field("Version", sym.0.get(endian) & !VER_NDX_HIDDEN);
p.flags(sym.0.get(endian), 0, FLAGS_VER_NDX);
// TODO: version name
p.field("Index", index);
if sym.0 <= VER_NDX_GLOBAL {
p.field_enum("Version", sym.0, FLAGS_VER_NDX);
} else {
let name = versions
.as_ref()
.and_then(|versions| versions.version(sym))
.map(|version| version.name());
p.field_string("Version", sym.0, name);
};
p.flags(sym.0, 0, FLAGS_VERSYM);
});
}
}
Expand Down Expand Up @@ -3342,7 +3397,8 @@ mod elf {
DF_1_PIE,
);
static FLAGS_VER_FLG: &[Flag<u16>] = &flags!(VER_FLG_BASE, VER_FLG_WEAK);
static FLAGS_VER_NDX: &[Flag<u16>] = &flags!(VER_NDX_HIDDEN);
static FLAGS_VER_NDX: &[Flag<u16>] = &flags!(VER_NDX_LOCAL, VER_NDX_GLOBAL);
static FLAGS_VERSYM: &[Flag<u16>] = &flags!(VERSYM_HIDDEN);
}

mod macho {
Expand Down
10 changes: 7 additions & 3 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1694,6 +1694,11 @@ pub const DF_1_PIE: u32 = 0x0800_0000;
#[repr(C)]
pub struct Versym<E: Endian>(pub U16<E>);

/// Symbol is hidden.
pub const VERSYM_HIDDEN: u16 = 0x8000;
/// Symbol version index.
pub const VERSYM_VERSION: u16 = 0x7fff;

/// Version definition sections
#[derive(Debug, Clone, Copy)]
#[repr(C)]
Expand All @@ -1720,9 +1725,10 @@ pub const VER_DEF_NONE: u16 = 0;
/// Current version
pub const VER_DEF_CURRENT: u16 = 1;

// Legal values for vd_flags and vna_flags (version information flags).
// Legal values for vd_flags (version information flags).
/// Version definition of file itself
pub const VER_FLG_BASE: u16 = 0x1;
// Legal values for vd_flags and vna_flags (version information flags).
/// Weak version identifier
pub const VER_FLG_WEAK: u16 = 0x2;

Expand All @@ -1731,8 +1737,6 @@ pub const VER_FLG_WEAK: u16 = 0x2;
pub const VER_NDX_LOCAL: u16 = 0;
/// Symbol is global.
pub const VER_NDX_GLOBAL: u16 = 1;
/// Symbol is hidden.
pub const VER_NDX_HIDDEN: u16 = 0x8000;

/// Auxiliary version information.
#[derive(Debug, Clone, Copy)]
Expand Down
4 changes: 2 additions & 2 deletions src/read/elf/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ where
&'file self,
index: SectionIndex,
) -> read::Result<ElfSection<'data, 'file, Elf, R>> {
let section = self.sections.section(index.0)?;
let section = self.sections.section(index)?;
Ok(ElfSection {
file: self,
index,
Expand Down Expand Up @@ -274,7 +274,7 @@ where
&'file self,
) -> Option<ElfDynamicRelocationIterator<'data, 'file, Elf, R>> {
Some(ElfDynamicRelocationIterator {
section_index: 1,
section_index: SectionIndex(1),
file: self,
relocations: None,
})
Expand Down
Loading

0 comments on commit ab39161

Please sign in to comment.