From 1f0f1fc9548869475949c9b8df831f82c2720830 Mon Sep 17 00:00:00 2001 From: Philip Craig Date: Thu, 5 Sep 2024 17:44:25 +1000 Subject: [PATCH] Improve simple_write example (#747) Use the correct relocation kind for COFF, and use the correct string section flags for ELF. --- crates/examples/src/bin/simple_write.rs | 33 +++++++++++++++++++------ src/common.rs | 7 ++++++ 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/crates/examples/src/bin/simple_write.rs b/crates/examples/src/bin/simple_write.rs index 1a791eae..25533ee7 100644 --- a/crates/examples/src/bin/simple_write.rs +++ b/crates/examples/src/bin/simple_write.rs @@ -3,7 +3,7 @@ //! The resulting object file can be linked with a C runtime to create a complete executable: //! ```sh //! $ cargo run --bin simple_write -//! $ gcc -o hello hello.o +//! $ gcc -o hello hello.o -z noexecstack //! $ ./hello //! Hello, world! //! ``` @@ -48,8 +48,9 @@ impl RelocateWriter for Section { } fn main() -> Result<(), Box> { + let binary_format = object::BinaryFormat::native_object(); let mut obj = object::write::Object::new( - object::BinaryFormat::native_object(), + binary_format, object::Architecture::X86_64, object::Endianness::Little, ); @@ -69,7 +70,12 @@ fn main() -> Result<(), Box> { // Choose the encoding parameters. let encoding = Encoding { format: Format::Dwarf32, - version: 5, + version: if binary_format == object::BinaryFormat::Coff { + // The COFF toolchain I used didn't work with DWARF version 5. + 4 + } else { + 5 + }, address_size: 8, }; @@ -148,7 +154,12 @@ fn main() -> Result<(), Box> { if section.data.len() == 0 { return Ok(()); } - let section_id = obj.add_section(Vec::new(), id.name().into(), object::SectionKind::Debug); + let kind = if id.is_string() { + object::SectionKind::DebugString + } else { + object::SectionKind::Debug + }; + let section_id = obj.add_section(Vec::new(), id.name().into(), kind); obj.set_section_data(section_id, section.data.take(), 1); // Record the section ID so that it can be used for relocations. @@ -166,14 +177,20 @@ fn main() -> Result<(), Box> { // The `eh_pe` field is not used in this example because we are not writing // unwind information. debug_assert!(reloc.eh_pe.is_none()); - let symbol = match reloc.target { + let (symbol, kind) = match reloc.target { RelocationTarget::Section(id) => { - obj.section_symbol(sections.get(id).unwrap().id.unwrap()) + let kind = if binary_format == object::BinaryFormat::Coff { + object::RelocationKind::SectionOffset + } else { + object::RelocationKind::Absolute + }; + let symbol = obj.section_symbol(sections.get(id).unwrap().id.unwrap()); + (symbol, kind) } RelocationTarget::Symbol(id) => { // The main function is the only symbol we have defined. debug_assert_eq!(id, 0); - main_symbol + (main_symbol, object::RelocationKind::Absolute) } }; obj.add_relocation( @@ -183,7 +200,7 @@ fn main() -> Result<(), Box> { symbol, addend: reloc.addend, flags: object::RelocationFlags::Generic { - kind: object::RelocationKind::Absolute, + kind, encoding: object::RelocationEncoding::Generic, size: reloc.size * 8, }, diff --git a/src/common.rs b/src/common.rs index 515718f3..8c51121a 100644 --- a/src/common.rs +++ b/src/common.rs @@ -365,6 +365,13 @@ impl SectionId { _ => return None, }) } + + /// Returns true if this is a mergeable string section. + /// + /// This is useful for determining the correct section flags. + pub fn is_string(self) -> bool { + matches!(self, SectionId::DebugStr | SectionId::DebugLineStr) + } } /// An optionally-provided implementation-defined compilation unit ID to enable