]>
Commit | Line | Data |
---|---|---|
f035d41b XL |
1 | use alloc::fmt; |
2 | ||
3 | #[cfg(feature = "coff")] | |
4 | use crate::read::coff; | |
5 | #[cfg(feature = "elf")] | |
6 | use crate::read::elf; | |
7 | #[cfg(feature = "macho")] | |
8 | use crate::read::macho; | |
9 | #[cfg(feature = "pe")] | |
10 | use crate::read::pe; | |
11 | #[cfg(feature = "wasm")] | |
12 | use crate::read::wasm; | |
13 | use crate::read::{ | |
14 | self, Architecture, BinaryFormat, CompressedData, Error, FileFlags, Object, ObjectSection, | |
15 | ObjectSegment, Relocation, Result, SectionFlags, SectionIndex, SectionKind, Symbol, | |
16 | SymbolIndex, SymbolMap, | |
17 | }; | |
18 | ||
19 | /// Evaluate an expression on the contents of a file format enum. | |
20 | /// | |
21 | /// This is a hack to avoid virtual calls. | |
22 | macro_rules! with_inner { | |
23 | ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { | |
24 | match $inner { | |
25 | #[cfg(feature = "coff")] | |
26 | $enum::Coff(ref $var) => $body, | |
27 | #[cfg(feature = "elf")] | |
28 | $enum::Elf32(ref $var) => $body, | |
29 | #[cfg(feature = "elf")] | |
30 | $enum::Elf64(ref $var) => $body, | |
31 | #[cfg(feature = "macho")] | |
32 | $enum::MachO32(ref $var) => $body, | |
33 | #[cfg(feature = "macho")] | |
34 | $enum::MachO64(ref $var) => $body, | |
35 | #[cfg(feature = "pe")] | |
36 | $enum::Pe32(ref $var) => $body, | |
37 | #[cfg(feature = "pe")] | |
38 | $enum::Pe64(ref $var) => $body, | |
39 | #[cfg(feature = "wasm")] | |
40 | $enum::Wasm(ref $var) => $body, | |
41 | } | |
42 | }; | |
43 | } | |
44 | ||
45 | macro_rules! with_inner_mut { | |
46 | ($inner:expr, $enum:ident, | $var:ident | $body:expr) => { | |
47 | match $inner { | |
48 | #[cfg(feature = "coff")] | |
49 | $enum::Coff(ref mut $var) => $body, | |
50 | #[cfg(feature = "elf")] | |
51 | $enum::Elf32(ref mut $var) => $body, | |
52 | #[cfg(feature = "elf")] | |
53 | $enum::Elf64(ref mut $var) => $body, | |
54 | #[cfg(feature = "macho")] | |
55 | $enum::MachO32(ref mut $var) => $body, | |
56 | #[cfg(feature = "macho")] | |
57 | $enum::MachO64(ref mut $var) => $body, | |
58 | #[cfg(feature = "pe")] | |
59 | $enum::Pe32(ref mut $var) => $body, | |
60 | #[cfg(feature = "pe")] | |
61 | $enum::Pe64(ref mut $var) => $body, | |
62 | #[cfg(feature = "wasm")] | |
63 | $enum::Wasm(ref mut $var) => $body, | |
64 | } | |
65 | }; | |
66 | } | |
67 | ||
68 | /// Like `with_inner!`, but wraps the result in another enum. | |
69 | macro_rules! map_inner { | |
70 | ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { | |
71 | match $inner { | |
72 | #[cfg(feature = "coff")] | |
73 | $from::Coff(ref $var) => $to::Coff($body), | |
74 | #[cfg(feature = "elf")] | |
75 | $from::Elf32(ref $var) => $to::Elf32($body), | |
76 | #[cfg(feature = "elf")] | |
77 | $from::Elf64(ref $var) => $to::Elf64($body), | |
78 | #[cfg(feature = "macho")] | |
79 | $from::MachO32(ref $var) => $to::MachO32($body), | |
80 | #[cfg(feature = "macho")] | |
81 | $from::MachO64(ref $var) => $to::MachO64($body), | |
82 | #[cfg(feature = "pe")] | |
83 | $from::Pe32(ref $var) => $to::Pe32($body), | |
84 | #[cfg(feature = "pe")] | |
85 | $from::Pe64(ref $var) => $to::Pe64($body), | |
86 | #[cfg(feature = "wasm")] | |
87 | $from::Wasm(ref $var) => $to::Wasm($body), | |
88 | } | |
89 | }; | |
90 | } | |
91 | ||
92 | /// Like `map_inner!`, but the result is a Result or Option. | |
93 | macro_rules! map_inner_option { | |
94 | ($inner:expr, $from:ident, $to:ident, | $var:ident | $body:expr) => { | |
95 | match $inner { | |
96 | #[cfg(feature = "coff")] | |
97 | $from::Coff(ref $var) => $body.map($to::Coff), | |
98 | #[cfg(feature = "elf")] | |
99 | $from::Elf32(ref $var) => $body.map($to::Elf32), | |
100 | #[cfg(feature = "elf")] | |
101 | $from::Elf64(ref $var) => $body.map($to::Elf64), | |
102 | #[cfg(feature = "macho")] | |
103 | $from::MachO32(ref $var) => $body.map($to::MachO32), | |
104 | #[cfg(feature = "macho")] | |
105 | $from::MachO64(ref $var) => $body.map($to::MachO64), | |
106 | #[cfg(feature = "pe")] | |
107 | $from::Pe32(ref $var) => $body.map($to::Pe32), | |
108 | #[cfg(feature = "pe")] | |
109 | $from::Pe64(ref $var) => $body.map($to::Pe64), | |
110 | #[cfg(feature = "wasm")] | |
111 | $from::Wasm(ref $var) => $body.map($to::Wasm), | |
112 | } | |
113 | }; | |
114 | } | |
115 | ||
116 | /// Call `next` for a file format iterator. | |
117 | macro_rules! next_inner { | |
118 | ($inner:expr, $from:ident, $to:ident) => { | |
119 | match $inner { | |
120 | #[cfg(feature = "coff")] | |
121 | $from::Coff(ref mut iter) => iter.next().map($to::Coff), | |
122 | #[cfg(feature = "elf")] | |
123 | $from::Elf32(ref mut iter) => iter.next().map($to::Elf32), | |
124 | #[cfg(feature = "elf")] | |
125 | $from::Elf64(ref mut iter) => iter.next().map($to::Elf64), | |
126 | #[cfg(feature = "macho")] | |
127 | $from::MachO32(ref mut iter) => iter.next().map($to::MachO32), | |
128 | #[cfg(feature = "macho")] | |
129 | $from::MachO64(ref mut iter) => iter.next().map($to::MachO64), | |
130 | #[cfg(feature = "pe")] | |
131 | $from::Pe32(ref mut iter) => iter.next().map($to::Pe32), | |
132 | #[cfg(feature = "pe")] | |
133 | $from::Pe64(ref mut iter) => iter.next().map($to::Pe64), | |
134 | #[cfg(feature = "wasm")] | |
135 | $from::Wasm(ref mut iter) => iter.next().map($to::Wasm), | |
136 | } | |
137 | }; | |
138 | } | |
139 | ||
140 | /// An object file. | |
141 | /// | |
142 | /// Most functionality is provided by the `Object` trait implementation. | |
143 | #[derive(Debug)] | |
144 | pub struct File<'data> { | |
145 | inner: FileInternal<'data>, | |
146 | } | |
147 | ||
148 | #[allow(clippy::large_enum_variant)] | |
149 | #[derive(Debug)] | |
150 | enum FileInternal<'data> { | |
151 | #[cfg(feature = "coff")] | |
152 | Coff(coff::CoffFile<'data>), | |
153 | #[cfg(feature = "elf")] | |
154 | Elf32(elf::ElfFile32<'data>), | |
155 | #[cfg(feature = "elf")] | |
156 | Elf64(elf::ElfFile64<'data>), | |
157 | #[cfg(feature = "macho")] | |
158 | MachO32(macho::MachOFile32<'data>), | |
159 | #[cfg(feature = "macho")] | |
160 | MachO64(macho::MachOFile64<'data>), | |
161 | #[cfg(feature = "pe")] | |
162 | Pe32(pe::PeFile32<'data>), | |
163 | #[cfg(feature = "pe")] | |
164 | Pe64(pe::PeFile64<'data>), | |
165 | #[cfg(feature = "wasm")] | |
166 | Wasm(wasm::WasmFile<'data>), | |
167 | } | |
168 | ||
169 | impl<'data> File<'data> { | |
170 | /// Parse the raw file data. | |
171 | pub fn parse(data: &'data [u8]) -> Result<Self> { | |
172 | if data.len() < 16 { | |
173 | return Err(Error("File too short")); | |
174 | } | |
175 | ||
176 | let inner = match [data[0], data[1], data[2], data[3], data[4]] { | |
177 | // 32-bit ELF | |
178 | #[cfg(feature = "elf")] | |
179 | [0x7f, b'E', b'L', b'F', 1] => FileInternal::Elf32(elf::ElfFile32::parse(data)?), | |
180 | // 64-bit ELF | |
181 | #[cfg(feature = "elf")] | |
182 | [0x7f, b'E', b'L', b'F', 2] => FileInternal::Elf64(elf::ElfFile64::parse(data)?), | |
183 | // 32-bit Mach-O | |
184 | #[cfg(feature = "macho")] | |
185 | [0xfe, 0xed, 0xfa, 0xce, _] | |
186 | | [0xce, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO32(macho::MachOFile32::parse(data)?), | |
187 | // 64-bit Mach-O | |
188 | #[cfg(feature = "macho")] | |
189 | | [0xfe, 0xed, 0xfa, 0xcf, _] | |
190 | | [0xcf, 0xfa, 0xed, 0xfe, _] => FileInternal::MachO64(macho::MachOFile64::parse(data)?), | |
191 | // WASM | |
192 | #[cfg(feature = "wasm")] | |
193 | [0x00, b'a', b's', b'm', _] => FileInternal::Wasm(wasm::WasmFile::parse(data)?), | |
194 | // MS-DOS, assume stub for Windows PE32 or PE32+ | |
195 | #[cfg(feature = "pe")] | |
196 | [b'M', b'Z', _, _, _] => { | |
197 | // `optional_header_magic` doesn't care if it's `PeFile32` and `PeFile64`. | |
198 | match pe::PeFile64::optional_header_magic(data) { | |
199 | Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => { | |
200 | FileInternal::Pe32(pe::PeFile32::parse(data)?) | |
201 | } | |
202 | Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => { | |
203 | FileInternal::Pe64(pe::PeFile64::parse(data)?) | |
204 | } | |
205 | _ => return Err(Error("Unknown MS-DOS file")), | |
206 | } | |
207 | } | |
208 | // TODO: more COFF machines | |
209 | #[cfg(feature = "coff")] | |
210 | // COFF x86 | |
211 | [0x4c, 0x01, _, _, _] | |
212 | // COFF x86-64 | |
213 | | [0x64, 0x86, _, _, _] => FileInternal::Coff(coff::CoffFile::parse(data)?), | |
214 | _ => return Err(Error("Unknown file magic")), | |
215 | }; | |
216 | Ok(File { inner }) | |
217 | } | |
218 | ||
219 | /// Return the file format. | |
220 | pub fn format(&self) -> BinaryFormat { | |
221 | match self.inner { | |
222 | #[cfg(feature = "coff")] | |
223 | FileInternal::Coff(_) => BinaryFormat::Coff, | |
224 | #[cfg(feature = "elf")] | |
225 | FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf, | |
226 | #[cfg(feature = "macho")] | |
227 | FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO, | |
228 | #[cfg(feature = "pe")] | |
229 | FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe, | |
230 | #[cfg(feature = "wasm")] | |
231 | FileInternal::Wasm(_) => BinaryFormat::Wasm, | |
232 | } | |
233 | } | |
234 | } | |
235 | ||
236 | impl<'data> read::private::Sealed for File<'data> {} | |
237 | ||
238 | impl<'data, 'file> Object<'data, 'file> for File<'data> | |
239 | where | |
240 | 'data: 'file, | |
241 | { | |
242 | type Segment = Segment<'data, 'file>; | |
243 | type SegmentIterator = SegmentIterator<'data, 'file>; | |
244 | type Section = Section<'data, 'file>; | |
245 | type SectionIterator = SectionIterator<'data, 'file>; | |
246 | type SymbolIterator = SymbolIterator<'data, 'file>; | |
247 | ||
248 | fn architecture(&self) -> Architecture { | |
249 | with_inner!(self.inner, FileInternal, |x| x.architecture()) | |
250 | } | |
251 | ||
252 | fn is_little_endian(&self) -> bool { | |
253 | with_inner!(self.inner, FileInternal, |x| x.is_little_endian()) | |
254 | } | |
255 | ||
256 | fn is_64(&self) -> bool { | |
257 | with_inner!(self.inner, FileInternal, |x| x.is_64()) | |
258 | } | |
259 | ||
260 | fn segments(&'file self) -> SegmentIterator<'data, 'file> { | |
261 | SegmentIterator { | |
262 | inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x | |
263 | .segments()), | |
264 | } | |
265 | } | |
266 | ||
267 | fn section_by_name(&'file self, section_name: &str) -> Option<Section<'data, 'file>> { | |
268 | map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x | |
269 | .section_by_name(section_name)) | |
270 | .map(|inner| Section { inner }) | |
271 | } | |
272 | ||
273 | fn section_by_index(&'file self, index: SectionIndex) -> Result<Section<'data, 'file>> { | |
274 | map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x | |
275 | .section_by_index(index)) | |
276 | .map(|inner| Section { inner }) | |
277 | } | |
278 | ||
279 | fn sections(&'file self) -> SectionIterator<'data, 'file> { | |
280 | SectionIterator { | |
281 | inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x | |
282 | .sections()), | |
283 | } | |
284 | } | |
285 | ||
286 | fn symbol_by_index(&self, index: SymbolIndex) -> Result<Symbol<'data>> { | |
287 | with_inner!(self.inner, FileInternal, |x| x.symbol_by_index(index)) | |
288 | } | |
289 | ||
290 | fn symbols(&'file self) -> SymbolIterator<'data, 'file> { | |
291 | SymbolIterator { | |
292 | inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x | |
293 | .symbols()), | |
294 | } | |
295 | } | |
296 | ||
297 | fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file> { | |
298 | SymbolIterator { | |
299 | inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| x | |
300 | .dynamic_symbols()), | |
301 | } | |
302 | } | |
303 | ||
304 | fn symbol_map(&self) -> SymbolMap<'data> { | |
305 | with_inner!(self.inner, FileInternal, |x| x.symbol_map()) | |
306 | } | |
307 | ||
308 | fn has_debug_symbols(&self) -> bool { | |
309 | with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols()) | |
310 | } | |
311 | ||
312 | #[inline] | |
313 | fn mach_uuid(&self) -> Result<Option<[u8; 16]>> { | |
314 | with_inner!(self.inner, FileInternal, |x| x.mach_uuid()) | |
315 | } | |
316 | ||
317 | #[inline] | |
318 | fn build_id(&self) -> Result<Option<&'data [u8]>> { | |
319 | with_inner!(self.inner, FileInternal, |x| x.build_id()) | |
320 | } | |
321 | ||
322 | #[inline] | |
323 | fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> { | |
324 | with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink()) | |
325 | } | |
326 | ||
327 | fn entry(&self) -> u64 { | |
328 | with_inner!(self.inner, FileInternal, |x| x.entry()) | |
329 | } | |
330 | ||
331 | fn flags(&self) -> FileFlags { | |
332 | with_inner!(self.inner, FileInternal, |x| x.flags()) | |
333 | } | |
334 | } | |
335 | ||
336 | /// An iterator over the segments of a `File`. | |
337 | #[derive(Debug)] | |
338 | pub struct SegmentIterator<'data, 'file> | |
339 | where | |
340 | 'data: 'file, | |
341 | { | |
342 | inner: SegmentIteratorInternal<'data, 'file>, | |
343 | } | |
344 | ||
345 | #[derive(Debug)] | |
346 | enum SegmentIteratorInternal<'data, 'file> | |
347 | where | |
348 | 'data: 'file, | |
349 | { | |
350 | #[cfg(feature = "coff")] | |
351 | Coff(coff::CoffSegmentIterator<'data, 'file>), | |
352 | #[cfg(feature = "elf")] | |
353 | Elf32(elf::ElfSegmentIterator32<'data, 'file>), | |
354 | #[cfg(feature = "elf")] | |
355 | Elf64(elf::ElfSegmentIterator64<'data, 'file>), | |
356 | #[cfg(feature = "macho")] | |
357 | MachO32(macho::MachOSegmentIterator32<'data, 'file>), | |
358 | #[cfg(feature = "macho")] | |
359 | MachO64(macho::MachOSegmentIterator64<'data, 'file>), | |
360 | #[cfg(feature = "pe")] | |
361 | Pe32(pe::PeSegmentIterator32<'data, 'file>), | |
362 | #[cfg(feature = "pe")] | |
363 | Pe64(pe::PeSegmentIterator64<'data, 'file>), | |
364 | #[cfg(feature = "wasm")] | |
365 | Wasm(wasm::WasmSegmentIterator<'data, 'file>), | |
366 | } | |
367 | ||
368 | impl<'data, 'file> Iterator for SegmentIterator<'data, 'file> { | |
369 | type Item = Segment<'data, 'file>; | |
370 | ||
371 | fn next(&mut self) -> Option<Self::Item> { | |
372 | next_inner!(self.inner, SegmentIteratorInternal, SegmentInternal) | |
373 | .map(|inner| Segment { inner }) | |
374 | } | |
375 | } | |
376 | ||
377 | /// A segment of a `File`. | |
378 | pub struct Segment<'data, 'file> | |
379 | where | |
380 | 'data: 'file, | |
381 | { | |
382 | inner: SegmentInternal<'data, 'file>, | |
383 | } | |
384 | ||
385 | #[derive(Debug)] | |
386 | enum SegmentInternal<'data, 'file> | |
387 | where | |
388 | 'data: 'file, | |
389 | { | |
390 | #[cfg(feature = "coff")] | |
391 | Coff(coff::CoffSegment<'data, 'file>), | |
392 | #[cfg(feature = "elf")] | |
393 | Elf32(elf::ElfSegment32<'data, 'file>), | |
394 | #[cfg(feature = "elf")] | |
395 | Elf64(elf::ElfSegment64<'data, 'file>), | |
396 | #[cfg(feature = "macho")] | |
397 | MachO32(macho::MachOSegment32<'data, 'file>), | |
398 | #[cfg(feature = "macho")] | |
399 | MachO64(macho::MachOSegment64<'data, 'file>), | |
400 | #[cfg(feature = "pe")] | |
401 | Pe32(pe::PeSegment32<'data, 'file>), | |
402 | #[cfg(feature = "pe")] | |
403 | Pe64(pe::PeSegment64<'data, 'file>), | |
404 | #[cfg(feature = "wasm")] | |
405 | Wasm(wasm::WasmSegment<'data, 'file>), | |
406 | } | |
407 | ||
408 | impl<'data, 'file> fmt::Debug for Segment<'data, 'file> { | |
409 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
410 | // It's painful to do much better than this | |
411 | let mut s = f.debug_struct("Segment"); | |
412 | match self.name() { | |
413 | Ok(Some(ref name)) => { | |
414 | s.field("name", name); | |
415 | } | |
416 | Ok(None) => {} | |
417 | Err(_) => { | |
418 | s.field("name", &"<invalid>"); | |
419 | } | |
420 | } | |
421 | s.field("address", &self.address()) | |
422 | .field("size", &self.size()) | |
423 | .finish() | |
424 | } | |
425 | } | |
426 | ||
427 | impl<'data, 'file> read::private::Sealed for Segment<'data, 'file> {} | |
428 | ||
429 | impl<'data, 'file> ObjectSegment<'data> for Segment<'data, 'file> { | |
430 | fn address(&self) -> u64 { | |
431 | with_inner!(self.inner, SegmentInternal, |x| x.address()) | |
432 | } | |
433 | ||
434 | fn size(&self) -> u64 { | |
435 | with_inner!(self.inner, SegmentInternal, |x| x.size()) | |
436 | } | |
437 | ||
438 | fn align(&self) -> u64 { | |
439 | with_inner!(self.inner, SegmentInternal, |x| x.align()) | |
440 | } | |
441 | ||
442 | fn file_range(&self) -> (u64, u64) { | |
443 | with_inner!(self.inner, SegmentInternal, |x| x.file_range()) | |
444 | } | |
445 | ||
446 | fn data(&self) -> Result<&'data [u8]> { | |
447 | with_inner!(self.inner, SegmentInternal, |x| x.data()) | |
448 | } | |
449 | ||
450 | fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { | |
451 | with_inner!(self.inner, SegmentInternal, |x| x.data_range(address, size)) | |
452 | } | |
453 | ||
454 | fn name(&self) -> Result<Option<&str>> { | |
455 | with_inner!(self.inner, SegmentInternal, |x| x.name()) | |
456 | } | |
457 | } | |
458 | ||
459 | /// An iterator of the sections of a `File`. | |
460 | #[derive(Debug)] | |
461 | pub struct SectionIterator<'data, 'file> | |
462 | where | |
463 | 'data: 'file, | |
464 | { | |
465 | inner: SectionIteratorInternal<'data, 'file>, | |
466 | } | |
467 | ||
468 | // we wrap our enums in a struct so that they are kept private. | |
469 | #[derive(Debug)] | |
470 | enum SectionIteratorInternal<'data, 'file> | |
471 | where | |
472 | 'data: 'file, | |
473 | { | |
474 | #[cfg(feature = "coff")] | |
475 | Coff(coff::CoffSectionIterator<'data, 'file>), | |
476 | #[cfg(feature = "elf")] | |
477 | Elf32(elf::ElfSectionIterator32<'data, 'file>), | |
478 | #[cfg(feature = "elf")] | |
479 | Elf64(elf::ElfSectionIterator64<'data, 'file>), | |
480 | #[cfg(feature = "macho")] | |
481 | MachO32(macho::MachOSectionIterator32<'data, 'file>), | |
482 | #[cfg(feature = "macho")] | |
483 | MachO64(macho::MachOSectionIterator64<'data, 'file>), | |
484 | #[cfg(feature = "pe")] | |
485 | Pe32(pe::PeSectionIterator32<'data, 'file>), | |
486 | #[cfg(feature = "pe")] | |
487 | Pe64(pe::PeSectionIterator64<'data, 'file>), | |
488 | #[cfg(feature = "wasm")] | |
489 | Wasm(wasm::WasmSectionIterator<'data, 'file>), | |
490 | } | |
491 | ||
492 | impl<'data, 'file> Iterator for SectionIterator<'data, 'file> { | |
493 | type Item = Section<'data, 'file>; | |
494 | ||
495 | fn next(&mut self) -> Option<Self::Item> { | |
496 | next_inner!(self.inner, SectionIteratorInternal, SectionInternal) | |
497 | .map(|inner| Section { inner }) | |
498 | } | |
499 | } | |
500 | ||
501 | /// A Section of a File | |
502 | pub struct Section<'data, 'file> | |
503 | where | |
504 | 'data: 'file, | |
505 | { | |
506 | inner: SectionInternal<'data, 'file>, | |
507 | } | |
508 | ||
509 | enum SectionInternal<'data, 'file> | |
510 | where | |
511 | 'data: 'file, | |
512 | { | |
513 | #[cfg(feature = "coff")] | |
514 | Coff(coff::CoffSection<'data, 'file>), | |
515 | #[cfg(feature = "elf")] | |
516 | Elf32(elf::ElfSection32<'data, 'file>), | |
517 | #[cfg(feature = "elf")] | |
518 | Elf64(elf::ElfSection64<'data, 'file>), | |
519 | #[cfg(feature = "macho")] | |
520 | MachO32(macho::MachOSection32<'data, 'file>), | |
521 | #[cfg(feature = "macho")] | |
522 | MachO64(macho::MachOSection64<'data, 'file>), | |
523 | #[cfg(feature = "pe")] | |
524 | Pe32(pe::PeSection32<'data, 'file>), | |
525 | #[cfg(feature = "pe")] | |
526 | Pe64(pe::PeSection64<'data, 'file>), | |
527 | #[cfg(feature = "wasm")] | |
528 | Wasm(wasm::WasmSection<'data, 'file>), | |
529 | } | |
530 | ||
531 | impl<'data, 'file> fmt::Debug for Section<'data, 'file> { | |
532 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
533 | // It's painful to do much better than this | |
534 | let mut s = f.debug_struct("Section"); | |
535 | match self.segment_name() { | |
536 | Ok(Some(ref name)) => { | |
537 | s.field("segment", name); | |
538 | } | |
539 | Ok(None) => {} | |
540 | Err(_) => { | |
541 | s.field("segment", &"<invalid>"); | |
542 | } | |
543 | } | |
544 | s.field("name", &self.name().unwrap_or("<invalid>")) | |
545 | .field("address", &self.address()) | |
546 | .field("size", &self.size()) | |
547 | .field("kind", &self.kind()) | |
548 | .finish() | |
549 | } | |
550 | } | |
551 | ||
552 | impl<'data, 'file> read::private::Sealed for Section<'data, 'file> {} | |
553 | ||
554 | impl<'data, 'file> ObjectSection<'data> for Section<'data, 'file> { | |
555 | type RelocationIterator = RelocationIterator<'data, 'file>; | |
556 | ||
557 | fn index(&self) -> SectionIndex { | |
558 | with_inner!(self.inner, SectionInternal, |x| x.index()) | |
559 | } | |
560 | ||
561 | fn address(&self) -> u64 { | |
562 | with_inner!(self.inner, SectionInternal, |x| x.address()) | |
563 | } | |
564 | ||
565 | fn size(&self) -> u64 { | |
566 | with_inner!(self.inner, SectionInternal, |x| x.size()) | |
567 | } | |
568 | ||
569 | fn align(&self) -> u64 { | |
570 | with_inner!(self.inner, SectionInternal, |x| x.align()) | |
571 | } | |
572 | ||
573 | fn file_range(&self) -> Option<(u64, u64)> { | |
574 | with_inner!(self.inner, SectionInternal, |x| x.file_range()) | |
575 | } | |
576 | ||
577 | fn data(&self) -> Result<&'data [u8]> { | |
578 | with_inner!(self.inner, SectionInternal, |x| x.data()) | |
579 | } | |
580 | ||
581 | fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> { | |
582 | with_inner!(self.inner, SectionInternal, |x| x.data_range(address, size)) | |
583 | } | |
584 | ||
585 | fn compressed_data(&self) -> Result<CompressedData<'data>> { | |
586 | with_inner!(self.inner, SectionInternal, |x| x.compressed_data()) | |
587 | } | |
588 | ||
589 | fn name(&self) -> Result<&str> { | |
590 | with_inner!(self.inner, SectionInternal, |x| x.name()) | |
591 | } | |
592 | ||
593 | fn segment_name(&self) -> Result<Option<&str>> { | |
594 | with_inner!(self.inner, SectionInternal, |x| x.segment_name()) | |
595 | } | |
596 | ||
597 | fn kind(&self) -> SectionKind { | |
598 | with_inner!(self.inner, SectionInternal, |x| x.kind()) | |
599 | } | |
600 | ||
601 | fn relocations(&self) -> RelocationIterator<'data, 'file> { | |
602 | RelocationIterator { | |
603 | inner: map_inner!( | |
604 | self.inner, | |
605 | SectionInternal, | |
606 | RelocationIteratorInternal, | |
607 | |x| x.relocations() | |
608 | ), | |
609 | } | |
610 | } | |
611 | ||
612 | fn flags(&self) -> SectionFlags { | |
613 | with_inner!(self.inner, SectionInternal, |x| x.flags()) | |
614 | } | |
615 | } | |
616 | ||
617 | /// An iterator over symbol table entries. | |
618 | #[derive(Debug)] | |
619 | pub struct SymbolIterator<'data, 'file> | |
620 | where | |
621 | 'data: 'file, | |
622 | { | |
623 | inner: SymbolIteratorInternal<'data, 'file>, | |
624 | } | |
625 | ||
626 | #[derive(Debug)] | |
627 | enum SymbolIteratorInternal<'data, 'file> | |
628 | where | |
629 | 'data: 'file, | |
630 | { | |
631 | #[cfg(feature = "coff")] | |
632 | Coff(coff::CoffSymbolIterator<'data, 'file>), | |
633 | #[cfg(feature = "elf")] | |
634 | Elf32(elf::ElfSymbolIterator32<'data, 'file>), | |
635 | #[cfg(feature = "elf")] | |
636 | Elf64(elf::ElfSymbolIterator64<'data, 'file>), | |
637 | #[cfg(feature = "macho")] | |
638 | MachO32(macho::MachOSymbolIterator32<'data, 'file>), | |
639 | #[cfg(feature = "macho")] | |
640 | MachO64(macho::MachOSymbolIterator64<'data, 'file>), | |
641 | #[cfg(feature = "pe")] | |
642 | Pe32(coff::CoffSymbolIterator<'data, 'file>), | |
643 | #[cfg(feature = "pe")] | |
644 | Pe64(coff::CoffSymbolIterator<'data, 'file>), | |
645 | #[cfg(feature = "wasm")] | |
646 | Wasm(wasm::WasmSymbolIterator<'data, 'file>), | |
647 | } | |
648 | ||
649 | impl<'data, 'file> Iterator for SymbolIterator<'data, 'file> { | |
650 | type Item = (SymbolIndex, Symbol<'data>); | |
651 | ||
652 | fn next(&mut self) -> Option<Self::Item> { | |
653 | with_inner_mut!(self.inner, SymbolIteratorInternal, |x| x.next()) | |
654 | } | |
655 | } | |
656 | ||
657 | /// An iterator over relocation entries | |
658 | #[derive(Debug)] | |
659 | pub struct RelocationIterator<'data, 'file> | |
660 | where | |
661 | 'data: 'file, | |
662 | { | |
663 | inner: RelocationIteratorInternal<'data, 'file>, | |
664 | } | |
665 | ||
666 | #[derive(Debug)] | |
667 | enum RelocationIteratorInternal<'data, 'file> | |
668 | where | |
669 | 'data: 'file, | |
670 | { | |
671 | #[cfg(feature = "coff")] | |
672 | Coff(coff::CoffRelocationIterator<'data, 'file>), | |
673 | #[cfg(feature = "elf")] | |
674 | Elf32(elf::ElfRelocationIterator32<'data, 'file>), | |
675 | #[cfg(feature = "elf")] | |
676 | Elf64(elf::ElfRelocationIterator64<'data, 'file>), | |
677 | #[cfg(feature = "macho")] | |
678 | MachO32(macho::MachORelocationIterator32<'data, 'file>), | |
679 | #[cfg(feature = "macho")] | |
680 | MachO64(macho::MachORelocationIterator64<'data, 'file>), | |
681 | #[cfg(feature = "pe")] | |
682 | Pe32(pe::PeRelocationIterator<'data, 'file>), | |
683 | #[cfg(feature = "pe")] | |
684 | Pe64(pe::PeRelocationIterator<'data, 'file>), | |
685 | #[cfg(feature = "wasm")] | |
686 | Wasm(wasm::WasmRelocationIterator<'data, 'file>), | |
687 | } | |
688 | ||
689 | impl<'data, 'file> Iterator for RelocationIterator<'data, 'file> { | |
690 | type Item = (u64, Relocation); | |
691 | ||
692 | fn next(&mut self) -> Option<Self::Item> { | |
693 | with_inner_mut!(self.inner, RelocationIteratorInternal, |x| x.next()) | |
694 | } | |
695 | } |