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