diff --git a/src/write/elf/writer.rs b/src/write/elf/writer.rs index 8086f05..8c3ff85 100644 --- a/src/write/elf/writer.rs +++ b/src/write/elf/writer.rs @@ -1789,7 +1789,11 @@ impl<'a> Writer<'a, TwoPhase> { /// Return the size of the dynamic string table. /// /// Must be called after [`Self::reserve_dynstr`]. - pub fn dynstr_len(&mut self) -> u32 { + /// Returns 0 if the dynamic string table is not needed. + pub fn dynstr_len(&self) -> u32 { + if !self.dynstr_needed() { + return 0; + } debug_assert_ne!(self.dynstr_offset, 0); self.dynstr_size } @@ -1836,6 +1840,8 @@ impl<'a> Writer<'a, TwoPhase> { debug_assert_eq!(self.dynsym_offset, 0); debug_assert_eq!(self.dynsym_num, 0); self.dynsym_num = 1; + // The symbol table must link to a string table. + self.need_dynstr = true; SymbolIndex(0) } @@ -1852,6 +1858,8 @@ impl<'a> Writer<'a, TwoPhase> { debug_assert_eq!(self.dynsym_offset, 0); if self.dynsym_num == 0 { self.dynsym_num = 1; + // The symbol table must link to a string table. + self.need_dynstr = true; } let index = self.dynsym_num; self.dynsym_num += 1; diff --git a/tests/round_trip/elf.rs b/tests/round_trip/elf.rs index f98132e..86e7e25 100644 --- a/tests/round_trip/elf.rs +++ b/tests/round_trip/elf.rs @@ -109,6 +109,52 @@ fn empty_symtab() { assert_eq!(strtab.size(), 1); } +// .dynsym must link to .dynstr even when only the null dynamic symbol is present. +#[test] +fn empty_dynsym() { + let file_header = write::elf::FileHeader { + os_abi: elf::ELFOSABI_SYSV, + abi_version: 0, + e_type: elf::ET_DYN, + e_machine: elf::EM_X86_64, + e_entry: 0, + e_flags: elf::FileFlags(0), + }; + + let mut bytes = Vec::new(); + let mut writer = write::elf::Writer::new(Endianness::Little, true, &mut bytes); + + writer.reserve_file_header(); + writer.reserve_null_dynamic_symbol_index(); + writer.reserve_dynsym(); + writer.reserve_dynstr().unwrap(); + writer.reserve_null_section_index(); + writer.reserve_dynsym_section_index(); + let dynstr_index = writer.reserve_dynstr_section_index(); + writer.reserve_shstrtab_section_index(); + writer.reserve_shstrtab().unwrap(); + writer.reserve_section_headers(); + + writer.write_file_header(&file_header).unwrap(); + writer.write_null_dynamic_symbol(); + writer.write_dynstr(); + writer.write_shstrtab(); + writer.write_null_section_header(); + writer.write_dynsym_section_header(0, 1); + writer.write_dynstr_section_header(0); + writer.write_shstrtab_section_header(); + + let object = read::elf::ElfFile64::::parse(&*bytes).unwrap(); + let dynsym = object.section_by_name(".dynsym").unwrap(); + assert_eq!(dynsym.size(), 24); + let dynstr = object.section_by_name(".dynstr").unwrap(); + assert_eq!(dynstr.size(), 1); + assert_eq!( + dynsym.elf_section_header().sh_link(Endianness::Little), + dynstr_index.0, + ); +} + #[test] fn aligned_sections() { let mut object =