1 use alloc
::borrow
::Cow
;
5 self, Architecture
, CodeView
, ComdatKind
, CompressedData
, CompressedFileRange
, Export
,
6 FileFlags
, Import
, ObjectMap
, Relocation
, Result
, SectionFlags
, SectionIndex
, SectionKind
,
7 SymbolFlags
, SymbolIndex
, SymbolKind
, SymbolMap
, SymbolMapName
, SymbolScope
, SymbolSection
,
12 pub trait Object
<'data
: 'file
, 'file
>: read
::private
::Sealed
{
13 /// A segment in the object file.
14 type Segment
: ObjectSegment
<'data
>;
16 /// An iterator over the segments in the object file.
17 type SegmentIterator
: Iterator
<Item
= Self::Segment
>;
19 /// A section in the object file.
20 type Section
: ObjectSection
<'data
>;
22 /// An iterator over the sections in the object file.
23 type SectionIterator
: Iterator
<Item
= Self::Section
>;
25 /// A COMDAT section group in the object file.
26 type Comdat
: ObjectComdat
<'data
>;
28 /// An iterator over the COMDAT section groups in the object file.
29 type ComdatIterator
: Iterator
<Item
= Self::Comdat
>;
31 /// A symbol in the object file.
32 type Symbol
: ObjectSymbol
<'data
>;
34 /// An iterator over symbols in the object file.
35 type SymbolIterator
: Iterator
<Item
= Self::Symbol
>;
37 /// A symbol table in the object file.
38 type SymbolTable
: ObjectSymbolTable
<
40 Symbol
= Self::Symbol
,
41 SymbolIterator
= Self::SymbolIterator
,
44 /// An iterator over dynamic relocations in the file.
46 /// The first field in the item tuple is the address
47 /// that the relocation applies to.
48 type DynamicRelocationIterator
: Iterator
<Item
= (u64, Relocation
)>;
50 /// Get the architecture type of the file.
51 fn architecture(&self) -> Architecture
;
53 /// Get the endianness of the file.
55 fn endianness(&self) -> Endianness
{
56 if self.is_little_endian() {
63 /// Return true if the file is little endian, false if it is big endian.
64 fn is_little_endian(&self) -> bool
;
66 /// Return true if the file can contain 64-bit addresses.
67 fn is_64(&self) -> bool
;
69 /// Get an iterator over the segments in the file.
70 fn segments(&'file
self) -> Self::SegmentIterator
;
72 /// Get the section named `section_name`, if such a section exists.
74 /// If `section_name` starts with a '.' then it is treated as a system section name,
75 /// and is compared using the conventions specific to the object file format. This
77 /// - if ".debug_str_offsets" is requested for a Mach-O object file, then the actual
78 /// section name that is searched for is "__debug_str_offs".
79 /// - if ".debug_info" is requested for an ELF object file, then
80 /// ".zdebug_info" may be returned (and similarly for other debug sections).
82 /// For some object files, multiple segments may contain sections with the same
83 /// name. In this case, the first matching section will be used.
85 /// This method skips over sections with invalid names.
86 fn section_by_name(&'file
self, section_name
: &str) -> Option
<Self::Section
>;
88 /// Get the section at the given index.
90 /// The meaning of the index depends on the object file.
92 /// For some object files, this requires iterating through all sections.
94 /// Returns an error if the index is invalid.
95 fn section_by_index(&'file
self, index
: SectionIndex
) -> Result
<Self::Section
>;
97 /// Get an iterator over the sections in the file.
98 fn sections(&'file
self) -> Self::SectionIterator
;
100 /// Get an iterator over the COMDAT section groups in the file.
101 fn comdats(&'file
self) -> Self::ComdatIterator
;
103 /// Get the symbol table, if any.
104 fn symbol_table(&'file
self) -> Option
<Self::SymbolTable
>;
106 /// Get the debugging symbol at the given index.
108 /// The meaning of the index depends on the object file.
110 /// Returns an error if the index is invalid.
111 fn symbol_by_index(&'file
self, index
: SymbolIndex
) -> Result
<Self::Symbol
>;
113 /// Get an iterator over the debugging symbols in the file.
115 /// This may skip over symbols that are malformed or unsupported.
117 /// For Mach-O files, this does not include STAB entries.
118 fn symbols(&'file
self) -> Self::SymbolIterator
;
120 /// Get the dynamic linking symbol table, if any.
122 /// Only ELF has a separate dynamic linking symbol table.
123 fn dynamic_symbol_table(&'file
self) -> Option
<Self::SymbolTable
>;
125 /// Get an iterator over the dynamic linking symbols in the file.
127 /// This may skip over symbols that are malformed or unsupported.
129 /// Only ELF has separate dynamic linking symbols.
130 /// Other file formats will return an empty iterator.
131 fn dynamic_symbols(&'file
self) -> Self::SymbolIterator
;
133 /// Get the dynamic relocations for this file.
135 /// Symbol indices in these relocations refer to the dynamic symbol table.
137 /// Only ELF has dynamic relocations.
138 fn dynamic_relocations(&'file
self) -> Option
<Self::DynamicRelocationIterator
>;
140 /// Construct a map from addresses to symbol names.
142 /// The map will only contain defined text and data symbols.
143 /// The dynamic symbol table will only be used if there are no debugging symbols.
144 fn symbol_map(&'file
self) -> SymbolMap
<SymbolMapName
<'data
>> {
145 let mut symbols
= Vec
::new();
146 if let Some(table
) = self.symbol_table().or_else(|| self.dynamic_symbol_table()) {
147 for symbol
in table
.symbols() {
148 if !symbol
.is_definition() {
151 if let Ok(name
) = symbol
.name() {
152 symbols
.push(SymbolMapName
::new(symbol
.address(), name
));
156 SymbolMap
::new(symbols
)
159 /// Construct a map from addresses to symbol names and object file names.
161 /// This is derived from Mach-O STAB entries.
162 fn object_map(&'file
self) -> ObjectMap
<'data
> {
166 /// Get the imported symbols.
167 fn imports(&self) -> Result
<Vec
<Import
<'data
>>>;
169 /// Get the exported symbols.
170 fn exports(&self) -> Result
<Vec
<Export
<'data
>>>;
172 /// Return true if the file contains debug information sections, false if not.
173 fn has_debug_symbols(&self) -> bool
;
175 /// The UUID from a Mach-O `LC_UUID` load command.
177 fn mach_uuid(&self) -> Result
<Option
<[u8; 16]>> {
181 /// The build ID from an ELF `NT_GNU_BUILD_ID` note.
183 fn build_id(&self) -> Result
<Option
<&'data
[u8]>> {
187 /// The filename and CRC from a `.gnu_debuglink` section.
189 fn gnu_debuglink(&self) -> Result
<Option
<(&'data
[u8], u32)>> {
193 /// The filename and build ID from a `.gnu_debugaltlink` section.
195 fn gnu_debugaltlink(&self) -> Result
<Option
<(&'data
[u8], &'data
[u8])>> {
199 /// The filename and GUID from the PE CodeView section
201 fn pdb_info(&self) -> Result
<Option
<CodeView
>> {
205 /// Get the base address used for relative virtual addresses.
207 /// Currently this is only non-zero for PE.
208 fn relative_address_base(&'file
self) -> u64;
210 /// Get the virtual address of the entry point of the binary
211 fn entry(&'file
self) -> u64;
213 /// File flags that are specific to each file format.
214 fn flags(&self) -> FileFlags
;
217 /// A loadable segment defined in an object file.
219 /// For ELF, this is a program header with type `PT_LOAD`.
220 /// For Mach-O, this is a load command with type `LC_SEGMENT` or `LC_SEGMENT_64`.
221 pub trait ObjectSegment
<'data
>: read
::private
::Sealed
{
222 /// Returns the virtual address of the segment.
223 fn address(&self) -> u64;
225 /// Returns the size of the segment in memory.
226 fn size(&self) -> u64;
228 /// Returns the alignment of the segment in memory.
229 fn align(&self) -> u64;
231 /// Returns the offset and size of the segment in the file.
232 fn file_range(&self) -> (u64, u64);
234 /// Returns a reference to the file contents of the segment.
236 /// The length of this data may be different from the size of the
237 /// segment in memory.
238 fn data(&self) -> Result
<&'data
[u8]>;
240 /// Return the segment data in the given range.
242 /// Returns `Ok(None)` if the segment does not contain the given range.
243 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>>;
245 /// Returns the name of the segment.
246 fn name(&self) -> Result
<Option
<&str>>;
249 /// A section defined in an object file.
250 pub trait ObjectSection
<'data
>: read
::private
::Sealed
{
251 /// An iterator over the relocations for a section.
253 /// The first field in the item tuple is the section offset
254 /// that the relocation applies to.
255 type RelocationIterator
: Iterator
<Item
= (u64, Relocation
)>;
257 /// Returns the section index.
258 fn index(&self) -> SectionIndex
;
260 /// Returns the address of the section.
261 fn address(&self) -> u64;
263 /// Returns the size of the section in memory.
264 fn size(&self) -> u64;
266 /// Returns the alignment of the section in memory.
267 fn align(&self) -> u64;
269 /// Returns offset and size of on-disk segment (if any).
270 fn file_range(&self) -> Option
<(u64, u64)>;
272 /// Returns the raw contents of the section.
274 /// The length of this data may be different from the size of the
275 /// section in memory.
277 /// This does not do any decompression.
278 fn data(&self) -> Result
<&'data
[u8]>;
280 /// Return the raw contents of the section data in the given range.
282 /// This does not do any decompression.
284 /// Returns `Ok(None)` if the section does not contain the given range.
285 fn data_range(&self, address
: u64, size
: u64) -> Result
<Option
<&'data
[u8]>>;
287 /// Returns the potentially compressed file range of the section,
288 /// along with information about the compression.
289 fn compressed_file_range(&self) -> Result
<CompressedFileRange
>;
291 /// Returns the potentially compressed contents of the section,
292 /// along with information about the compression.
293 fn compressed_data(&self) -> Result
<CompressedData
<'data
>>;
295 /// Returns the uncompressed contents of the section.
297 /// The length of this data may be different from the size of the
298 /// section in memory.
300 /// If no compression is detected, then returns the data unchanged.
301 /// Returns `Err` if decompression fails.
302 fn uncompressed_data(&self) -> Result
<Cow
<'data
, [u8]>> {
303 self.compressed_data()?
.decompress()
306 /// Returns the name of the section.
307 fn name(&self) -> Result
<&str>;
309 /// Returns the name of the segment for this section.
310 fn segment_name(&self) -> Result
<Option
<&str>>;
312 /// Return the kind of this section.
313 fn kind(&self) -> SectionKind
;
315 /// Get the relocations for this section.
316 fn relocations(&self) -> Self::RelocationIterator
;
318 /// Section flags that are specific to each file format.
319 fn flags(&self) -> SectionFlags
;
322 /// A COMDAT section group defined in an object file.
323 pub trait ObjectComdat
<'data
>: read
::private
::Sealed
{
324 /// An iterator over the sections in the object file.
325 type SectionIterator
: Iterator
<Item
= SectionIndex
>;
327 /// Returns the COMDAT selection kind.
328 fn kind(&self) -> ComdatKind
;
330 /// Returns the index of the symbol used for the name of COMDAT section group.
331 fn symbol(&self) -> SymbolIndex
;
333 /// Returns the name of the COMDAT section group.
334 fn name(&self) -> Result
<&str>;
336 /// Get the sections in this section group.
337 fn sections(&self) -> Self::SectionIterator
;
341 pub trait ObjectSymbolTable
<'data
>: read
::private
::Sealed
{
342 /// A symbol table entry.
343 type Symbol
: ObjectSymbol
<'data
>;
345 /// An iterator over the symbols in a symbol table.
346 type SymbolIterator
: Iterator
<Item
= Self::Symbol
>;
348 /// Get an iterator over the symbols in the table.
350 /// This may skip over symbols that are malformed or unsupported.
351 fn symbols(&self) -> Self::SymbolIterator
;
353 /// Get the symbol at the given index.
355 /// The meaning of the index depends on the object file.
357 /// Returns an error if the index is invalid.
358 fn symbol_by_index(&self, index
: SymbolIndex
) -> Result
<Self::Symbol
>;
361 /// A symbol table entry.
362 pub trait ObjectSymbol
<'data
>: read
::private
::Sealed
{
363 /// The index of the symbol.
364 fn index(&self) -> SymbolIndex
;
366 /// The name of the symbol.
367 fn name(&self) -> Result
<&'data
str>;
369 /// The address of the symbol. May be zero if the address is unknown.
370 fn address(&self) -> u64;
372 /// The size of the symbol. May be zero if the size is unknown.
373 fn size(&self) -> u64;
375 /// Return the kind of this symbol.
376 fn kind(&self) -> SymbolKind
;
378 /// Returns the section where the symbol is defined.
379 fn section(&self) -> SymbolSection
;
381 /// Returns the section index for the section containing this symbol.
383 /// May return `None` if the symbol is not defined in a section.
384 fn section_index(&self) -> Option
<SectionIndex
> {
385 self.section().index()
388 /// Return true if the symbol is undefined.
389 fn is_undefined(&self) -> bool
;
391 /// Return true if the symbol is a definition of a function or data object
392 /// that has a known address.
393 fn is_definition(&self) -> bool
;
395 /// Return true if the symbol is common data.
397 /// Note: does not check for `SymbolSection::Section` with `SectionKind::Common`.
398 fn is_common(&self) -> bool
;
400 /// Return true if the symbol is weak.
401 fn is_weak(&self) -> bool
;
403 /// Returns the symbol scope.
404 fn scope(&self) -> SymbolScope
;
406 /// Return true if the symbol visible outside of the compilation unit.
408 /// This treats `SymbolScope::Unknown` as global.
409 fn is_global(&self) -> bool
;
411 /// Return true if the symbol is only visible within the compilation unit.
412 fn is_local(&self) -> bool
;
414 /// Symbol flags that are specific to each file format.
415 fn flags(&self) -> SymbolFlags
<SectionIndex
>;
418 /// An iterator for files that don't have dynamic relocations.
420 pub struct NoDynamicRelocationIterator
;
422 impl Iterator
for NoDynamicRelocationIterator
{
423 type Item
= (u64, Relocation
);
426 fn next(&mut self) -> Option
<Self::Item
> {