mirror of
https://github.com/encounter/object.git
synced 2026-07-10 12:18:39 -07:00
elf: allow for absence of dynstr (#646)
.dynstr doesn't need to be present if there are no dynamic strings. - handle section index 0 in read::elf::SectionTable::strings - don't require .dynstr when writing if there are no strings - don't print name of symbol index 0 in readobj example
This commit is contained in:
@@ -398,11 +398,15 @@ fn print_section_symbols<Elf: FileHeader>(
|
||||
for (index, symbol) in symbols.iter().enumerate() {
|
||||
p.group("Symbol", |p| {
|
||||
p.field("Index", index);
|
||||
p.field_string(
|
||||
"Name",
|
||||
symbol.st_name(endian),
|
||||
symbol.name(endian, symbols.strings()),
|
||||
);
|
||||
if index == 0 {
|
||||
p.field_hex("Name", symbol.st_name(endian));
|
||||
} else {
|
||||
p.field_string(
|
||||
"Name",
|
||||
symbol.st_name(endian),
|
||||
symbol.name(endian, symbols.strings()),
|
||||
);
|
||||
}
|
||||
if let Some(versions) = versions.as_ref() {
|
||||
let version_index = versions.version_index(endian, index);
|
||||
print_version(p, Some(versions), version_index);
|
||||
@@ -511,6 +515,10 @@ fn print_rel_symbol<Elf: FileHeader>(
|
||||
symbols: Option<SymbolTable<'_, Elf>>,
|
||||
sym: u32,
|
||||
) {
|
||||
if sym == 0 {
|
||||
p.field_hex("Symbol", sym);
|
||||
return;
|
||||
}
|
||||
let name = symbols.and_then(|symbols| {
|
||||
symbols
|
||||
.symbol(sym as usize)
|
||||
|
||||
@@ -167,7 +167,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -338,7 +338,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -559,37 +559,37 @@ SectionHeader {
|
||||
Relocation {
|
||||
Offset: 0x10D80
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x720
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x10D88
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x6D8
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x10FC8
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x7C8
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x10FE8
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x748
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x10FF0
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x724
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x11008
|
||||
Type: R_AARCH64_RELATIVE (0x403)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x11008
|
||||
}
|
||||
Relocation {
|
||||
@@ -971,7 +971,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -269,7 +269,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -442,7 +442,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -984,7 +984,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -197,7 +197,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -371,7 +371,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -547,19 +547,19 @@ SectionHeader {
|
||||
Relocation {
|
||||
Offset: 0x200DA8
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x670
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x200DB0
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x630
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x201008
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: "" (0x0)
|
||||
Symbol: 0x0
|
||||
Addend: 0x201008
|
||||
}
|
||||
Relocation {
|
||||
@@ -959,7 +959,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -227,7 +227,7 @@ SectionHeader {
|
||||
EntrySize: 0x10
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -185,7 +185,7 @@ SectionHeader {
|
||||
EntrySize: 0x10
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: "" (0x0)
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -211,7 +211,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -583,7 +583,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -371,7 +371,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -547,19 +547,19 @@ SectionHeader {
|
||||
Relocation {
|
||||
Offset: 0x200DA8
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: ""
|
||||
Symbol: 0x0
|
||||
Addend: 0x670
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x200DB0
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: ""
|
||||
Symbol: 0x0
|
||||
Addend: 0x630
|
||||
}
|
||||
Relocation {
|
||||
Offset: 0x201008
|
||||
Type: R_X86_64_RELATIVE (0x8)
|
||||
Symbol: ""
|
||||
Symbol: 0x0
|
||||
Addend: 0x201008
|
||||
}
|
||||
Relocation {
|
||||
@@ -959,7 +959,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -222,7 +222,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Version: VER_NDX_LOCAL (0x0)
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
@@ -605,7 +605,7 @@ SectionHeader {
|
||||
EntrySize: 0x18
|
||||
Symbol {
|
||||
Index: 0
|
||||
Name: ""
|
||||
Name: 0x0
|
||||
Value: 0x0
|
||||
Size: 0x0
|
||||
Type: STT_NOTYPE (0x0)
|
||||
|
||||
@@ -1034,15 +1034,21 @@ impl<'data> Builder<'data> {
|
||||
return Err(Error::new(
|
||||
".symtab.shndx section is needed but not present",
|
||||
));
|
||||
} else if symtab_shndx_id.is_some() {
|
||||
writer.require_symtab_shndx();
|
||||
}
|
||||
if strtab_id.is_none() && writer.strtab_needed() {
|
||||
return Err(Error::new(".strtab section is needed but not present"));
|
||||
} else if strtab_id.is_some() {
|
||||
writer.require_strtab();
|
||||
}
|
||||
if dynsym_id.is_none() && !out_dynsyms.is_empty() {
|
||||
return Err(Error::new(".dynsym section is needed but not present"));
|
||||
}
|
||||
if dynstr_id.is_none() && writer.dynstr_needed() {
|
||||
return Err(Error::new(".dynstr section is needed but not present"));
|
||||
} else if dynstr_id.is_some() {
|
||||
writer.require_dynstr();
|
||||
}
|
||||
if gnu_verdef_id.is_none() && verdef_count > 0 {
|
||||
return Err(Error::new(
|
||||
|
||||
@@ -86,6 +86,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> {
|
||||
|
||||
/// Return the string table at the given section index.
|
||||
///
|
||||
/// Returns an empty string table if the index is 0.
|
||||
/// Returns an error if the section is not a string table.
|
||||
#[inline]
|
||||
pub fn strings(
|
||||
@@ -94,6 +95,9 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> {
|
||||
data: R,
|
||||
index: SectionIndex,
|
||||
) -> read::Result<StringTable<'data, R>> {
|
||||
if index == SectionIndex(0) {
|
||||
return Ok(StringTable::default());
|
||||
}
|
||||
self.section(index)?
|
||||
.strings(endian, data)?
|
||||
.read_error("Invalid ELF string section type")
|
||||
|
||||
+16
-14
@@ -641,6 +641,11 @@ impl<'a> Writer<'a> {
|
||||
self.need_strtab
|
||||
}
|
||||
|
||||
/// Require the string table even if no strings were added.
|
||||
pub fn require_strtab(&mut self) {
|
||||
self.need_strtab = true;
|
||||
}
|
||||
|
||||
/// Reserve the range for the string table.
|
||||
///
|
||||
/// This range is used for a section named `.strtab`.
|
||||
@@ -719,8 +724,6 @@ impl<'a> Writer<'a> {
|
||||
debug_assert_eq!(self.symtab_offset, 0);
|
||||
debug_assert_eq!(self.symtab_num, 0);
|
||||
self.symtab_num = 1;
|
||||
// The symtab must link to a strtab.
|
||||
self.need_strtab = true;
|
||||
SymbolIndex(0)
|
||||
}
|
||||
|
||||
@@ -741,8 +744,6 @@ impl<'a> Writer<'a> {
|
||||
debug_assert_eq!(self.symtab_shndx_offset, 0);
|
||||
if self.symtab_num == 0 {
|
||||
self.symtab_num = 1;
|
||||
// The symtab must link to a strtab.
|
||||
self.need_strtab = true;
|
||||
}
|
||||
let index = self.symtab_num;
|
||||
self.symtab_num += 1;
|
||||
@@ -893,6 +894,12 @@ impl<'a> Writer<'a> {
|
||||
self.need_symtab_shndx
|
||||
}
|
||||
|
||||
/// Require the extended section indices for the symbol table even
|
||||
/// if no section indices are too large.
|
||||
pub fn require_symtab_shndx(&mut self) {
|
||||
self.need_symtab_shndx = true;
|
||||
}
|
||||
|
||||
/// Reserve the range for the extended section indices for the symbol table.
|
||||
///
|
||||
/// This range is used for a section named `.symtab_shndx`.
|
||||
@@ -992,6 +999,11 @@ impl<'a> Writer<'a> {
|
||||
self.need_dynstr
|
||||
}
|
||||
|
||||
/// Require the dynamic string table even if no strings were added.
|
||||
pub fn require_dynstr(&mut self) {
|
||||
self.need_dynstr = true;
|
||||
}
|
||||
|
||||
/// Reserve the range for the dynamic string table.
|
||||
///
|
||||
/// This range is used for a section named `.dynstr`.
|
||||
@@ -1000,9 +1012,6 @@ impl<'a> Writer<'a> {
|
||||
/// This must be called after [`Self::add_dynamic_string`].
|
||||
pub fn reserve_dynstr(&mut self) -> usize {
|
||||
debug_assert_eq!(self.dynstr_offset, 0);
|
||||
if !self.need_dynstr {
|
||||
return 0;
|
||||
}
|
||||
// Start with null string.
|
||||
self.dynstr_data = vec![0];
|
||||
self.dynstr.write(1, &mut self.dynstr_data);
|
||||
@@ -1014,9 +1023,6 @@ impl<'a> Writer<'a> {
|
||||
///
|
||||
/// This must be called after [`Self::reserve_dynstr`].
|
||||
pub fn dynstr_len(&mut self) -> usize {
|
||||
if !self.need_dynstr {
|
||||
return 0;
|
||||
}
|
||||
debug_assert_ne!(self.dynstr_offset, 0);
|
||||
self.dynstr_data.len()
|
||||
}
|
||||
@@ -1087,8 +1093,6 @@ impl<'a> Writer<'a> {
|
||||
debug_assert_eq!(self.dynsym_offset, 0);
|
||||
debug_assert_eq!(self.dynsym_num, 0);
|
||||
self.dynsym_num = 1;
|
||||
// The symtab must link to a strtab.
|
||||
self.need_dynstr = true;
|
||||
SymbolIndex(0)
|
||||
}
|
||||
|
||||
@@ -1105,8 +1109,6 @@ impl<'a> Writer<'a> {
|
||||
debug_assert_eq!(self.dynsym_offset, 0);
|
||||
if self.dynsym_num == 0 {
|
||||
self.dynsym_num = 1;
|
||||
// The symtab must link to a strtab.
|
||||
self.need_dynstr = true;
|
||||
}
|
||||
let index = self.dynsym_num;
|
||||
self.dynsym_num += 1;
|
||||
|
||||
@@ -37,3 +37,74 @@ fn test_nobits_offset() {
|
||||
let mut buf = Vec::new();
|
||||
builder.write(&mut buf).unwrap();
|
||||
}
|
||||
|
||||
// Test that we can read and write a file with no dynamic string table.
|
||||
#[test]
|
||||
fn test_no_dynstr() {
|
||||
let mut builder = build::elf::Builder::new(object::Endianness::Little, true);
|
||||
builder.header.e_type = elf::ET_EXEC;
|
||||
builder.header.e_machine = elf::EM_X86_64;
|
||||
builder.header.e_phoff = 0x40;
|
||||
|
||||
let section = builder.sections.add();
|
||||
section.name = b".shstrtab"[..].into();
|
||||
section.sh_type = elf::SHT_STRTAB;
|
||||
section.data = build::elf::SectionData::SectionString;
|
||||
|
||||
let section = builder.sections.add();
|
||||
section.name = b".dynsym"[..].into();
|
||||
section.sh_type = elf::SHT_DYNSYM;
|
||||
section.sh_flags = elf::SHF_ALLOC as u64;
|
||||
section.sh_addr = 0x1000;
|
||||
section.sh_offset = 0x1000;
|
||||
section.sh_addralign = 8;
|
||||
section.data = build::elf::SectionData::DynamicSymbol;
|
||||
let dynsym_id = section.id();
|
||||
|
||||
let section = builder.sections.add();
|
||||
section.name = b".rela.dyn"[..].into();
|
||||
section.sh_type = elf::SHT_RELA;
|
||||
section.sh_flags = elf::SHF_ALLOC as u64;
|
||||
section.sh_addr = 0x1100;
|
||||
section.sh_offset = 0x1100;
|
||||
section.sh_addralign = 8;
|
||||
section.data =
|
||||
build::elf::SectionData::DynamicRelocation(vec![build::elf::DynamicRelocation {
|
||||
r_offset: 0x1000,
|
||||
symbol: None,
|
||||
r_type: elf::R_X86_64_64,
|
||||
r_addend: 0x300,
|
||||
}]);
|
||||
let rela_id = section.id();
|
||||
|
||||
let segment = builder.segments.add();
|
||||
segment.p_type = elf::PT_LOAD;
|
||||
segment.p_flags = elf::PF_R;
|
||||
segment.p_offset = 0x1000;
|
||||
segment.p_vaddr = 0x1000;
|
||||
segment.p_paddr = 0x1000;
|
||||
segment.p_filesz = 0x200;
|
||||
segment.p_memsz = 0x200;
|
||||
segment.p_align = 8;
|
||||
segment.sections.push(dynsym_id);
|
||||
segment.sections.push(rela_id);
|
||||
|
||||
let mut buf = Vec::new();
|
||||
builder.write(&mut buf).unwrap();
|
||||
|
||||
let builder = build::elf::Builder::read(&*buf).unwrap();
|
||||
assert_eq!(builder.sections.count(), 3);
|
||||
assert_eq!(builder.segments.count(), 1);
|
||||
for section in &builder.sections {
|
||||
match §ion.data {
|
||||
build::elf::SectionData::DynamicSymbol => {
|
||||
assert_eq!(section.sh_offset, 0x1000);
|
||||
}
|
||||
build::elf::SectionData::DynamicRelocation(rela) => {
|
||||
assert_eq!(section.sh_offset, 0x1100);
|
||||
assert_eq!(rela.len(), 1);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user