diff options
Diffstat (limited to 'third_party/rust/goblin/tests/archive.rs')
-rw-r--r-- | third_party/rust/goblin/tests/archive.rs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/third_party/rust/goblin/tests/archive.rs b/third_party/rust/goblin/tests/archive.rs new file mode 100644 index 0000000000..a74007f4b8 --- /dev/null +++ b/third_party/rust/goblin/tests/archive.rs @@ -0,0 +1,100 @@ +use goblin::archive::*; +use scroll::Pread; +use std::path::Path; +use std::fs::File; + +#[test] +fn parse_file_header() { + let file_header: [u8; SIZEOF_HEADER] = [0x2f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x30, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, + 0x32, 0x34, 0x34, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x60, 0x0a]; + let buffer = &file_header[..]; + match buffer.pread::<MemberHeader>(0) { + Err(e) => panic!("could not read the buffer: {:?}", e), + Ok(file_header2) => { + let file_header = MemberHeader { + identifier: [0x2f,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,], + timestamp: [48, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32], + owner_id: [48, 32, 32, 32, 32, 32], + group_id: [48, 32, 32, 32, 32, 32], + mode: [48, 32, 32, 32, 32, 32, 32, 32], + file_size: [56, 50, 52, 52, 32, 32, 32, 32, 32, 32], + terminator: [96, 10] }; + assert_eq!(file_header, file_header2) + } + } +} + +#[test] +fn parse_archive() { + let crt1a: Vec<u8> = include!("../etc/crt1a.rs"); + const START: &str = "_start"; + match Archive::parse(&crt1a) { + Ok(archive) => { + assert_eq!(archive.member_of_symbol(START), Some("crt1.o")); + if let Some(member) = archive.get("crt1.o") { + assert_eq!(member.offset, 194); + assert_eq!(member.size(), 1928) + } else { + panic!("could not get crt1.o"); + } + }, + Err(err) => panic!("could not parse archive: {:?}", err), + }; +} + +#[test] +fn parse_self() { + use std::fs; + use std::io::Read; + let mut path = Path::new("target").join("debug").join("libgoblin.rlib"); + // https://github.com/m4b/goblin/issues/63 + if fs::metadata(&path).is_err() { + path = Path::new("target").join("release").join("libgoblin.rlib"); + } + let buffer = { + let mut fd = File::open(path).expect("can open file; did you run cargo build first?"); + let mut v = Vec::new(); + fd.read_to_end(&mut v).expect("read file"); + v + }; + + let archive = Archive::parse(&buffer).expect("parse rlib"); + + // check that the archive has a useful symbol table by counting the total number of symbols + let symbol_count: usize = archive.summarize().into_iter() + .map(|(_member_name, _member_index, ref symbols)| symbols.len()) + .sum(); + assert!(symbol_count > 500); + + let goblin_object_name = archive.members() + .into_iter() + .find(|member| { + println!("member: {:?}", member); + member.ends_with("goblin-archive.o") // < 1.18 + || (member.starts_with("goblin") && member.ends_with("0.o")) // >= 1.18 && < 1.22 + || (member.starts_with("goblin") && member.ends_with("rust-cgu.o")) // = 1.22 + || (member.starts_with("goblin") && member.ends_with("rcgu.o")) // >= nightly 1.23 + }) + .expect("goblin-<hash>.0.o not found"); + + let bytes = archive.extract(goblin_object_name, &buffer).expect("extract goblin object"); + match goblin::Object::parse(&bytes).expect("parse object") { + goblin::Object::Elf(elf) => { + assert!(elf.entry == 0); + } + goblin::Object::Mach(goblin::mach::Mach::Binary(macho)) => { + assert_eq!(macho.header.filetype, goblin::mach::header::MH_OBJECT); + assert_eq!(macho.entry, 0); + } + other => { + panic!("unexpected Object::parse result: {:?}", other); + } + } +} |