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