1 #![cfg(all(feature = "read", feature = "write"))]
2 
3 use object::read::{Object, ObjectSection, ObjectSymbol};
4 use object::{read, write};
5 use object::{
6     Architecture, BinaryFormat, Endianness, RelocationEncoding, RelocationKind, SectionKind,
7     SymbolFlags, SymbolKind, SymbolScope, SymbolSection,
8 };
9 
10 mod bss;
11 mod comdat;
12 mod common;
13 mod elf;
14 mod macho;
15 mod tls;
16 
17 #[test]
coff_x86_64()18 fn coff_x86_64() {
19     let mut object =
20         write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little);
21 
22     object.add_file_symbol(b"file.c".to_vec());
23 
24     let text = object.section_id(write::StandardSection::Text);
25     object.append_section_data(text, &[1; 30], 4);
26 
27     let func1_offset = object.append_section_data(text, &[1; 30], 4);
28     assert_eq!(func1_offset, 32);
29     let func1_symbol = object.add_symbol(write::Symbol {
30         name: b"func1".to_vec(),
31         value: func1_offset,
32         size: 32,
33         kind: SymbolKind::Text,
34         scope: SymbolScope::Linkage,
35         weak: false,
36         section: write::SymbolSection::Section(text),
37         flags: SymbolFlags::None,
38     });
39     object
40         .add_relocation(
41             text,
42             write::Relocation {
43                 offset: 8,
44                 size: 64,
45                 kind: RelocationKind::Absolute,
46                 encoding: RelocationEncoding::Generic,
47                 symbol: func1_symbol,
48                 addend: 0,
49             },
50         )
51         .unwrap();
52 
53     let bytes = object.write().unwrap();
54     let object = read::File::parse(&*bytes).unwrap();
55     assert_eq!(object.format(), BinaryFormat::Coff);
56     assert_eq!(object.architecture(), Architecture::X86_64);
57     assert_eq!(object.endianness(), Endianness::Little);
58 
59     let mut sections = object.sections();
60 
61     let text = sections.next().unwrap();
62     println!("{:?}", text);
63     let text_index = text.index();
64     assert_eq!(text.name(), Ok(".text"));
65     assert_eq!(text.kind(), SectionKind::Text);
66     assert_eq!(text.address(), 0);
67     assert_eq!(text.size(), 62);
68     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
69     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
70 
71     let mut symbols = object.symbols();
72 
73     let symbol = symbols.next().unwrap();
74     println!("{:?}", symbol);
75     assert_eq!(symbol.name(), Ok("file.c"));
76     assert_eq!(symbol.address(), 0);
77     assert_eq!(symbol.kind(), SymbolKind::File);
78     assert_eq!(symbol.section(), SymbolSection::None);
79     assert_eq!(symbol.scope(), SymbolScope::Compilation);
80     assert_eq!(symbol.is_weak(), false);
81 
82     let symbol = symbols.next().unwrap();
83     println!("{:?}", symbol);
84     let func1_symbol = symbol.index();
85     assert_eq!(symbol.name(), Ok("func1"));
86     assert_eq!(symbol.address(), func1_offset);
87     assert_eq!(symbol.kind(), SymbolKind::Text);
88     assert_eq!(symbol.section_index(), Some(text_index));
89     assert_eq!(symbol.scope(), SymbolScope::Linkage);
90     assert_eq!(symbol.is_weak(), false);
91     assert_eq!(symbol.is_undefined(), false);
92 
93     let mut relocations = text.relocations();
94 
95     let (offset, relocation) = relocations.next().unwrap();
96     println!("{:?}", relocation);
97     assert_eq!(offset, 8);
98     assert_eq!(relocation.kind(), RelocationKind::Absolute);
99     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
100     assert_eq!(relocation.size(), 64);
101     assert_eq!(
102         relocation.target(),
103         read::RelocationTarget::Symbol(func1_symbol)
104     );
105     assert_eq!(relocation.addend(), 0);
106 
107     let map = object.symbol_map();
108     let symbol = map.get(func1_offset + 1).unwrap();
109     assert_eq!(symbol.address(), func1_offset);
110     assert_eq!(symbol.name(), "func1");
111     assert_eq!(map.get(func1_offset - 1), None);
112 }
113 
114 #[test]
elf_x86_64()115 fn elf_x86_64() {
116     let mut object =
117         write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
118 
119     object.add_file_symbol(b"file.c".to_vec());
120 
121     let text = object.section_id(write::StandardSection::Text);
122     object.append_section_data(text, &[1; 30], 4);
123 
124     let func1_offset = object.append_section_data(text, &[1; 30], 4);
125     assert_eq!(func1_offset, 32);
126     let func1_symbol = object.add_symbol(write::Symbol {
127         name: b"func1".to_vec(),
128         value: func1_offset,
129         size: 32,
130         kind: SymbolKind::Text,
131         scope: SymbolScope::Linkage,
132         weak: false,
133         section: write::SymbolSection::Section(text),
134         flags: SymbolFlags::None,
135     });
136     object
137         .add_relocation(
138             text,
139             write::Relocation {
140                 offset: 8,
141                 size: 64,
142                 kind: RelocationKind::Absolute,
143                 encoding: RelocationEncoding::Generic,
144                 symbol: func1_symbol,
145                 addend: 0,
146             },
147         )
148         .unwrap();
149 
150     let bytes = object.write().unwrap();
151     let object = read::File::parse(&*bytes).unwrap();
152     assert_eq!(object.format(), BinaryFormat::Elf);
153     assert_eq!(object.architecture(), Architecture::X86_64);
154     assert_eq!(object.endianness(), Endianness::Little);
155 
156     let mut sections = object.sections();
157 
158     let section = sections.next().unwrap();
159     println!("{:?}", section);
160     assert_eq!(section.name(), Ok(""));
161     assert_eq!(section.kind(), SectionKind::Metadata);
162     assert_eq!(section.address(), 0);
163     assert_eq!(section.size(), 0);
164 
165     let text = sections.next().unwrap();
166     println!("{:?}", text);
167     let text_index = text.index();
168     assert_eq!(text.name(), Ok(".text"));
169     assert_eq!(text.kind(), SectionKind::Text);
170     assert_eq!(text.address(), 0);
171     assert_eq!(text.size(), 62);
172     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
173     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
174 
175     let mut symbols = object.symbols();
176 
177     let symbol = symbols.next().unwrap();
178     println!("{:?}", symbol);
179     assert_eq!(symbol.name(), Ok(""));
180     assert_eq!(symbol.address(), 0);
181     assert_eq!(symbol.kind(), SymbolKind::Null);
182     assert_eq!(symbol.section_index(), None);
183     assert_eq!(symbol.scope(), SymbolScope::Unknown);
184     assert_eq!(symbol.is_weak(), false);
185     assert_eq!(symbol.is_undefined(), true);
186 
187     let symbol = symbols.next().unwrap();
188     println!("{:?}", symbol);
189     assert_eq!(symbol.name(), Ok("file.c"));
190     assert_eq!(symbol.address(), 0);
191     assert_eq!(symbol.kind(), SymbolKind::File);
192     assert_eq!(symbol.section(), SymbolSection::None);
193     assert_eq!(symbol.scope(), SymbolScope::Compilation);
194     assert_eq!(symbol.is_weak(), false);
195 
196     let symbol = symbols.next().unwrap();
197     println!("{:?}", symbol);
198     let func1_symbol = symbol.index();
199     assert_eq!(symbol.name(), Ok("func1"));
200     assert_eq!(symbol.address(), func1_offset);
201     assert_eq!(symbol.kind(), SymbolKind::Text);
202     assert_eq!(symbol.section_index(), Some(text_index));
203     assert_eq!(symbol.scope(), SymbolScope::Linkage);
204     assert_eq!(symbol.is_weak(), false);
205     assert_eq!(symbol.is_undefined(), false);
206 
207     let mut relocations = text.relocations();
208 
209     let (offset, relocation) = relocations.next().unwrap();
210     println!("{:?}", relocation);
211     assert_eq!(offset, 8);
212     assert_eq!(relocation.kind(), RelocationKind::Absolute);
213     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
214     assert_eq!(relocation.size(), 64);
215     assert_eq!(
216         relocation.target(),
217         read::RelocationTarget::Symbol(func1_symbol)
218     );
219     assert_eq!(relocation.addend(), 0);
220 
221     let map = object.symbol_map();
222     let symbol = map.get(func1_offset + 1).unwrap();
223     assert_eq!(symbol.address(), func1_offset);
224     assert_eq!(symbol.name(), "func1");
225     assert_eq!(map.get(func1_offset - 1), None);
226 }
227 
228 #[test]
elf_any()229 fn elf_any() {
230     for (arch, endian) in [
231         (Architecture::Aarch64, Endianness::Little),
232         (Architecture::Arm, Endianness::Little),
233         (Architecture::Avr, Endianness::Little),
234         (Architecture::Bpf, Endianness::Little),
235         (Architecture::I386, Endianness::Little),
236         (Architecture::X86_64, Endianness::Little),
237         (Architecture::X86_64_X32, Endianness::Little),
238         (Architecture::Hexagon, Endianness::Little),
239         (Architecture::Mips, Endianness::Little),
240         (Architecture::Mips64, Endianness::Little),
241         (Architecture::Msp430, Endianness::Little),
242         (Architecture::PowerPc, Endianness::Big),
243         (Architecture::PowerPc64, Endianness::Big),
244         (Architecture::Riscv32, Endianness::Little),
245         (Architecture::Riscv64, Endianness::Little),
246         (Architecture::S390x, Endianness::Big),
247         (Architecture::Sparc64, Endianness::Big),
248     ]
249     .iter()
250     .copied()
251     {
252         let mut object = write::Object::new(BinaryFormat::Elf, arch, endian);
253 
254         let section = object.section_id(write::StandardSection::Data);
255         object.append_section_data(section, &[1; 30], 4);
256         let symbol = object.section_symbol(section);
257 
258         object
259             .add_relocation(
260                 section,
261                 write::Relocation {
262                     offset: 8,
263                     size: 32,
264                     kind: RelocationKind::Absolute,
265                     encoding: RelocationEncoding::Generic,
266                     symbol,
267                     addend: 0,
268                 },
269             )
270             .unwrap();
271         if arch.address_size().unwrap().bytes() >= 8 {
272             object
273                 .add_relocation(
274                     section,
275                     write::Relocation {
276                         offset: 16,
277                         size: 64,
278                         kind: RelocationKind::Absolute,
279                         encoding: RelocationEncoding::Generic,
280                         symbol,
281                         addend: 0,
282                     },
283                 )
284                 .unwrap();
285         }
286 
287         let bytes = object.write().unwrap();
288         let object = read::File::parse(&*bytes).unwrap();
289         println!("{:?}", object.architecture());
290         assert_eq!(object.format(), BinaryFormat::Elf);
291         assert_eq!(object.architecture(), arch);
292         assert_eq!(object.endianness(), endian);
293 
294         let mut sections = object.sections();
295 
296         let section = sections.next().unwrap();
297         println!("{:?}", section);
298         assert_eq!(section.name(), Ok(""));
299         assert_eq!(section.kind(), SectionKind::Metadata);
300         assert_eq!(section.address(), 0);
301         assert_eq!(section.size(), 0);
302 
303         let data = sections.next().unwrap();
304         println!("{:?}", data);
305         assert_eq!(data.name(), Ok(".data"));
306         assert_eq!(data.kind(), SectionKind::Data);
307 
308         let mut relocations = data.relocations();
309 
310         let (offset, relocation) = relocations.next().unwrap();
311         println!("{:?}", relocation);
312         assert_eq!(offset, 8);
313         assert_eq!(relocation.kind(), RelocationKind::Absolute);
314         assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
315         assert_eq!(relocation.size(), 32);
316         assert_eq!(relocation.addend(), 0);
317 
318         if arch.address_size().unwrap().bytes() >= 8 {
319             let (offset, relocation) = relocations.next().unwrap();
320             println!("{:?}", relocation);
321             assert_eq!(offset, 16);
322             assert_eq!(relocation.kind(), RelocationKind::Absolute);
323             assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
324             assert_eq!(relocation.size(), 64);
325             assert_eq!(relocation.addend(), 0);
326         }
327     }
328 }
329 
330 #[test]
macho_x86_64()331 fn macho_x86_64() {
332     let mut object = write::Object::new(
333         BinaryFormat::MachO,
334         Architecture::X86_64,
335         Endianness::Little,
336     );
337 
338     object.add_file_symbol(b"file.c".to_vec());
339 
340     let text = object.section_id(write::StandardSection::Text);
341     object.append_section_data(text, &[1; 30], 4);
342 
343     let func1_offset = object.append_section_data(text, &[1; 30], 4);
344     assert_eq!(func1_offset, 32);
345     let func1_symbol = object.add_symbol(write::Symbol {
346         name: b"func1".to_vec(),
347         value: func1_offset,
348         size: 32,
349         kind: SymbolKind::Text,
350         scope: SymbolScope::Linkage,
351         weak: false,
352         section: write::SymbolSection::Section(text),
353         flags: SymbolFlags::None,
354     });
355     object
356         .add_relocation(
357             text,
358             write::Relocation {
359                 offset: 8,
360                 size: 64,
361                 kind: RelocationKind::Absolute,
362                 encoding: RelocationEncoding::Generic,
363                 symbol: func1_symbol,
364                 addend: 0,
365             },
366         )
367         .unwrap();
368     object
369         .add_relocation(
370             text,
371             write::Relocation {
372                 offset: 16,
373                 size: 32,
374                 kind: RelocationKind::Relative,
375                 encoding: RelocationEncoding::Generic,
376                 symbol: func1_symbol,
377                 addend: -4,
378             },
379         )
380         .unwrap();
381 
382     let bytes = object.write().unwrap();
383     let object = read::File::parse(&*bytes).unwrap();
384     assert_eq!(object.format(), BinaryFormat::MachO);
385     assert_eq!(object.architecture(), Architecture::X86_64);
386     assert_eq!(object.endianness(), Endianness::Little);
387 
388     let mut sections = object.sections();
389 
390     let text = sections.next().unwrap();
391     println!("{:?}", text);
392     let text_index = text.index();
393     assert_eq!(text.name(), Ok("__text"));
394     assert_eq!(text.segment_name(), Ok(Some("__TEXT")));
395     assert_eq!(text.kind(), SectionKind::Text);
396     assert_eq!(text.address(), 0);
397     assert_eq!(text.size(), 62);
398     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
399     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
400 
401     let mut symbols = object.symbols();
402 
403     let symbol = symbols.next().unwrap();
404     println!("{:?}", symbol);
405     let func1_symbol = symbol.index();
406     assert_eq!(symbol.name(), Ok("_func1"));
407     assert_eq!(symbol.address(), func1_offset);
408     assert_eq!(symbol.kind(), SymbolKind::Text);
409     assert_eq!(symbol.section_index(), Some(text_index));
410     assert_eq!(symbol.scope(), SymbolScope::Linkage);
411     assert_eq!(symbol.is_weak(), false);
412     assert_eq!(symbol.is_undefined(), false);
413 
414     let mut relocations = text.relocations();
415 
416     let (offset, relocation) = relocations.next().unwrap();
417     println!("{:?}", relocation);
418     assert_eq!(offset, 8);
419     assert_eq!(relocation.kind(), RelocationKind::Absolute);
420     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
421     assert_eq!(relocation.size(), 64);
422     assert_eq!(
423         relocation.target(),
424         read::RelocationTarget::Symbol(func1_symbol)
425     );
426     assert_eq!(relocation.addend(), 0);
427 
428     let (offset, relocation) = relocations.next().unwrap();
429     println!("{:?}", relocation);
430     assert_eq!(offset, 16);
431     assert_eq!(relocation.kind(), RelocationKind::Relative);
432     assert_eq!(relocation.encoding(), RelocationEncoding::X86RipRelative);
433     assert_eq!(relocation.size(), 32);
434     assert_eq!(
435         relocation.target(),
436         read::RelocationTarget::Symbol(func1_symbol)
437     );
438     assert_eq!(relocation.addend(), -4);
439 
440     let map = object.symbol_map();
441     let symbol = map.get(func1_offset + 1).unwrap();
442     assert_eq!(symbol.address(), func1_offset);
443     assert_eq!(symbol.name(), "_func1");
444     assert_eq!(map.get(func1_offset - 1), None);
445 }
446