1 #![cfg(all(feature = "read", feature = "write"))]
2 
3 use object::read::{Object, ObjectSection};
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 common;
12 mod elf;
13 mod tls;
14 
15 #[test]
coff_x86_64()16 fn coff_x86_64() {
17     let mut object =
18         write::Object::new(BinaryFormat::Coff, Architecture::X86_64, Endianness::Little);
19 
20     object.add_file_symbol(b"file.c".to_vec());
21 
22     let text = object.section_id(write::StandardSection::Text);
23     object.append_section_data(text, &[1; 30], 4);
24 
25     let func1_offset = object.append_section_data(text, &[1; 30], 4);
26     assert_eq!(func1_offset, 32);
27     let func1_symbol = object.add_symbol(write::Symbol {
28         name: b"func1".to_vec(),
29         value: func1_offset,
30         size: 32,
31         kind: SymbolKind::Text,
32         scope: SymbolScope::Linkage,
33         weak: false,
34         section: write::SymbolSection::Section(text),
35         flags: SymbolFlags::None,
36     });
37     object
38         .add_relocation(
39             text,
40             write::Relocation {
41                 offset: 8,
42                 size: 64,
43                 kind: RelocationKind::Absolute,
44                 encoding: RelocationEncoding::Generic,
45                 symbol: func1_symbol,
46                 addend: 0,
47             },
48         )
49         .unwrap();
50 
51     let bytes = object.write().unwrap();
52     let object = read::File::parse(&bytes).unwrap();
53     assert_eq!(object.format(), BinaryFormat::Coff);
54     assert_eq!(object.architecture(), Architecture::X86_64);
55     assert_eq!(object.endianness(), Endianness::Little);
56 
57     let mut sections = object.sections();
58 
59     let text = sections.next().unwrap();
60     println!("{:?}", text);
61     let text_index = text.index();
62     assert_eq!(text.name(), Ok(".text"));
63     assert_eq!(text.kind(), SectionKind::Text);
64     assert_eq!(text.address(), 0);
65     assert_eq!(text.size(), 62);
66     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
67     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
68 
69     let mut symbols = object.symbols();
70 
71     let (_, symbol) = symbols.next().unwrap();
72     println!("{:?}", symbol);
73     assert_eq!(symbol.name(), Some("file.c"));
74     assert_eq!(symbol.address(), 0);
75     assert_eq!(symbol.kind(), SymbolKind::File);
76     assert_eq!(symbol.section(), SymbolSection::None);
77     assert_eq!(symbol.scope(), SymbolScope::Compilation);
78     assert_eq!(symbol.is_weak(), false);
79 
80     let (func1_symbol, symbol) = symbols.next().unwrap();
81     println!("{:?}", symbol);
82     assert_eq!(symbol.name(), Some("func1"));
83     assert_eq!(symbol.address(), func1_offset);
84     assert_eq!(symbol.kind(), SymbolKind::Text);
85     assert_eq!(symbol.section_index(), Some(text_index));
86     assert_eq!(symbol.scope(), SymbolScope::Linkage);
87     assert_eq!(symbol.is_weak(), false);
88     assert_eq!(symbol.is_undefined(), false);
89 
90     let mut relocations = text.relocations();
91 
92     let (offset, relocation) = relocations.next().unwrap();
93     println!("{:?}", relocation);
94     assert_eq!(offset, 8);
95     assert_eq!(relocation.kind(), RelocationKind::Absolute);
96     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
97     assert_eq!(relocation.size(), 64);
98     assert_eq!(
99         relocation.target(),
100         read::RelocationTarget::Symbol(func1_symbol)
101     );
102     assert_eq!(relocation.addend(), 0);
103 }
104 
105 #[test]
elf_x86_64()106 fn elf_x86_64() {
107     let mut object =
108         write::Object::new(BinaryFormat::Elf, Architecture::X86_64, Endianness::Little);
109 
110     object.add_file_symbol(b"file.c".to_vec());
111 
112     let text = object.section_id(write::StandardSection::Text);
113     object.append_section_data(text, &[1; 30], 4);
114 
115     let func1_offset = object.append_section_data(text, &[1; 30], 4);
116     assert_eq!(func1_offset, 32);
117     let func1_symbol = object.add_symbol(write::Symbol {
118         name: b"func1".to_vec(),
119         value: func1_offset,
120         size: 32,
121         kind: SymbolKind::Text,
122         scope: SymbolScope::Linkage,
123         weak: false,
124         section: write::SymbolSection::Section(text),
125         flags: SymbolFlags::None,
126     });
127     object
128         .add_relocation(
129             text,
130             write::Relocation {
131                 offset: 8,
132                 size: 64,
133                 kind: RelocationKind::Absolute,
134                 encoding: RelocationEncoding::Generic,
135                 symbol: func1_symbol,
136                 addend: 0,
137             },
138         )
139         .unwrap();
140 
141     let bytes = object.write().unwrap();
142     let object = read::File::parse(&bytes).unwrap();
143     assert_eq!(object.format(), BinaryFormat::Elf);
144     assert_eq!(object.architecture(), Architecture::X86_64);
145     assert_eq!(object.endianness(), Endianness::Little);
146 
147     let mut sections = object.sections();
148 
149     let section = sections.next().unwrap();
150     println!("{:?}", section);
151     assert_eq!(section.name(), Ok(""));
152     assert_eq!(section.kind(), SectionKind::Metadata);
153     assert_eq!(section.address(), 0);
154     assert_eq!(section.size(), 0);
155 
156     let text = sections.next().unwrap();
157     println!("{:?}", text);
158     let text_index = text.index();
159     assert_eq!(text.name(), Ok(".text"));
160     assert_eq!(text.kind(), SectionKind::Text);
161     assert_eq!(text.address(), 0);
162     assert_eq!(text.size(), 62);
163     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
164     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
165 
166     let mut symbols = object.symbols();
167 
168     let (_, symbol) = symbols.next().unwrap();
169     println!("{:?}", symbol);
170     assert_eq!(symbol.name(), Some(""));
171     assert_eq!(symbol.address(), 0);
172     assert_eq!(symbol.kind(), SymbolKind::Null);
173     assert_eq!(symbol.section_index(), None);
174     assert_eq!(symbol.scope(), SymbolScope::Unknown);
175     assert_eq!(symbol.is_weak(), false);
176     assert_eq!(symbol.is_undefined(), true);
177 
178     let (_, symbol) = symbols.next().unwrap();
179     println!("{:?}", symbol);
180     assert_eq!(symbol.name(), Some("file.c"));
181     assert_eq!(symbol.address(), 0);
182     assert_eq!(symbol.kind(), SymbolKind::File);
183     assert_eq!(symbol.section(), SymbolSection::None);
184     assert_eq!(symbol.scope(), SymbolScope::Compilation);
185     assert_eq!(symbol.is_weak(), false);
186 
187     let (func1_symbol, symbol) = symbols.next().unwrap();
188     println!("{:?}", symbol);
189     assert_eq!(symbol.name(), Some("func1"));
190     assert_eq!(symbol.address(), func1_offset);
191     assert_eq!(symbol.kind(), SymbolKind::Text);
192     assert_eq!(symbol.section_index(), Some(text_index));
193     assert_eq!(symbol.scope(), SymbolScope::Linkage);
194     assert_eq!(symbol.is_weak(), false);
195     assert_eq!(symbol.is_undefined(), false);
196 
197     let mut relocations = text.relocations();
198 
199     let (offset, relocation) = relocations.next().unwrap();
200     println!("{:?}", relocation);
201     assert_eq!(offset, 8);
202     assert_eq!(relocation.kind(), RelocationKind::Absolute);
203     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
204     assert_eq!(relocation.size(), 64);
205     assert_eq!(
206         relocation.target(),
207         read::RelocationTarget::Symbol(func1_symbol)
208     );
209     assert_eq!(relocation.addend(), 0);
210 }
211 
212 #[test]
macho_x86_64()213 fn macho_x86_64() {
214     let mut object = write::Object::new(
215         BinaryFormat::MachO,
216         Architecture::X86_64,
217         Endianness::Little,
218     );
219 
220     object.add_file_symbol(b"file.c".to_vec());
221 
222     let text = object.section_id(write::StandardSection::Text);
223     object.append_section_data(text, &[1; 30], 4);
224 
225     let func1_offset = object.append_section_data(text, &[1; 30], 4);
226     assert_eq!(func1_offset, 32);
227     let func1_symbol = object.add_symbol(write::Symbol {
228         name: b"func1".to_vec(),
229         value: func1_offset,
230         size: 32,
231         kind: SymbolKind::Text,
232         scope: SymbolScope::Linkage,
233         weak: false,
234         section: write::SymbolSection::Section(text),
235         flags: SymbolFlags::None,
236     });
237     object
238         .add_relocation(
239             text,
240             write::Relocation {
241                 offset: 8,
242                 size: 64,
243                 kind: RelocationKind::Absolute,
244                 encoding: RelocationEncoding::Generic,
245                 symbol: func1_symbol,
246                 addend: 0,
247             },
248         )
249         .unwrap();
250     object
251         .add_relocation(
252             text,
253             write::Relocation {
254                 offset: 16,
255                 size: 32,
256                 kind: RelocationKind::Relative,
257                 encoding: RelocationEncoding::Generic,
258                 symbol: func1_symbol,
259                 addend: -4,
260             },
261         )
262         .unwrap();
263 
264     let bytes = object.write().unwrap();
265     let object = read::File::parse(&bytes).unwrap();
266     assert_eq!(object.format(), BinaryFormat::MachO);
267     assert_eq!(object.architecture(), Architecture::X86_64);
268     assert_eq!(object.endianness(), Endianness::Little);
269 
270     let mut sections = object.sections();
271 
272     let text = sections.next().unwrap();
273     println!("{:?}", text);
274     let text_index = text.index();
275     assert_eq!(text.name(), Ok("__text"));
276     assert_eq!(text.segment_name(), Ok(Some("__TEXT")));
277     assert_eq!(text.kind(), SectionKind::Text);
278     assert_eq!(text.address(), 0);
279     assert_eq!(text.size(), 62);
280     assert_eq!(&text.data().unwrap()[..30], &[1; 30]);
281     assert_eq!(&text.data().unwrap()[32..62], &[1; 30]);
282 
283     let mut symbols = object.symbols();
284 
285     let (func1_symbol, symbol) = symbols.next().unwrap();
286     println!("{:?}", symbol);
287     assert_eq!(symbol.name(), Some("_func1"));
288     assert_eq!(symbol.address(), func1_offset);
289     assert_eq!(symbol.kind(), SymbolKind::Text);
290     assert_eq!(symbol.section_index(), Some(text_index));
291     assert_eq!(symbol.scope(), SymbolScope::Linkage);
292     assert_eq!(symbol.is_weak(), false);
293     assert_eq!(symbol.is_undefined(), false);
294 
295     let mut relocations = text.relocations();
296 
297     let (offset, relocation) = relocations.next().unwrap();
298     println!("{:?}", relocation);
299     assert_eq!(offset, 8);
300     assert_eq!(relocation.kind(), RelocationKind::Absolute);
301     assert_eq!(relocation.encoding(), RelocationEncoding::Generic);
302     assert_eq!(relocation.size(), 64);
303     assert_eq!(
304         relocation.target(),
305         read::RelocationTarget::Symbol(func1_symbol)
306     );
307     assert_eq!(relocation.addend(), 0);
308 
309     let (offset, relocation) = relocations.next().unwrap();
310     println!("{:?}", relocation);
311     assert_eq!(offset, 16);
312     assert_eq!(relocation.kind(), RelocationKind::Relative);
313     assert_eq!(relocation.encoding(), RelocationEncoding::X86RipRelative);
314     assert_eq!(relocation.size(), 32);
315     assert_eq!(
316         relocation.target(),
317         read::RelocationTarget::Symbol(func1_symbol)
318     );
319     assert_eq!(relocation.addend(), -4);
320 }
321