object/read/traits.rs
1use alloc::borrow::Cow;
2use alloc::vec::Vec;
3
4use crate::endian::Endianness;
5use crate::read::{
6 self, Architecture, CodeView, ComdatKind, CompressedData, CompressedFileRange, Export,
7 FileFlags, Import, ObjectKind, ObjectMap, Permissions, Relocation, RelocationMap, Result,
8 SectionFlags, SectionIndex, SectionKind, SegmentFlags, SubArchitecture, SymbolFlags,
9 SymbolIndex, SymbolKind, SymbolMap, SymbolMapBuilder, SymbolMapName, SymbolScope,
10 SymbolSection,
11};
12
13/// An object file.
14///
15/// This is the primary trait for the unified read API.
16pub trait Object<'data>: read::private::Sealed {
17 /// A loadable segment in the object file.
18 type Segment<'file>: ObjectSegment<'data>
19 where
20 Self: 'file,
21 'data: 'file;
22
23 /// An iterator for the loadable segments in the object file.
24 type SegmentIterator<'file>: Iterator<Item = Self::Segment<'file>>
25 where
26 Self: 'file,
27 'data: 'file;
28
29 /// A section in the object file.
30 type Section<'file>: ObjectSection<'data>
31 where
32 Self: 'file,
33 'data: 'file;
34
35 /// An iterator for the sections in the object file.
36 type SectionIterator<'file>: Iterator<Item = Self::Section<'file>>
37 where
38 Self: 'file,
39 'data: 'file;
40
41 /// A COMDAT section group in the object file.
42 type Comdat<'file>: ObjectComdat<'data>
43 where
44 Self: 'file,
45 'data: 'file;
46
47 /// An iterator for the COMDAT section groups in the object file.
48 type ComdatIterator<'file>: Iterator<Item = Self::Comdat<'file>>
49 where
50 Self: 'file,
51 'data: 'file;
52
53 /// A symbol in the object file.
54 type Symbol<'file>: ObjectSymbol<'data>
55 where
56 Self: 'file,
57 'data: 'file;
58
59 /// An iterator for symbols in the object file.
60 type SymbolIterator<'file>: Iterator<Item = Self::Symbol<'file>>
61 where
62 Self: 'file,
63 'data: 'file;
64
65 /// A symbol table in the object file.
66 type SymbolTable<'file>: ObjectSymbolTable<
67 'data,
68 Symbol = Self::Symbol<'file>,
69 SymbolIterator = Self::SymbolIterator<'file>,
70 >
71 where
72 Self: 'file,
73 'data: 'file;
74
75 /// An iterator for the dynamic relocations in the file.
76 ///
77 /// The first field in the item tuple is the address
78 /// that the relocation applies to.
79 type DynamicRelocationIterator<'file>: Iterator<Item = (u64, Relocation)>
80 where
81 Self: 'file,
82 'data: 'file;
83
84 /// Get the architecture type of the file.
85 fn architecture(&self) -> Architecture;
86
87 /// Get the sub-architecture type of the file if known.
88 ///
89 /// A value of `None` has a range of meanings: the file supports all
90 /// sub-architectures, the file does not explicitly specify a
91 /// sub-architecture, or the sub-architecture is currently unrecognized.
92 fn sub_architecture(&self) -> Option<SubArchitecture> {
93 None
94 }
95
96 /// Get the endianness of the file.
97 #[inline]
98 fn endianness(&self) -> Endianness {
99 if self.is_little_endian() {
100 Endianness::Little
101 } else {
102 Endianness::Big
103 }
104 }
105
106 /// Return true if the file is little endian, false if it is big endian.
107 fn is_little_endian(&self) -> bool;
108
109 /// Return true if the file can contain 64-bit addresses.
110 fn is_64(&self) -> bool;
111
112 /// Return the kind of this object.
113 fn kind(&self) -> ObjectKind;
114
115 /// Get an iterator for the loadable segments in the file.
116 ///
117 /// For ELF, this is program headers with type [`PT_LOAD`](crate::elf::PT_LOAD).
118 /// For Mach-O, this is load commands with type [`LC_SEGMENT`](crate::macho::LC_SEGMENT)
119 /// or [`LC_SEGMENT_64`](crate::macho::LC_SEGMENT_64).
120 /// For PE, this is all sections.
121 fn segments(&self) -> Self::SegmentIterator<'_>;
122
123 /// Get the section named `section_name`, if such a section exists.
124 ///
125 /// If `section_name` starts with a '.' then it is treated as a system
126 /// section name, and is compared using the conventions specific to the
127 /// object file format. This includes:
128 /// - if ".debug_str_offsets" is requested for a Mach-O object file, then
129 /// the actual section name that is searched for is "__debug_str_offs".
130 /// - if ".debug_info" is requested for an ELF object file, then
131 /// ".zdebug_info" may be returned (and similarly for other debug
132 /// sections). Similarly, if ".debug_info" is requested for a Mach-O
133 /// object file, then "__zdebug_info" may be returned.
134 ///
135 /// For some object files, multiple segments may contain sections with the
136 /// same name. In this case, the first matching section will be used.
137 ///
138 /// This method skips over sections with invalid names.
139 fn section_by_name(&self, section_name: &str) -> Option<Self::Section<'_>> {
140 self.section_by_name_bytes(section_name.as_bytes())
141 }
142
143 /// Like [`Self::section_by_name`], but allows names that are not UTF-8.
144 fn section_by_name_bytes<'file>(
145 &'file self,
146 section_name: &[u8],
147 ) -> Option<Self::Section<'file>>;
148
149 /// Get the section at the given index.
150 ///
151 /// The meaning of the index depends on the object file.
152 ///
153 /// For some object files, this requires iterating through all sections.
154 ///
155 /// Returns an error if the index is invalid.
156 fn section_by_index(&self, index: SectionIndex) -> Result<Self::Section<'_>>;
157
158 /// Get an iterator for the sections in the file.
159 fn sections(&self) -> Self::SectionIterator<'_>;
160
161 /// Get an iterator for the COMDAT section groups in the file.
162 fn comdats(&self) -> Self::ComdatIterator<'_>;
163
164 /// Get the debugging symbol table, if any.
165 fn symbol_table(&self) -> Option<Self::SymbolTable<'_>>;
166
167 /// Get the debugging symbol at the given index.
168 ///
169 /// The meaning of the index depends on the object file.
170 ///
171 /// Returns an error if the index is invalid.
172 fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol<'_>>;
173
174 /// Get an iterator for the debugging symbols in the file.
175 ///
176 /// This may skip over symbols that are malformed or unsupported.
177 ///
178 /// For Mach-O files, this does not include STAB entries.
179 fn symbols(&self) -> Self::SymbolIterator<'_>;
180
181 /// Get the symbol named `symbol_name`, if the symbol exists.
182 fn symbol_by_name<'file>(&'file self, symbol_name: &str) -> Option<Self::Symbol<'file>> {
183 self.symbol_by_name_bytes(symbol_name.as_bytes())
184 }
185
186 /// Like [`Self::symbol_by_name`], but allows names that are not UTF-8.
187 fn symbol_by_name_bytes<'file>(&'file self, symbol_name: &[u8]) -> Option<Self::Symbol<'file>> {
188 self.symbols()
189 .find(|sym| sym.name_bytes() == Ok(symbol_name))
190 }
191
192 /// Get the dynamic linking symbol table, if any.
193 ///
194 /// Only ELF has a separate dynamic linking symbol table.
195 /// Consider using [`Self::exports`] or [`Self::imports`] instead.
196 fn dynamic_symbol_table(&self) -> Option<Self::SymbolTable<'_>>;
197
198 /// Get an iterator for the dynamic linking symbols in the file.
199 ///
200 /// This may skip over symbols that are malformed or unsupported.
201 ///
202 /// Only ELF has dynamic linking symbols.
203 /// Other file formats will return an empty iterator.
204 /// Consider using [`Self::exports`] or [`Self::imports`] instead.
205 fn dynamic_symbols(&self) -> Self::SymbolIterator<'_>;
206
207 /// Get the dynamic relocations for this file.
208 ///
209 /// Symbol indices in these relocations refer to the dynamic symbol table.
210 ///
211 /// Only ELF has dynamic relocations.
212 fn dynamic_relocations(&self) -> Option<Self::DynamicRelocationIterator<'_>>;
213
214 /// Construct a map from addresses to symbol names.
215 ///
216 /// See [`SymbolMapBuilder::build`] for details of the map contents.
217 fn symbol_map(&self) -> SymbolMap<SymbolMapName<'data>> {
218 SymbolMapBuilder::new().build(self)
219 }
220
221 /// Construct a map from addresses to symbol names and object file names.
222 ///
223 /// This is derived from Mach-O STAB entries.
224 fn object_map(&self) -> ObjectMap<'data> {
225 ObjectMap::default()
226 }
227
228 /// Get the imported symbols.
229 fn imports(&self) -> Result<Vec<Import<'data>>>;
230
231 /// Get the exported symbols that expose both a name and an address.
232 ///
233 /// Some file formats may provide other kinds of symbols that can be retrieved using
234 /// the low level API.
235 fn exports(&self) -> Result<Vec<Export<'data>>>;
236
237 /// Return true if the file contains DWARF debug information sections, false if not.
238 fn has_debug_symbols(&self) -> bool;
239
240 /// The UUID from a Mach-O [`LC_UUID`](crate::macho::LC_UUID) load command.
241 #[inline]
242 fn mach_uuid(&self) -> Result<Option<[u8; 16]>> {
243 Ok(None)
244 }
245
246 /// The build ID from an ELF [`NT_GNU_BUILD_ID`](crate::elf::NT_GNU_BUILD_ID) note.
247 #[inline]
248 fn build_id(&self) -> Result<Option<&'data [u8]>> {
249 Ok(None)
250 }
251
252 /// The filename and CRC from a `.gnu_debuglink` section.
253 #[inline]
254 fn gnu_debuglink(&self) -> Result<Option<(&'data [u8], u32)>> {
255 Ok(None)
256 }
257
258 /// The filename and build ID from a `.gnu_debugaltlink` section.
259 #[inline]
260 fn gnu_debugaltlink(&self) -> Result<Option<(&'data [u8], &'data [u8])>> {
261 Ok(None)
262 }
263
264 /// The filename and GUID from the PE CodeView section.
265 #[inline]
266 fn pdb_info(&self) -> Result<Option<CodeView<'_>>> {
267 Ok(None)
268 }
269
270 /// Get the base address used for relative virtual addresses.
271 ///
272 /// Currently this is only non-zero for PE.
273 fn relative_address_base(&self) -> u64;
274
275 /// Get the virtual address of the entry point of the binary.
276 fn entry(&self) -> u64;
277
278 /// File flags that are specific to each file format.
279 fn flags(&self) -> FileFlags;
280}
281
282/// A loadable segment in an [`Object`].
283///
284/// This trait is part of the unified read API.
285pub trait ObjectSegment<'data>: read::private::Sealed {
286 /// Returns the virtual address of the segment.
287 fn address(&self) -> u64;
288
289 /// Returns the size of the segment in memory.
290 fn size(&self) -> u64;
291
292 /// Returns the alignment of the segment in memory.
293 fn align(&self) -> u64;
294
295 /// Returns the offset and size of the segment in the file.
296 fn file_range(&self) -> (u64, u64);
297
298 /// Returns a reference to the file contents of the segment.
299 ///
300 /// The length of this data may be different from the size of the
301 /// segment in memory.
302 fn data(&self) -> Result<&'data [u8]>;
303
304 /// Return the segment data in the given range.
305 ///
306 /// Returns `Ok(None)` if the segment does not contain the given range.
307 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>;
308
309 /// Returns the name of the segment.
310 fn name_bytes(&self) -> Result<Option<&[u8]>>;
311
312 /// Returns the name of the segment.
313 ///
314 /// Returns an error if the name is not UTF-8.
315 fn name(&self) -> Result<Option<&str>>;
316
317 /// Return the flags of segment.
318 fn flags(&self) -> SegmentFlags;
319
320 /// Return the permissions of the segment.
321 fn permissions(&self) -> Permissions;
322}
323
324/// A section in an [`Object`].
325///
326/// This trait is part of the unified read API.
327pub trait ObjectSection<'data>: read::private::Sealed {
328 /// An iterator for the relocations for a section.
329 ///
330 /// The first field in the item tuple is the section offset
331 /// that the relocation applies to.
332 type RelocationIterator: Iterator<Item = (u64, Relocation)>;
333
334 /// Returns the section index.
335 fn index(&self) -> SectionIndex;
336
337 /// Returns the address of the section.
338 fn address(&self) -> u64;
339
340 /// Returns the size of the section in memory.
341 fn size(&self) -> u64;
342
343 /// Returns the alignment of the section in memory.
344 fn align(&self) -> u64;
345
346 /// Returns offset and size of on-disk segment (if any).
347 fn file_range(&self) -> Option<(u64, u64)>;
348
349 /// Returns the raw contents of the section.
350 ///
351 /// The length of this data may be different from the size of the
352 /// section in memory.
353 ///
354 /// This does not do any decompression.
355 fn data(&self) -> Result<&'data [u8]>;
356
357 /// Return the raw contents of the section data in the given range.
358 ///
359 /// This does not do any decompression.
360 ///
361 /// Returns `Ok(None)` if the section does not contain the given range.
362 fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>>;
363
364 /// Returns the potentially compressed file range of the section,
365 /// along with information about the compression.
366 fn compressed_file_range(&self) -> Result<CompressedFileRange>;
367
368 /// Returns the potentially compressed contents of the section,
369 /// along with information about the compression.
370 fn compressed_data(&self) -> Result<CompressedData<'data>>;
371
372 /// Returns the uncompressed contents of the section.
373 ///
374 /// The length of this data may be different from the size of the
375 /// section in memory.
376 ///
377 /// If no compression is detected, then returns the data unchanged.
378 /// Returns `Err` if decompression fails.
379 fn uncompressed_data(&self) -> Result<Cow<'data, [u8]>> {
380 self.compressed_data()?.decompress()
381 }
382
383 /// Returns the name of the section.
384 fn name_bytes(&self) -> Result<&'data [u8]>;
385
386 /// Returns the name of the section.
387 ///
388 /// Returns an error if the name is not UTF-8.
389 fn name(&self) -> Result<&'data str>;
390
391 /// Returns the name of the segment for this section.
392 fn segment_name_bytes(&self) -> Result<Option<&[u8]>>;
393
394 /// Returns the name of the segment for this section.
395 ///
396 /// Returns an error if the name is not UTF-8.
397 fn segment_name(&self) -> Result<Option<&str>>;
398
399 /// Return the kind of this section.
400 fn kind(&self) -> SectionKind;
401
402 /// Get the relocations for this section.
403 fn relocations(&self) -> Self::RelocationIterator;
404
405 /// Construct a relocation map for this section.
406 fn relocation_map(&self) -> Result<RelocationMap>;
407
408 /// Section flags that are specific to each file format.
409 fn flags(&self) -> SectionFlags;
410}
411
412/// A COMDAT section group in an [`Object`].
413///
414/// This trait is part of the unified read API.
415pub trait ObjectComdat<'data>: read::private::Sealed {
416 /// An iterator for the sections in the section group.
417 type SectionIterator: Iterator<Item = SectionIndex>;
418
419 /// Returns the COMDAT selection kind.
420 fn kind(&self) -> ComdatKind;
421
422 /// Returns the index of the symbol used for the name of COMDAT section group.
423 fn symbol(&self) -> SymbolIndex;
424
425 /// Returns the name of the COMDAT section group.
426 fn name_bytes(&self) -> Result<&'data [u8]>;
427
428 /// Returns the name of the COMDAT section group.
429 ///
430 /// Returns an error if the name is not UTF-8.
431 fn name(&self) -> Result<&'data str>;
432
433 /// Get the sections in this section group.
434 fn sections(&self) -> Self::SectionIterator;
435}
436
437/// A symbol table in an [`Object`].
438///
439/// This trait is part of the unified read API.
440pub trait ObjectSymbolTable<'data>: read::private::Sealed {
441 /// A symbol table entry.
442 type Symbol: ObjectSymbol<'data>;
443
444 /// An iterator for the symbols in a symbol table.
445 type SymbolIterator: Iterator<Item = Self::Symbol>;
446
447 /// Get an iterator for the symbols in the table.
448 ///
449 /// This may skip over symbols that are malformed or unsupported.
450 fn symbols(&self) -> Self::SymbolIterator;
451
452 /// Get the symbol at the given index.
453 ///
454 /// The meaning of the index depends on the object file.
455 ///
456 /// Returns an error if the index is invalid.
457 fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol>;
458}
459
460/// A symbol table entry in an [`Object`].
461///
462/// This trait is part of the unified read API.
463pub trait ObjectSymbol<'data>: read::private::Sealed {
464 /// The index of the symbol.
465 fn index(&self) -> SymbolIndex;
466
467 /// The name of the symbol.
468 fn name_bytes(&self) -> Result<&'data [u8]>;
469
470 /// The name of the symbol.
471 ///
472 /// Returns an error if the name is not UTF-8.
473 fn name(&self) -> Result<&'data str>;
474
475 /// The address of the symbol. May be zero if the address is unknown.
476 fn address(&self) -> u64;
477
478 /// The size of the symbol. May be zero if the size is unknown.
479 fn size(&self) -> u64;
480
481 /// Return the kind of this symbol.
482 fn kind(&self) -> SymbolKind;
483
484 /// Returns the section where the symbol is defined.
485 fn section(&self) -> SymbolSection;
486
487 /// Returns the section index for the section containing this symbol.
488 ///
489 /// May return `None` if the symbol is not defined in a section.
490 fn section_index(&self) -> Option<SectionIndex> {
491 self.section().index()
492 }
493
494 /// Return true if the symbol is undefined.
495 fn is_undefined(&self) -> bool;
496
497 /// Return true if the symbol is a definition of a function or data object
498 /// that has a known address.
499 ///
500 /// This is primarily used to implement [`Object::symbol_map`].
501 fn is_definition(&self) -> bool;
502
503 /// Return true if the symbol is common data.
504 ///
505 /// Note: does not check for [`SymbolSection::Section`] with [`SectionKind::Common`].
506 fn is_common(&self) -> bool;
507
508 /// Return true if the symbol is weak.
509 fn is_weak(&self) -> bool;
510
511 /// Returns the symbol scope.
512 fn scope(&self) -> SymbolScope;
513
514 /// Return true if the symbol visible outside of the compilation unit.
515 ///
516 /// This treats [`SymbolScope::Unknown`] as global.
517 fn is_global(&self) -> bool;
518
519 /// Return true if the symbol is only visible within the compilation unit.
520 fn is_local(&self) -> bool;
521
522 /// Symbol flags that are specific to each file format.
523 fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex>;
524}
525
526/// An iterator for files that don't have dynamic relocations.
527#[derive(Debug)]
528pub struct NoDynamicRelocationIterator;
529
530impl Iterator for NoDynamicRelocationIterator {
531 type Item = (u64, Relocation);
532
533 #[inline]
534 fn next(&mut self) -> Option<Self::Item> {
535 None
536 }
537}