diff options
Diffstat (limited to 'third_party/rust/object/tests')
-rw-r--r-- | third_party/rust/object/tests/integration.rs | 2 | ||||
-rw-r--r-- | third_party/rust/object/tests/parse_self.rs | 25 | ||||
-rw-r--r-- | third_party/rust/object/tests/read/coff.rs | 23 | ||||
-rw-r--r-- | third_party/rust/object/tests/read/mod.rs | 3 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/bss.rs | 255 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/coff.rs | 56 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/comdat.rs | 225 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/common.rs | 245 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/elf.rs | 218 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/macho.rs | 24 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/mod.rs | 451 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/section_flags.rs | 90 | ||||
-rw-r--r-- | third_party/rust/object/tests/round_trip/tls.rs | 316 |
13 files changed, 1933 insertions, 0 deletions
diff --git a/third_party/rust/object/tests/integration.rs b/third_party/rust/object/tests/integration.rs new file mode 100644 index 0000000000..6ebcb547f8 --- /dev/null +++ b/third_party/rust/object/tests/integration.rs @@ -0,0 +1,2 @@ +mod read; +mod round_trip; diff --git a/third_party/rust/object/tests/parse_self.rs b/third_party/rust/object/tests/parse_self.rs new file mode 100644 index 0000000000..1e7df67158 --- /dev/null +++ b/third_party/rust/object/tests/parse_self.rs @@ -0,0 +1,25 @@ +#![cfg(feature = "read")] +use object::{File, Object}; +use std::{env, fs}; + +#[test] +fn parse_self() { + let exe = env::current_exe().unwrap(); + let data = fs::read(exe).unwrap(); + let object = File::parse(&*data).unwrap(); + assert!(object.entry() != 0); + assert!(object.sections().count() != 0); +} + +#[cfg(feature = "std")] +#[test] +fn parse_self_cache() { + use object::read::{ReadCache, ReadRef}; + let exe = env::current_exe().unwrap(); + let file = fs::File::open(exe).unwrap(); + let cache = ReadCache::new(file); + let data = cache.range(0, cache.len().unwrap()); + let object = File::parse(data).unwrap(); + assert!(object.entry() != 0); + assert!(object.sections().count() != 0); +} diff --git a/third_party/rust/object/tests/read/coff.rs b/third_party/rust/object/tests/read/coff.rs new file mode 100644 index 0000000000..3e61ec284d --- /dev/null +++ b/third_party/rust/object/tests/read/coff.rs @@ -0,0 +1,23 @@ +use object::{pe, read, Object, ObjectSection}; +use std::fs; +use std::path::PathBuf; + +#[cfg(feature = "coff")] +#[test] +fn coff_extended_relocations() { + let path_to_obj: PathBuf = ["testfiles", "coff", "relocs_overflow.o"].iter().collect(); + let contents = fs::read(&path_to_obj).expect("Could not read relocs_overflow.o"); + let file = + read::coff::CoffFile::parse(&contents[..]).expect("Could not parse relocs_overflow.o"); + let code_section = file + .section_by_name(".text") + .expect("Could not find .text section in relocs_overflow.o"); + match code_section.flags() { + object::SectionFlags::Coff { characteristics } => { + assert!(characteristics & pe::IMAGE_SCN_LNK_NRELOC_OVFL != 0) + } + _ => panic!("Invalid section flags flavour."), + }; + let relocations = code_section.relocations().collect::<Vec<_>>(); + assert_eq!(relocations.len(), 65536); +} diff --git a/third_party/rust/object/tests/read/mod.rs b/third_party/rust/object/tests/read/mod.rs new file mode 100644 index 0000000000..d60d1933b7 --- /dev/null +++ b/third_party/rust/object/tests/read/mod.rs @@ -0,0 +1,3 @@ +#![cfg(feature = "read")] + +mod coff; diff --git a/third_party/rust/object/tests/round_trip/bss.rs b/third_party/rust/object/tests/round_trip/bss.rs new file mode 100644 index 0000000000..1354fcc781 --- /dev/null +++ b/third_party/rust/object/tests/round_trip/bss.rs @@ -0,0 +1,255 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::read::{Object, ObjectSection, ObjectSymbol}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, Endianness, SectionKind, SymbolFlags, SymbolKind, SymbolScope, +}; + +#[test] +fn coff_x86_64_bss() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + let section = object.section_id(write::StandardSection::UninitializedData); + + let symbol = object.add_symbol(write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 18, 4); + + let symbol = object.add_symbol(write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 34, 8); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"bss.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let bss = sections.next().unwrap(); + println!("{:?}", bss); + let bss_index = bss.index(); + assert_eq!(bss.name(), Ok(".bss")); + assert_eq!(bss.kind(), SectionKind::UninitializedData); + assert_eq!(bss.size(), 58); + assert_eq!(bss.data(), Ok(&[][..])); + + let section = sections.next(); + assert!(section.is_none(), "unexpected section {:?}", section); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 24); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} + +#[test] +fn elf_x86_64_bss() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + let section = object.section_id(write::StandardSection::UninitializedData); + + let symbol = object.add_symbol(write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 18, 4); + + let symbol = object.add_symbol(write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 34, 8); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"bss.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok("")); + assert_eq!(section.kind(), SectionKind::Metadata); + assert_eq!(section.address(), 0); + assert_eq!(section.size(), 0); + + let bss = sections.next().unwrap(); + println!("{:?}", bss); + let bss_index = bss.index(); + assert_eq!(bss.name(), Ok(".bss")); + assert_eq!(bss.kind(), SectionKind::UninitializedData); + assert_eq!(bss.size(), 58); + assert_eq!(bss.data(), Ok(&[][..])); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("")); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 18); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 24); + assert_eq!(symbol.size(), 34); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} + +#[test] +fn macho_x86_64_bss() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + let section = object.section_id(write::StandardSection::UninitializedData); + + let symbol = object.add_symbol(write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 18, 4); + + let symbol = object.add_symbol(write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 34, 8); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"bss.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::MachO); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let bss = sections.next().unwrap(); + println!("{:?}", bss); + let bss_index = bss.index(); + assert_eq!(bss.name(), Ok("__bss")); + assert_eq!(bss.segment_name(), Ok(Some("__DATA"))); + assert_eq!(bss.kind(), SectionKind::UninitializedData); + assert_eq!(bss.size(), 58); + assert_eq!(bss.data(), Ok(&[][..])); + + let section = sections.next(); + assert!(section.is_none(), "unexpected section {:?}", section); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 24); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} diff --git a/third_party/rust/object/tests/round_trip/coff.rs b/third_party/rust/object/tests/round_trip/coff.rs new file mode 100644 index 0000000000..6785dc367e --- /dev/null +++ b/third_party/rust/object/tests/round_trip/coff.rs @@ -0,0 +1,56 @@ +use object::read::{Object, ObjectSection}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SymbolFlags, + SymbolKind, SymbolScope, +}; + +#[test] +fn reloc_overflow() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + let text = object.section_id(write::StandardSection::Text); + object.append_section_data(text, &[0; 4], 4); + let symbol = object.add_symbol(write::Symbol { + name: b"f".to_vec(), + value: 0, + size: 4, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(text), + flags: SymbolFlags::None, + }); + for i in 0..0x10000 { + object + .add_relocation( + text, + write::Relocation { + offset: i, + size: 64, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol, + addend: 0, + }, + ) + .unwrap(); + } + let bytes = object.write().unwrap(); + + //std::fs::write(&"reloc_overflow.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let section = object.sections().next().unwrap(); + assert_eq!(section.name(), Ok(".text")); + + let mut i = 0; + for (offset, _relocation) in section.relocations() { + assert_eq!(offset, i); + i += 1; + } + assert_eq!(i, 0x10000); +} diff --git a/third_party/rust/object/tests/round_trip/comdat.rs b/third_party/rust/object/tests/round_trip/comdat.rs new file mode 100644 index 0000000000..7b697a04c0 --- /dev/null +++ b/third_party/rust/object/tests/round_trip/comdat.rs @@ -0,0 +1,225 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::pe; +use object::read::{Object, ObjectComdat, ObjectSection, ObjectSymbol}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, ComdatKind, Endianness, SectionKind, SymbolFlags, SymbolKind, + SymbolScope, +}; + +#[test] +fn coff_x86_64_comdat() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + let (section1, offset) = + object.add_subsection(write::StandardSection::Text, b"s1", &[0, 1, 2, 3], 4); + object.section_symbol(section1); + let (section2, _) = + object.add_subsection(write::StandardSection::Data, b"s1", &[0, 1, 2, 3], 4); + object.section_symbol(section2); + + let symbol = object.add_symbol(write::Symbol { + name: b"s1".to_vec(), + value: offset, + size: 4, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(section1), + flags: SymbolFlags::None, + }); + + object.add_comdat(write::Comdat { + kind: ComdatKind::NoDuplicates, + symbol, + sections: vec![section1, section2], + }); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"comdat.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let section1 = sections.next().unwrap(); + println!("{:?}", section1); + let section1_index = section1.index(); + assert_eq!(section1.name(), Ok(".text$s1")); + assert_eq!(section1.kind(), SectionKind::Text); + assert_eq!(section1.address(), 0); + assert_eq!(section1.size(), 4); + + let section2 = sections.next().unwrap(); + println!("{:?}", section2); + let section2_index = section2.index(); + assert_eq!(section2.name(), Ok(".data$s1")); + assert_eq!(section2.kind(), SectionKind::Data); + assert_eq!(section2.address(), 0); + assert_eq!(section2.size(), 4); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok(".text$s1")); + assert_eq!(symbol.kind(), SymbolKind::Section); + assert_eq!( + symbol.section(), + read::SymbolSection::Section(section1.index()) + ); + assert_eq!( + symbol.flags(), + SymbolFlags::CoffSection { + selection: pe::IMAGE_COMDAT_SELECT_NODUPLICATES, + associative_section: None + } + ); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok(".data$s1")); + assert_eq!(symbol.kind(), SymbolKind::Section); + assert_eq!( + symbol.section(), + read::SymbolSection::Section(section2.index()) + ); + assert_eq!( + symbol.flags(), + SymbolFlags::CoffSection { + selection: pe::IMAGE_COMDAT_SELECT_ASSOCIATIVE, + associative_section: Some(section1_index) + } + ); + + let symbol = symbols.next().unwrap(); + let symbol_index = symbol.index(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("s1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!( + symbol.section(), + read::SymbolSection::Section(section1.index()) + ); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); + + let mut comdats = object.comdats(); + + let comdat = comdats.next().unwrap(); + println!("{:?}", comdat); + assert_eq!(comdat.kind(), ComdatKind::NoDuplicates); + assert_eq!(comdat.symbol(), symbol_index); + + let mut comdat_sections = comdat.sections(); + assert_eq!(comdat_sections.next(), Some(section1_index)); + assert_eq!(comdat_sections.next(), Some(section2_index)); + assert_eq!(comdat_sections.next(), None); +} + +#[test] +fn elf_x86_64_comdat() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + let (section1, offset) = + object.add_subsection(write::StandardSection::Text, b"s1", &[0, 1, 2, 3], 4); + let (section2, _) = + object.add_subsection(write::StandardSection::Data, b"s1", &[0, 1, 2, 3], 4); + + let symbol = object.add_symbol(write::Symbol { + name: b"s1".to_vec(), + value: offset, + size: 4, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(section1), + flags: SymbolFlags::None, + }); + + object.add_comdat(write::Comdat { + kind: ComdatKind::Any, + symbol, + sections: vec![section1, section2], + }); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"comdat.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok("")); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok(".group")); + + let section1 = sections.next().unwrap(); + println!("{:?}", section1); + let section1_index = section1.index(); + assert_eq!(section1.name(), Ok(".text.s1")); + assert_eq!(section1.kind(), SectionKind::Text); + assert_eq!(section1.address(), 0); + assert_eq!(section1.size(), 4); + + let section2 = sections.next().unwrap(); + println!("{:?}", section2); + let section2_index = section2.index(); + assert_eq!(section2.name(), Ok(".data.s1")); + assert_eq!(section2.kind(), SectionKind::Data); + assert_eq!(section2.address(), 0); + assert_eq!(section2.size(), 4); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("")); + + let symbol = symbols.next().unwrap(); + let symbol_index = symbol.index(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("s1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!( + symbol.section(), + read::SymbolSection::Section(section1.index()) + ); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); + + let mut comdats = object.comdats(); + + let comdat = comdats.next().unwrap(); + println!("{:?}", comdat); + assert_eq!(comdat.kind(), ComdatKind::Any); + assert_eq!(comdat.symbol(), symbol_index); + + let mut comdat_sections = comdat.sections(); + assert_eq!(comdat_sections.next(), Some(section1_index)); + assert_eq!(comdat_sections.next(), Some(section2_index)); + assert_eq!(comdat_sections.next(), None); +} diff --git a/third_party/rust/object/tests/round_trip/common.rs b/third_party/rust/object/tests/round_trip/common.rs new file mode 100644 index 0000000000..74d443830f --- /dev/null +++ b/third_party/rust/object/tests/round_trip/common.rs @@ -0,0 +1,245 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::read::{Object, ObjectSection, ObjectSymbol}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, Endianness, SectionKind, SymbolFlags, SymbolKind, SymbolScope, +}; + +#[test] +fn coff_x86_64_common() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + let symbol = write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 4, 4); + + let symbol = write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 8, 8); + + // Also check undefined symbols, which are very similar. + let symbol = write::Symbol { + name: b"v3".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_symbol(symbol); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"common.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section(), read::SymbolSection::Common); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 4); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section(), read::SymbolSection::Common); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 8); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v3")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section(), read::SymbolSection::Undefined); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), true); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 0); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} + +#[test] +fn elf_x86_64_common() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + let symbol = write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 4, 4); + + let symbol = write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 8, 8); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"common.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("")); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section(), read::SymbolSection::Common); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 4); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section(), read::SymbolSection::Common); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.size(), 8); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} + +#[test] +fn macho_x86_64_common() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + let symbol = write::Symbol { + name: b"v1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 4, 4); + + let symbol = write::Symbol { + name: b"v2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Data, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }; + object.add_common_symbol(symbol, 8, 8); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"common.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::MachO); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let common = sections.next().unwrap(); + println!("{:?}", common); + let common_index = common.index(); + assert_eq!(common.name(), Ok("__common")); + assert_eq!(common.segment_name(), Ok(Some("__DATA"))); + assert_eq!(common.kind(), SectionKind::Common); + assert_eq!(common.size(), 16); + assert_eq!(common.data(), Ok(&[][..])); + + let section = sections.next(); + assert!(section.is_none(), "unexpected section {:?}", section); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_v1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(common_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 0); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_v2")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(common_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.address(), 8); + + let symbol = symbols.next(); + assert!(symbol.is_none(), "unexpected symbol {:?}", symbol); +} diff --git a/third_party/rust/object/tests/round_trip/elf.rs b/third_party/rust/object/tests/round_trip/elf.rs new file mode 100644 index 0000000000..048db5795a --- /dev/null +++ b/third_party/rust/object/tests/round_trip/elf.rs @@ -0,0 +1,218 @@ +use object::read::elf::{FileHeader, SectionHeader}; +use object::read::{Object, ObjectSymbol}; +use object::{ + elf, read, write, Architecture, BinaryFormat, Endianness, LittleEndian, SectionIndex, + SectionKind, SymbolFlags, SymbolKind, SymbolScope, SymbolSection, U32, +}; +use std::io::Write; + +#[test] +fn symtab_shndx() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + for i in 0..0x10000 { + let name = format!("func{}", i).into_bytes(); + let (section, offset) = + object.add_subsection(write::StandardSection::Text, &name, &[0xcc], 1); + object.add_symbol(write::Symbol { + name, + value: offset, + size: 1, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(section), + flags: SymbolFlags::None, + }); + } + let bytes = object.write().unwrap(); + + //std::fs::write(&"symtab_shndx.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + for symbol in object.symbols().skip(1) { + assert_eq!( + symbol.section(), + SymbolSection::Section(SectionIndex(symbol.index().0)) + ); + } +} + +#[cfg(feature = "compression")] +#[test] +fn compression_zlib() { + use object::read::ObjectSection; + use object::LittleEndian as LE; + + let data = b"test data data data"; + let len = data.len() as u64; + + let mut ch = object::elf::CompressionHeader64::<LE>::default(); + ch.ch_type.set(LE, object::elf::ELFCOMPRESS_ZLIB); + ch.ch_size.set(LE, len); + ch.ch_addralign.set(LE, 1); + + let mut buf = Vec::new(); + buf.write(object::bytes_of(&ch)).unwrap(); + let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); + encoder.write_all(data).unwrap(); + let compressed = encoder.finish().unwrap(); + + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + let section = object.add_section( + Vec::new(), + b".debug_info".to_vec(), + object::SectionKind::Other, + ); + object.section_mut(section).set_data(compressed, 1); + object.section_mut(section).flags = object::SectionFlags::Elf { + sh_flags: object::elf::SHF_COMPRESSED.into(), + }; + let bytes = object.write().unwrap(); + + //std::fs::write(&"compression.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let section = object.section_by_name(".debug_info").unwrap(); + let uncompressed = section.uncompressed_data().unwrap(); + assert_eq!(data, &*uncompressed); +} + +#[cfg(feature = "compression")] +#[test] +fn compression_gnu() { + use object::read::ObjectSection; + use std::io::Write; + + let data = b"test data data data"; + let len = data.len() as u32; + + let mut buf = Vec::new(); + buf.write_all(b"ZLIB\0\0\0\0").unwrap(); + buf.write_all(&len.to_be_bytes()).unwrap(); + let mut encoder = flate2::write::ZlibEncoder::new(buf, flate2::Compression::default()); + encoder.write_all(data).unwrap(); + let compressed = encoder.finish().unwrap(); + + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + let section = object.add_section( + Vec::new(), + b".zdebug_info".to_vec(), + object::SectionKind::Other, + ); + object.section_mut(section).set_data(compressed, 1); + let bytes = object.write().unwrap(); + + //std::fs::write(&"compression.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let section = object.section_by_name(".zdebug_info").unwrap(); + let uncompressed = section.uncompressed_data().unwrap(); + assert_eq!(data, &*uncompressed); +} + +#[test] +fn note() { + let endian = Endianness::Little; + let mut object = write::Object::new(BinaryFormat::Elf, Architecture::X86_64, endian); + + // Add note section with align = 4. + let mut buffer = Vec::new(); + + buffer + .write(object::bytes_of(&elf::NoteHeader32 { + n_namesz: U32::new(endian, 6), + n_descsz: U32::new(endian, 11), + n_type: U32::new(endian, 1), + })) + .unwrap(); + buffer.write(b"name1\0\0\0").unwrap(); + buffer.write(b"descriptor\0\0").unwrap(); + + buffer + .write(object::bytes_of(&elf::NoteHeader32 { + n_namesz: U32::new(endian, 6), + n_descsz: U32::new(endian, 11), + n_type: U32::new(endian, 2), + })) + .unwrap(); + buffer.write(b"name2\0\0\0").unwrap(); + buffer.write(b"descriptor\0\0").unwrap(); + + let section = object.add_section(Vec::new(), b".note4".to_vec(), SectionKind::Note); + object.section_mut(section).set_data(buffer, 4); + + // Add note section with align = 8. + let mut buffer = Vec::new(); + + buffer + .write(object::bytes_of(&elf::NoteHeader32 { + n_namesz: U32::new(endian, 6), + n_descsz: U32::new(endian, 11), + n_type: U32::new(endian, 1), + })) + .unwrap(); + buffer.write(b"name1\0\0\0\0\0\0\0").unwrap(); + buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); + + buffer + .write(object::bytes_of(&elf::NoteHeader32 { + n_namesz: U32::new(endian, 4), + n_descsz: U32::new(endian, 11), + n_type: U32::new(endian, 2), + })) + .unwrap(); + buffer.write(b"abc\0").unwrap(); + buffer.write(b"descriptor\0\0\0\0\0\0").unwrap(); + + let section = object.add_section(Vec::new(), b".note8".to_vec(), SectionKind::Note); + object.section_mut(section).set_data(buffer, 8); + + let bytes = &*object.write().unwrap(); + + //std::fs::write(&"note.o", &bytes).unwrap(); + + let header = elf::FileHeader64::parse(bytes).unwrap(); + let endian: LittleEndian = header.endian().unwrap(); + let sections = header.sections(endian, bytes).unwrap(); + + let section = sections.section(SectionIndex(1)).unwrap(); + assert_eq!(sections.section_name(endian, section).unwrap(), b".note4"); + assert_eq!(section.sh_addralign(endian), 4); + let mut notes = section.notes(endian, bytes).unwrap().unwrap(); + let note = notes.next().unwrap().unwrap(); + assert_eq!(note.name(), b"name1"); + assert_eq!(note.desc(), b"descriptor\0"); + assert_eq!(note.n_type(endian), 1); + let note = notes.next().unwrap().unwrap(); + assert_eq!(note.name(), b"name2"); + assert_eq!(note.desc(), b"descriptor\0"); + assert_eq!(note.n_type(endian), 2); + assert!(notes.next().unwrap().is_none()); + + let section = sections.section(SectionIndex(2)).unwrap(); + assert_eq!(sections.section_name(endian, section).unwrap(), b".note8"); + assert_eq!(section.sh_addralign(endian), 8); + let mut notes = section.notes(endian, bytes).unwrap().unwrap(); + let note = notes.next().unwrap().unwrap(); + assert_eq!(note.name(), b"name1"); + assert_eq!(note.desc(), b"descriptor\0"); + assert_eq!(note.n_type(endian), 1); + let note = notes.next().unwrap().unwrap(); + assert_eq!(note.name(), b"abc"); + assert_eq!(note.desc(), b"descriptor\0"); + assert_eq!(note.n_type(endian), 2); + assert!(notes.next().unwrap().is_none()); +} diff --git a/third_party/rust/object/tests/round_trip/macho.rs b/third_party/rust/object/tests/round_trip/macho.rs new file mode 100644 index 0000000000..ca3ad5ca2e --- /dev/null +++ b/third_party/rust/object/tests/round_trip/macho.rs @@ -0,0 +1,24 @@ +use object::read::macho::MachHeader; +use object::{macho, write, Architecture, BinaryFormat, Endianness}; + +#[test] +// Test that segment size is valid when the first section needs alignment. +fn issue_286_segment_file_size() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + let text = object.section_id(write::StandardSection::Text); + object.append_section_data(text, &[1; 30], 0x1000); + + let bytes = &*object.write().unwrap(); + let header = macho::MachHeader64::parse(bytes, 0).unwrap(); + let endian: Endianness = header.endian().unwrap(); + let mut commands = header.load_commands(endian, bytes, 0).unwrap(); + let command = commands.next().unwrap().unwrap(); + let (segment, _) = command.segment_64().unwrap().unwrap(); + assert_eq!(segment.vmsize.get(endian), 30); + assert_eq!(segment.filesize.get(endian), 30); +} diff --git a/third_party/rust/object/tests/round_trip/mod.rs b/third_party/rust/object/tests/round_trip/mod.rs new file mode 100644 index 0000000000..89bed8bf3c --- /dev/null +++ b/third_party/rust/object/tests/round_trip/mod.rs @@ -0,0 +1,451 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::read::{Object, ObjectSection, ObjectSymbol}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind, + SymbolFlags, SymbolKind, SymbolScope, SymbolSection, +}; + +mod bss; +mod coff; +mod comdat; +mod common; +mod elf; +mod macho; +mod section_flags; +mod tls; + +#[test] +fn coff_x86_64() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + object.add_file_symbol(b"file.c".to_vec()); + + let text = object.section_id(write::StandardSection::Text); + object.append_section_data(text, &[1; 30], 4); + + let func1_offset = object.append_section_data(text, &[1; 30], 4); + assert_eq!(func1_offset, 32); + let func1_symbol = object.add_symbol(write::Symbol { + name: b"func1".to_vec(), + value: func1_offset, + size: 32, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(text), + flags: SymbolFlags::None, + }); + object + .add_relocation( + text, + write::Relocation { + offset: 8, + size: 64, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol: func1_symbol, + addend: 0, + }, + ) + .unwrap(); + + let bytes = object.write().unwrap(); + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + assert_eq!(object.endianness(), Endianness::Little); + + let mut sections = object.sections(); + + let text = sections.next().unwrap(); + println!("{:?}", text); + let text_index = text.index(); + assert_eq!(text.name(), Ok(".text")); + assert_eq!(text.kind(), SectionKind::Text); + assert_eq!(text.address(), 0); + assert_eq!(text.size(), 62); + assert_eq!(&text.data().unwrap()[..30], &[1; 30]); + assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("file.c")); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.kind(), SymbolKind::File); + assert_eq!(symbol.section(), SymbolSection::None); + assert_eq!(symbol.scope(), SymbolScope::Compilation); + assert_eq!(symbol.is_weak(), false); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let func1_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("func1")); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.kind(), SymbolKind::Text); + assert_eq!(symbol.section_index(), Some(text_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let mut relocations = text.relocations(); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 8); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(func1_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let map = object.symbol_map(); + let symbol = map.get(func1_offset + 1).unwrap(); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.name(), "func1"); + assert_eq!(map.get(func1_offset - 1), None); +} + +#[test] +fn elf_x86_64() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + object.add_file_symbol(b"file.c".to_vec()); + + let text = object.section_id(write::StandardSection::Text); + object.append_section_data(text, &[1; 30], 4); + + let func1_offset = object.append_section_data(text, &[1; 30], 4); + assert_eq!(func1_offset, 32); + let func1_symbol = object.add_symbol(write::Symbol { + name: b"func1".to_vec(), + value: func1_offset, + size: 32, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(text), + flags: SymbolFlags::None, + }); + object + .add_relocation( + text, + write::Relocation { + offset: 8, + size: 64, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol: func1_symbol, + addend: 0, + }, + ) + .unwrap(); + + let bytes = object.write().unwrap(); + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + assert_eq!(object.endianness(), Endianness::Little); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok("")); + assert_eq!(section.kind(), SectionKind::Metadata); + assert_eq!(section.address(), 0); + assert_eq!(section.size(), 0); + + let text = sections.next().unwrap(); + println!("{:?}", text); + let text_index = text.index(); + assert_eq!(text.name(), Ok(".text")); + assert_eq!(text.kind(), SectionKind::Text); + assert_eq!(text.address(), 0); + assert_eq!(text.size(), 62); + assert_eq!(&text.data().unwrap()[..30], &[1; 30]); + assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("")); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.kind(), SymbolKind::Null); + assert_eq!(symbol.section_index(), None); + assert_eq!(symbol.scope(), SymbolScope::Unknown); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), true); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("file.c")); + assert_eq!(symbol.address(), 0); + assert_eq!(symbol.kind(), SymbolKind::File); + assert_eq!(symbol.section(), SymbolSection::None); + assert_eq!(symbol.scope(), SymbolScope::Compilation); + assert_eq!(symbol.is_weak(), false); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let func1_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("func1")); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.kind(), SymbolKind::Text); + assert_eq!(symbol.section_index(), Some(text_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let mut relocations = text.relocations(); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 8); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(func1_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let map = object.symbol_map(); + let symbol = map.get(func1_offset + 1).unwrap(); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.name(), "func1"); + assert_eq!(map.get(func1_offset - 1), None); +} + +#[test] +fn elf_any() { + for (arch, endian) in [ + (Architecture::Aarch64, Endianness::Little), + (Architecture::Aarch64_Ilp32, Endianness::Little), + (Architecture::Arm, Endianness::Little), + (Architecture::Avr, Endianness::Little), + (Architecture::Bpf, Endianness::Little), + (Architecture::I386, Endianness::Little), + (Architecture::X86_64, Endianness::Little), + (Architecture::X86_64_X32, Endianness::Little), + (Architecture::Hexagon, Endianness::Little), + (Architecture::LoongArch64, Endianness::Little), + (Architecture::Mips, Endianness::Little), + (Architecture::Mips64, Endianness::Little), + (Architecture::Msp430, Endianness::Little), + (Architecture::PowerPc, Endianness::Big), + (Architecture::PowerPc64, Endianness::Big), + (Architecture::Riscv32, Endianness::Little), + (Architecture::Riscv64, Endianness::Little), + (Architecture::S390x, Endianness::Big), + (Architecture::Sbf, Endianness::Little), + (Architecture::Sparc64, Endianness::Big), + (Architecture::Xtensa, Endianness::Little), + ] + .iter() + .copied() + { + let mut object = write::Object::new(BinaryFormat::Elf, arch, endian); + + let section = object.section_id(write::StandardSection::Data); + object.append_section_data(section, &[1; 30], 4); + let symbol = object.section_symbol(section); + + object + .add_relocation( + section, + write::Relocation { + offset: 8, + size: 32, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol, + addend: 0, + }, + ) + .unwrap(); + if arch.address_size().unwrap().bytes() >= 8 { + object + .add_relocation( + section, + write::Relocation { + offset: 16, + size: 64, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol, + addend: 0, + }, + ) + .unwrap(); + } + + let bytes = object.write().unwrap(); + let object = read::File::parse(&*bytes).unwrap(); + println!("{:?}", object.architecture()); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), arch); + assert_eq!(object.endianness(), endian); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok("")); + assert_eq!(section.kind(), SectionKind::Metadata); + assert_eq!(section.address(), 0); + assert_eq!(section.size(), 0); + + let data = sections.next().unwrap(); + println!("{:?}", data); + assert_eq!(data.name(), Ok(".data")); + assert_eq!(data.kind(), SectionKind::Data); + + let mut relocations = data.relocations(); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 8); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 32); + assert_eq!(relocation.addend(), 0); + + if arch.address_size().unwrap().bytes() >= 8 { + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 16); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!(relocation.addend(), 0); + } + } +} + +#[test] +fn macho_x86_64() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + object.add_file_symbol(b"file.c".to_vec()); + + let text = object.section_id(write::StandardSection::Text); + object.append_section_data(text, &[1; 30], 4); + + let func1_offset = object.append_section_data(text, &[1; 30], 4); + assert_eq!(func1_offset, 32); + let func1_symbol = object.add_symbol(write::Symbol { + name: b"func1".to_vec(), + value: func1_offset, + size: 32, + kind: SymbolKind::Text, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Section(text), + flags: SymbolFlags::None, + }); + object + .add_relocation( + text, + write::Relocation { + offset: 8, + size: 64, + kind: RelocationKind::Absolute, + encoding: RelocationEncoding::Generic, + symbol: func1_symbol, + addend: 0, + }, + ) + .unwrap(); + object + .add_relocation( + text, + write::Relocation { + offset: 16, + size: 32, + kind: RelocationKind::Relative, + encoding: RelocationEncoding::Generic, + symbol: func1_symbol, + addend: -4, + }, + ) + .unwrap(); + + let bytes = object.write().unwrap(); + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::MachO); + assert_eq!(object.architecture(), Architecture::X86_64); + assert_eq!(object.endianness(), Endianness::Little); + + let mut sections = object.sections(); + + let text = sections.next().unwrap(); + println!("{:?}", text); + let text_index = text.index(); + assert_eq!(text.name(), Ok("__text")); + assert_eq!(text.segment_name(), Ok(Some("__TEXT"))); + assert_eq!(text.kind(), SectionKind::Text); + assert_eq!(text.address(), 0); + assert_eq!(text.size(), 62); + assert_eq!(&text.data().unwrap()[..30], &[1; 30]); + assert_eq!(&text.data().unwrap()[32..62], &[1; 30]); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let func1_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("_func1")); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.kind(), SymbolKind::Text); + assert_eq!(symbol.section_index(), Some(text_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let mut relocations = text.relocations(); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 8); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(func1_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 16); + assert_eq!(relocation.kind(), RelocationKind::Relative); + assert_eq!(relocation.encoding(), RelocationEncoding::X86RipRelative); + assert_eq!(relocation.size(), 32); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(func1_symbol) + ); + assert_eq!(relocation.addend(), -4); + + let map = object.symbol_map(); + let symbol = map.get(func1_offset + 1).unwrap(); + assert_eq!(symbol.address(), func1_offset); + assert_eq!(symbol.name(), "_func1"); + assert_eq!(map.get(func1_offset - 1), None); +} diff --git a/third_party/rust/object/tests/round_trip/section_flags.rs b/third_party/rust/object/tests/round_trip/section_flags.rs new file mode 100644 index 0000000000..b1ca398b4c --- /dev/null +++ b/third_party/rust/object/tests/round_trip/section_flags.rs @@ -0,0 +1,90 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::read::{Object, ObjectSection}; +use object::{read, write}; +use object::{Architecture, BinaryFormat, Endianness, SectionFlags, SectionKind}; + +#[test] +fn coff_x86_64_section_flags() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); + object.section_mut(section).flags = SectionFlags::Coff { + characteristics: object::pe::IMAGE_SCN_MEM_WRITE, + }; + + let bytes = object.write().unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + let section = sections.next().unwrap(); + assert_eq!(section.name(), Ok(".text")); + assert_eq!( + section.flags(), + SectionFlags::Coff { + characteristics: object::pe::IMAGE_SCN_MEM_WRITE | object::pe::IMAGE_SCN_ALIGN_1BYTES, + } + ); +} + +#[test] +fn elf_x86_64_section_flags() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); + object.section_mut(section).flags = SectionFlags::Elf { + sh_flags: object::elf::SHF_WRITE.into(), + }; + + let bytes = object.write().unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + sections.next().unwrap(); + let section = sections.next().unwrap(); + assert_eq!(section.name(), Ok(".text")); + assert_eq!( + section.flags(), + SectionFlags::Elf { + sh_flags: object::elf::SHF_WRITE.into(), + } + ); +} + +#[test] +fn macho_x86_64_section_flags() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + let section = object.add_section(Vec::new(), b".text".to_vec(), SectionKind::Text); + object.section_mut(section).flags = SectionFlags::MachO { + flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, + }; + + let bytes = object.write().unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::MachO); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + let section = sections.next().unwrap(); + assert_eq!(section.name(), Ok(".text")); + assert_eq!( + section.flags(), + SectionFlags::MachO { + flags: object::macho::S_ATTR_SELF_MODIFYING_CODE, + } + ); +} diff --git a/third_party/rust/object/tests/round_trip/tls.rs b/third_party/rust/object/tests/round_trip/tls.rs new file mode 100644 index 0000000000..999e2f1815 --- /dev/null +++ b/third_party/rust/object/tests/round_trip/tls.rs @@ -0,0 +1,316 @@ +#![cfg(all(feature = "read", feature = "write"))] + +use object::read::{Object, ObjectSection, ObjectSymbol}; +use object::{read, write}; +use object::{ + Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind, + SymbolFlags, SymbolKind, SymbolScope, +}; + +#[test] +fn coff_x86_64_tls() { + let mut object = + write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little); + + let section = object.section_id(write::StandardSection::Tls); + let symbol = object.add_symbol(write::Symbol { + name: b"tls1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Tls, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_data(symbol, section, &[1; 30], 4); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"tls.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Coff); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + let tls_index = section.index(); + assert_eq!(section.name(), Ok(".tls$")); + assert_eq!(section.kind(), SectionKind::Data); + assert_eq!(section.size(), 30); + assert_eq!(§ion.data().unwrap()[..], &[1; 30]); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("tls1")); + assert_eq!(symbol.kind(), SymbolKind::Data); + assert_eq!(symbol.section_index(), Some(tls_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); +} + +#[test] +fn elf_x86_64_tls() { + let mut object = + write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little); + + let section = object.section_id(write::StandardSection::Tls); + let symbol = object.add_symbol(write::Symbol { + name: b"tls1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Tls, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_data(symbol, section, &[1; 30], 4); + + let section = object.section_id(write::StandardSection::UninitializedTls); + let symbol = object.add_symbol(write::Symbol { + name: b"tls2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Tls, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 31, 4); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"tls.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::Elf); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let section = sections.next().unwrap(); + println!("{:?}", section); + assert_eq!(section.name(), Ok("")); + + let section = sections.next().unwrap(); + println!("{:?}", section); + let tdata_index = section.index(); + assert_eq!(section.name(), Ok(".tdata")); + assert_eq!(section.kind(), SectionKind::Tls); + assert_eq!(section.size(), 30); + assert_eq!(§ion.data().unwrap()[..], &[1; 30]); + + let section = sections.next().unwrap(); + println!("{:?}", section); + let tbss_index = section.index(); + assert_eq!(section.name(), Ok(".tbss")); + assert_eq!(section.kind(), SectionKind::UninitializedTls); + assert_eq!(section.size(), 31); + assert_eq!(§ion.data().unwrap()[..], &[]); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("")); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("tls1")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(tdata_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.size(), 30); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("tls2")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(tbss_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + assert_eq!(symbol.size(), 31); +} + +#[test] +fn macho_x86_64_tls() { + let mut object = write::Object::new( + BinaryFormat::MachO, + Architecture::X86_64, + Endianness::Little, + ); + + let section = object.section_id(write::StandardSection::Tls); + let symbol = object.add_symbol(write::Symbol { + name: b"tls1".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Tls, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_data(symbol, section, &[1; 30], 4); + + let section = object.section_id(write::StandardSection::UninitializedTls); + let symbol = object.add_symbol(write::Symbol { + name: b"tls2".to_vec(), + value: 0, + size: 0, + kind: SymbolKind::Tls, + scope: SymbolScope::Linkage, + weak: false, + section: write::SymbolSection::Undefined, + flags: SymbolFlags::None, + }); + object.add_symbol_bss(symbol, section, 31, 4); + + let bytes = object.write().unwrap(); + + //std::fs::write(&"tls.o", &bytes).unwrap(); + + let object = read::File::parse(&*bytes).unwrap(); + assert_eq!(object.format(), BinaryFormat::MachO); + assert_eq!(object.architecture(), Architecture::X86_64); + + let mut sections = object.sections(); + + let thread_data = sections.next().unwrap(); + println!("{:?}", thread_data); + let thread_data_index = thread_data.index(); + assert_eq!(thread_data.name(), Ok("__thread_data")); + assert_eq!(thread_data.segment_name(), Ok(Some("__DATA"))); + assert_eq!(thread_data.kind(), SectionKind::Tls); + assert_eq!(thread_data.size(), 30); + assert_eq!(&thread_data.data().unwrap()[..], &[1; 30]); + + let thread_vars = sections.next().unwrap(); + println!("{:?}", thread_vars); + let thread_vars_index = thread_vars.index(); + assert_eq!(thread_vars.name(), Ok("__thread_vars")); + assert_eq!(thread_vars.segment_name(), Ok(Some("__DATA"))); + assert_eq!(thread_vars.kind(), SectionKind::TlsVariables); + assert_eq!(thread_vars.size(), 2 * 3 * 8); + assert_eq!(&thread_vars.data().unwrap()[..], &[0; 48][..]); + + let thread_bss = sections.next().unwrap(); + println!("{:?}", thread_bss); + let thread_bss_index = thread_bss.index(); + assert_eq!(thread_bss.name(), Ok("__thread_bss")); + assert_eq!(thread_bss.segment_name(), Ok(Some("__DATA"))); + assert_eq!(thread_bss.kind(), SectionKind::UninitializedTls); + assert_eq!(thread_bss.size(), 31); + assert_eq!(thread_bss.data(), Ok(&[][..])); + + let mut symbols = object.symbols(); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_tls1")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(thread_vars_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let tls1_init_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("_tls1$tlv$init")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(thread_data_index)); + assert_eq!(symbol.scope(), SymbolScope::Compilation); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let tlv_bootstrap_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("__tlv_bootstrap")); + assert_eq!(symbol.kind(), SymbolKind::Unknown); + assert_eq!(symbol.section_index(), None); + assert_eq!(symbol.scope(), SymbolScope::Unknown); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), true); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + assert_eq!(symbol.name(), Ok("_tls2")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(thread_vars_index)); + assert_eq!(symbol.scope(), SymbolScope::Linkage); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let symbol = symbols.next().unwrap(); + println!("{:?}", symbol); + let tls2_init_symbol = symbol.index(); + assert_eq!(symbol.name(), Ok("_tls2$tlv$init")); + assert_eq!(symbol.kind(), SymbolKind::Tls); + assert_eq!(symbol.section_index(), Some(thread_bss_index)); + assert_eq!(symbol.scope(), SymbolScope::Compilation); + assert_eq!(symbol.is_weak(), false); + assert_eq!(symbol.is_undefined(), false); + + let mut relocations = thread_vars.relocations(); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 0); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(tlv_bootstrap_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 16); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(tls1_init_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 24); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(tlv_bootstrap_symbol) + ); + assert_eq!(relocation.addend(), 0); + + let (offset, relocation) = relocations.next().unwrap(); + println!("{:?}", relocation); + assert_eq!(offset, 40); + assert_eq!(relocation.kind(), RelocationKind::Absolute); + assert_eq!(relocation.encoding(), RelocationEncoding::Generic); + assert_eq!(relocation.size(), 64); + assert_eq!( + relocation.target(), + read::RelocationTarget::Symbol(tls2_init_symbol) + ); + assert_eq!(relocation.addend(), 0); +} |