object/read/coff/
symbol.rs

1use alloc::fmt;
2use alloc::vec::Vec;
3use core::convert::TryInto;
4use core::fmt::Debug;
5use core::str;
6
7use super::{CoffCommon, CoffHeader, SectionTable};
8use crate::endian::{LittleEndian as LE, U32Bytes};
9use crate::pe;
10use crate::pod::{bytes_of, bytes_of_slice, Pod};
11use crate::read::util::StringTable;
12use crate::read::{
13    self, Bytes, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex,
14    SymbolFlags, SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
15};
16
17/// A table of symbol entries in a COFF or PE file.
18///
19/// Also includes the string table used for the symbol names.
20///
21/// Returned by [`CoffHeader::symbols`] and
22/// [`ImageNtHeaders::symbols`](crate::read::pe::ImageNtHeaders::symbols).
23#[derive(Debug)]
24pub struct SymbolTable<'data, R = &'data [u8], Coff = pe::ImageFileHeader>
25where
26    R: ReadRef<'data>,
27    Coff: CoffHeader,
28{
29    symbols: &'data [Coff::ImageSymbolBytes],
30    strings: StringTable<'data, R>,
31}
32
33impl<'data, R: ReadRef<'data>, Coff: CoffHeader> Default for SymbolTable<'data, R, Coff> {
34    fn default() -> Self {
35        Self {
36            symbols: &[],
37            strings: StringTable::default(),
38        }
39    }
40}
41
42impl<'data, R: ReadRef<'data>, Coff: CoffHeader> SymbolTable<'data, R, Coff> {
43    /// Read the symbol table.
44    pub fn parse(header: &Coff, data: R) -> Result<Self> {
45        // The symbol table may not be present.
46        let mut offset = header.pointer_to_symbol_table().into();
47        let (symbols, strings) = if offset != 0 {
48            let symbols = data
49                .read_slice(&mut offset, header.number_of_symbols() as usize)
50                .read_error("Invalid COFF symbol table offset or size")?;
51
52            // Note: don't update data when reading length; the length includes itself.
53            let length = data
54                .read_at::<U32Bytes<_>>(offset)
55                .read_error("Missing COFF string table")?
56                .get(LE);
57            let str_end = offset
58                .checked_add(length as u64)
59                .read_error("Invalid COFF string table length")?;
60            let strings = StringTable::new(data, offset, str_end);
61
62            (symbols, strings)
63        } else {
64            (&[][..], StringTable::default())
65        };
66
67        Ok(SymbolTable { symbols, strings })
68    }
69
70    /// Return the string table used for the symbol names.
71    #[inline]
72    pub fn strings(&self) -> StringTable<'data, R> {
73        self.strings
74    }
75
76    /// Return true if the symbol table is empty.
77    #[inline]
78    pub fn is_empty(&self) -> bool {
79        self.symbols.is_empty()
80    }
81
82    /// The number of symbol table entries.
83    ///
84    /// This includes auxiliary symbol table entries.
85    #[inline]
86    pub fn len(&self) -> usize {
87        self.symbols.len()
88    }
89
90    /// Iterate over the symbols.
91    #[inline]
92    pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, R, Coff> {
93        SymbolIterator {
94            symbols: self,
95            index: SymbolIndex(0),
96        }
97    }
98
99    /// Return the symbol table entry at the given index.
100    #[inline]
101    pub fn symbol(&self, index: SymbolIndex) -> Result<&'data Coff::ImageSymbol> {
102        self.get::<Coff::ImageSymbol>(index, 0)
103    }
104
105    /// Return the auxiliary function symbol for the symbol table entry at the given index.
106    ///
107    /// Note that the index is of the symbol, not the first auxiliary record.
108    #[inline]
109    pub fn aux_function(&self, index: SymbolIndex) -> Result<&'data pe::ImageAuxSymbolFunction> {
110        self.get::<pe::ImageAuxSymbolFunction>(index, 1)
111    }
112
113    /// Return the auxiliary section symbol for the symbol table entry at the given index.
114    ///
115    /// Note that the index is of the symbol, not the first auxiliary record.
116    #[inline]
117    pub fn aux_section(&self, index: SymbolIndex) -> Result<&'data pe::ImageAuxSymbolSection> {
118        self.get::<pe::ImageAuxSymbolSection>(index, 1)
119    }
120
121    /// Return the auxiliary weak external symbol for the symbol table entry at the given index.
122    ///
123    /// Note that the index is of the symbol, not the first auxiliary record.
124    #[inline]
125    pub fn aux_weak_external(&self, index: SymbolIndex) -> Result<&'data pe::ImageAuxSymbolWeak> {
126        self.get::<pe::ImageAuxSymbolWeak>(index, 1)
127    }
128
129    /// Return the auxiliary file name for the symbol table entry at the given index.
130    ///
131    /// Note that the index is of the symbol, not the first auxiliary record.
132    pub fn aux_file_name(&self, index: SymbolIndex, aux_count: u8) -> Result<&'data [u8]> {
133        let entries = index
134            .0
135            .checked_add(1)
136            .and_then(|x| Some(x..x.checked_add(aux_count.into())?))
137            .and_then(|x| self.symbols.get(x))
138            .read_error("Invalid COFF symbol index")?;
139        let bytes = bytes_of_slice(entries);
140        // The name is padded with nulls.
141        Ok(match memchr::memchr(b'\0', bytes) {
142            Some(end) => &bytes[..end],
143            None => bytes,
144        })
145    }
146
147    /// Return the symbol table entry or auxiliary record at the given index and offset.
148    pub fn get<T: Pod>(&self, index: SymbolIndex, offset: usize) -> Result<&'data T> {
149        let bytes = index
150            .0
151            .checked_add(offset)
152            .and_then(|x| self.symbols.get(x))
153            .read_error("Invalid COFF symbol index")?;
154        Bytes(bytes_of(bytes))
155            .read()
156            .read_error("Invalid COFF symbol data")
157    }
158
159    /// Construct a map from addresses to a user-defined map entry.
160    pub fn map<Entry: SymbolMapEntry, F: Fn(&'data Coff::ImageSymbol) -> Option<Entry>>(
161        &self,
162        f: F,
163    ) -> SymbolMap<Entry> {
164        let mut symbols = Vec::with_capacity(self.symbols.len());
165        for (_, symbol) in self.iter() {
166            if !symbol.is_definition() {
167                continue;
168            }
169            if let Some(entry) = f(symbol) {
170                symbols.push(entry);
171            }
172        }
173        SymbolMap::new(symbols)
174    }
175}
176
177/// An iterator for symbol entries in a COFF or PE file.
178///
179/// Yields the index and symbol structure for each symbol.
180#[derive(Debug)]
181pub struct SymbolIterator<'data, 'table, R = &'data [u8], Coff = pe::ImageFileHeader>
182where
183    R: ReadRef<'data>,
184    Coff: CoffHeader,
185{
186    symbols: &'table SymbolTable<'data, R, Coff>,
187    index: SymbolIndex,
188}
189
190impl<'data, 'table, R: ReadRef<'data>, Coff: CoffHeader> Iterator
191    for SymbolIterator<'data, 'table, R, Coff>
192{
193    type Item = (SymbolIndex, &'data Coff::ImageSymbol);
194
195    fn next(&mut self) -> Option<Self::Item> {
196        let index = self.index;
197        let symbol = self.symbols.symbol(index).ok()?;
198        self.index.0 += 1 + symbol.number_of_aux_symbols() as usize;
199        Some((index, symbol))
200    }
201}
202
203/// A symbol table in a [`CoffBigFile`](super::CoffBigFile).
204pub type CoffBigSymbolTable<'data, 'file, R = &'data [u8]> =
205    CoffSymbolTable<'data, 'file, R, pe::AnonObjectHeaderBigobj>;
206
207/// A symbol table in a [`CoffFile`](super::CoffFile)
208/// or [`PeFile`](crate::read::pe::PeFile).
209#[derive(Debug, Clone, Copy)]
210pub struct CoffSymbolTable<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader>
211where
212    R: ReadRef<'data>,
213    Coff: CoffHeader,
214{
215    pub(crate) file: &'file CoffCommon<'data, R, Coff>,
216}
217
218impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed
219    for CoffSymbolTable<'data, 'file, R, Coff>
220{
221}
222
223impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbolTable<'data>
224    for CoffSymbolTable<'data, 'file, R, Coff>
225{
226    type Symbol = CoffSymbol<'data, 'file, R, Coff>;
227    type SymbolIterator = CoffSymbolIterator<'data, 'file, R, Coff>;
228
229    fn symbols(&self) -> Self::SymbolIterator {
230        CoffSymbolIterator::new(self.file)
231    }
232
233    fn symbol_by_index(&self, index: SymbolIndex) -> Result<Self::Symbol> {
234        let symbol = self.file.symbols.symbol(index)?;
235        Ok(CoffSymbol {
236            file: self.file,
237            index,
238            symbol,
239        })
240    }
241}
242
243/// An iterator for the symbols in a [`CoffBigFile`](super::CoffBigFile).
244pub type CoffBigSymbolIterator<'data, 'file, R = &'data [u8]> =
245    CoffSymbolIterator<'data, 'file, R, pe::AnonObjectHeaderBigobj>;
246
247/// An iterator for the symbols in a [`CoffFile`](super::CoffFile)
248/// or [`PeFile`](crate::read::pe::PeFile).
249pub struct CoffSymbolIterator<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader>
250where
251    R: ReadRef<'data>,
252    Coff: CoffHeader,
253{
254    file: &'file CoffCommon<'data, R, Coff>,
255    index: SymbolIndex,
256}
257
258impl<'data, 'file, R, Coff> CoffSymbolIterator<'data, 'file, R, Coff>
259where
260    R: ReadRef<'data>,
261    Coff: CoffHeader,
262{
263    pub(crate) fn new(file: &'file CoffCommon<'data, R, Coff>) -> Self {
264        Self {
265            file,
266            index: SymbolIndex(0),
267        }
268    }
269
270    pub(crate) fn empty(file: &'file CoffCommon<'data, R, Coff>) -> Self {
271        Self {
272            file,
273            index: SymbolIndex(file.symbols.len()),
274        }
275    }
276}
277
278impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> fmt::Debug
279    for CoffSymbolIterator<'data, 'file, R, Coff>
280{
281    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
282        f.debug_struct("CoffSymbolIterator").finish()
283    }
284}
285
286impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> Iterator
287    for CoffSymbolIterator<'data, 'file, R, Coff>
288{
289    type Item = CoffSymbol<'data, 'file, R, Coff>;
290
291    fn next(&mut self) -> Option<Self::Item> {
292        let index = self.index;
293        let symbol = self.file.symbols.symbol(index).ok()?;
294        self.index.0 += 1 + symbol.number_of_aux_symbols() as usize;
295        Some(CoffSymbol {
296            file: self.file,
297            index,
298            symbol,
299        })
300    }
301}
302
303/// A symbol in a [`CoffBigFile`](super::CoffBigFile).
304///
305/// Most functionality is provided by the [`ObjectSymbol`] trait implementation.
306pub type CoffBigSymbol<'data, 'file, R = &'data [u8]> =
307    CoffSymbol<'data, 'file, R, pe::AnonObjectHeaderBigobj>;
308
309/// A symbol in a [`CoffFile`](super::CoffFile) or [`PeFile`](crate::read::pe::PeFile).
310///
311/// Most functionality is provided by the [`ObjectSymbol`] trait implementation.
312#[derive(Debug, Clone, Copy)]
313pub struct CoffSymbol<'data, 'file, R = &'data [u8], Coff = pe::ImageFileHeader>
314where
315    R: ReadRef<'data>,
316    Coff: CoffHeader,
317{
318    pub(crate) file: &'file CoffCommon<'data, R, Coff>,
319    pub(crate) index: SymbolIndex,
320    pub(crate) symbol: &'data Coff::ImageSymbol,
321}
322
323impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> CoffSymbol<'data, 'file, R, Coff> {
324    #[inline]
325    /// Get the raw `ImageSymbol` struct.
326    #[deprecated(note = "Use `coff_symbol` instead")]
327    pub fn raw_symbol(&self) -> &'data Coff::ImageSymbol {
328        self.symbol
329    }
330
331    /// Get the raw `ImageSymbol` struct.
332    pub fn coff_symbol(&self) -> &'data Coff::ImageSymbol {
333        self.symbol
334    }
335}
336
337impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> read::private::Sealed
338    for CoffSymbol<'data, 'file, R, Coff>
339{
340}
341
342impl<'data, 'file, R: ReadRef<'data>, Coff: CoffHeader> ObjectSymbol<'data>
343    for CoffSymbol<'data, 'file, R, Coff>
344{
345    #[inline]
346    fn index(&self) -> SymbolIndex {
347        self.index
348    }
349
350    fn name_bytes(&self) -> read::Result<&'data [u8]> {
351        if self.symbol.has_aux_file_name() {
352            self.file
353                .symbols
354                .aux_file_name(self.index, self.symbol.number_of_aux_symbols())
355        } else {
356            self.symbol.name(self.file.symbols.strings())
357        }
358    }
359
360    fn name(&self) -> read::Result<&'data str> {
361        let name = self.name_bytes()?;
362        str::from_utf8(name)
363            .ok()
364            .read_error("Non UTF-8 COFF symbol name")
365    }
366
367    fn address(&self) -> u64 {
368        self.symbol
369            .address(self.file.image_base, &self.file.sections)
370            .unwrap_or(None)
371            .unwrap_or(0)
372    }
373
374    fn size(&self) -> u64 {
375        match self.symbol.storage_class() {
376            pe::IMAGE_SYM_CLASS_STATIC => {
377                // Section symbols may duplicate the size from the section table.
378                if self.symbol.has_aux_section() {
379                    if let Ok(aux) = self.file.symbols.aux_section(self.index) {
380                        u64::from(aux.length.get(LE))
381                    } else {
382                        0
383                    }
384                } else {
385                    0
386                }
387            }
388            pe::IMAGE_SYM_CLASS_EXTERNAL => {
389                if self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED {
390                    // For undefined symbols, symbol.value is 0 and the size is 0.
391                    // For common data, symbol.value is the size.
392                    u64::from(self.symbol.value())
393                } else if self.symbol.has_aux_function() {
394                    // Function symbols may have a size.
395                    if let Ok(aux) = self.file.symbols.aux_function(self.index) {
396                        u64::from(aux.total_size.get(LE))
397                    } else {
398                        0
399                    }
400                } else {
401                    0
402                }
403            }
404            // Most symbols don't have sizes.
405            _ => 0,
406        }
407    }
408
409    fn kind(&self) -> SymbolKind {
410        let derived_kind = if self.symbol.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION {
411            SymbolKind::Text
412        } else {
413            SymbolKind::Data
414        };
415        match self.symbol.storage_class() {
416            pe::IMAGE_SYM_CLASS_STATIC => {
417                if self.symbol.has_aux_section() {
418                    SymbolKind::Section
419                } else {
420                    derived_kind
421                }
422            }
423            pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => derived_kind,
424            pe::IMAGE_SYM_CLASS_SECTION => SymbolKind::Section,
425            pe::IMAGE_SYM_CLASS_FILE => SymbolKind::File,
426            pe::IMAGE_SYM_CLASS_LABEL => SymbolKind::Label,
427            _ => SymbolKind::Unknown,
428        }
429    }
430
431    fn section(&self) -> SymbolSection {
432        match self.symbol.section_number() {
433            pe::IMAGE_SYM_UNDEFINED => {
434                if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL {
435                    if self.symbol.value() == 0 {
436                        SymbolSection::Undefined
437                    } else {
438                        SymbolSection::Common
439                    }
440                } else if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_SECTION {
441                    SymbolSection::Undefined
442                } else {
443                    SymbolSection::Unknown
444                }
445            }
446            pe::IMAGE_SYM_ABSOLUTE => SymbolSection::Absolute,
447            pe::IMAGE_SYM_DEBUG => {
448                if self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_FILE {
449                    SymbolSection::None
450                } else {
451                    SymbolSection::Unknown
452                }
453            }
454            index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)),
455            _ => SymbolSection::Unknown,
456        }
457    }
458
459    #[inline]
460    fn is_undefined(&self) -> bool {
461        self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL
462            && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED
463            && self.symbol.value() == 0
464    }
465
466    #[inline]
467    fn is_definition(&self) -> bool {
468        self.symbol.is_definition()
469    }
470
471    #[inline]
472    fn is_common(&self) -> bool {
473        self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL
474            && self.symbol.section_number() == pe::IMAGE_SYM_UNDEFINED
475            && self.symbol.value() != 0
476    }
477
478    #[inline]
479    fn is_weak(&self) -> bool {
480        self.symbol.storage_class() == pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL
481    }
482
483    #[inline]
484    fn scope(&self) -> SymbolScope {
485        match self.symbol.storage_class() {
486            pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => {
487                // TODO: determine if symbol is exported
488                SymbolScope::Linkage
489            }
490            _ => SymbolScope::Compilation,
491        }
492    }
493
494    #[inline]
495    fn is_global(&self) -> bool {
496        match self.symbol.storage_class() {
497            pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true,
498            _ => false,
499        }
500    }
501
502    #[inline]
503    fn is_local(&self) -> bool {
504        !self.is_global()
505    }
506
507    fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
508        if self.symbol.has_aux_section() {
509            if let Ok(aux) = self.file.symbols.aux_section(self.index) {
510                let number = if Coff::is_type_bigobj() {
511                    u32::from(aux.number.get(LE)) | (u32::from(aux.high_number.get(LE)) << 16)
512                } else {
513                    u32::from(aux.number.get(LE))
514                };
515                return SymbolFlags::CoffSection {
516                    selection: aux.selection,
517                    associative_section: if number == 0 {
518                        None
519                    } else {
520                        Some(SectionIndex(number as usize))
521                    },
522                };
523            }
524        }
525        SymbolFlags::None
526    }
527}
528
529/// A trait for generic access to [`pe::ImageSymbol`] and [`pe::ImageSymbolEx`].
530#[allow(missing_docs)]
531pub trait ImageSymbol: Debug + Pod {
532    fn raw_name(&self) -> &[u8; 8];
533    fn value(&self) -> u32;
534    fn section_number(&self) -> i32;
535    fn typ(&self) -> u16;
536    fn storage_class(&self) -> u8;
537    fn number_of_aux_symbols(&self) -> u8;
538
539    /// Parse a COFF symbol name.
540    ///
541    /// `strings` must be the string table used for symbol names.
542    fn name<'data, R: ReadRef<'data>>(
543        &'data self,
544        strings: StringTable<'data, R>,
545    ) -> Result<&'data [u8]> {
546        let name = self.raw_name();
547        if name[0] == 0 {
548            // If the name starts with 0 then the last 4 bytes are a string table offset.
549            let offset = u32::from_le_bytes(name[4..8].try_into().unwrap());
550            strings
551                .get(offset)
552                .read_error("Invalid COFF symbol name offset")
553        } else {
554            // The name is inline and padded with nulls.
555            Ok(match memchr::memchr(b'\0', name) {
556                Some(end) => &name[..end],
557                None => &name[..],
558            })
559        }
560    }
561
562    /// Return the symbol address.
563    ///
564    /// This takes into account the image base and the section address,
565    /// and only returns an address for symbols that have an address.
566    fn address(&self, image_base: u64, sections: &SectionTable<'_>) -> Result<Option<u64>> {
567        // Only return an address for storage classes that we know use an address.
568        match self.storage_class() {
569            pe::IMAGE_SYM_CLASS_STATIC
570            | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL
571            | pe::IMAGE_SYM_CLASS_LABEL
572            | pe::IMAGE_SYM_CLASS_EXTERNAL => {}
573            _ => return Ok(None),
574        }
575        let Some(section_index) = self.section() else {
576            return Ok(None);
577        };
578        let section = sections.section(section_index)?;
579        let virtual_address = u64::from(section.virtual_address.get(LE));
580        let value = u64::from(self.value());
581        Ok(Some(image_base + virtual_address + value))
582    }
583
584    /// Return the section index for the symbol.
585    fn section(&self) -> Option<SectionIndex> {
586        let section_number = self.section_number();
587        if section_number > 0 {
588            Some(SectionIndex(section_number as usize))
589        } else {
590            None
591        }
592    }
593
594    /// Return true if the symbol is a definition of a function or data object.
595    fn is_definition(&self) -> bool {
596        if self.section_number() <= 0 {
597            return false;
598        }
599        match self.storage_class() {
600            pe::IMAGE_SYM_CLASS_STATIC => !self.has_aux_section(),
601            pe::IMAGE_SYM_CLASS_EXTERNAL | pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL => true,
602            _ => false,
603        }
604    }
605
606    /// Return true if the symbol has an auxiliary file name.
607    fn has_aux_file_name(&self) -> bool {
608        self.number_of_aux_symbols() > 0 && self.storage_class() == pe::IMAGE_SYM_CLASS_FILE
609    }
610
611    /// Return true if the symbol has an auxiliary function symbol.
612    fn has_aux_function(&self) -> bool {
613        self.number_of_aux_symbols() > 0
614            && self.derived_type() == pe::IMAGE_SYM_DTYPE_FUNCTION
615            && (self.storage_class() == pe::IMAGE_SYM_CLASS_EXTERNAL
616                || self.storage_class() == pe::IMAGE_SYM_CLASS_STATIC)
617    }
618
619    /// Return true if the symbol has an auxiliary section symbol.
620    fn has_aux_section(&self) -> bool {
621        self.number_of_aux_symbols() > 0
622            && self.storage_class() == pe::IMAGE_SYM_CLASS_STATIC
623            && self.typ() == 0
624    }
625
626    /// Return true if the symbol has an auxiliary weak external symbol.
627    fn has_aux_weak_external(&self) -> bool {
628        self.number_of_aux_symbols() > 0
629            && self.storage_class() == pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL
630            && self.section_number() == pe::IMAGE_SYM_UNDEFINED
631            && self.value() == 0
632    }
633
634    fn base_type(&self) -> u16 {
635        self.typ() & pe::N_BTMASK
636    }
637
638    fn derived_type(&self) -> u16 {
639        (self.typ() & pe::N_TMASK) >> pe::N_BTSHFT
640    }
641}
642
643impl ImageSymbol for pe::ImageSymbol {
644    fn raw_name(&self) -> &[u8; 8] {
645        &self.name
646    }
647    fn value(&self) -> u32 {
648        self.value.get(LE)
649    }
650    fn section_number(&self) -> i32 {
651        let section_number = self.section_number.get(LE);
652        if section_number >= pe::IMAGE_SYM_SECTION_MAX {
653            (section_number as i16) as i32
654        } else {
655            section_number as i32
656        }
657    }
658    fn typ(&self) -> u16 {
659        self.typ.get(LE)
660    }
661    fn storage_class(&self) -> u8 {
662        self.storage_class
663    }
664    fn number_of_aux_symbols(&self) -> u8 {
665        self.number_of_aux_symbols
666    }
667}
668
669impl ImageSymbol for pe::ImageSymbolEx {
670    fn raw_name(&self) -> &[u8; 8] {
671        &self.name
672    }
673    fn value(&self) -> u32 {
674        self.value.get(LE)
675    }
676    fn section_number(&self) -> i32 {
677        self.section_number.get(LE)
678    }
679    fn typ(&self) -> u16 {
680        self.typ.get(LE)
681    }
682    fn storage_class(&self) -> u8 {
683        self.storage_class
684    }
685    fn number_of_aux_symbols(&self) -> u8 {
686        self.number_of_aux_symbols
687    }
688}
689
690impl pe::ImageAuxSymbolWeak {
691    /// Get the symbol index of the default definition.
692    pub fn default_symbol(&self) -> SymbolIndex {
693        SymbolIndex(self.weak_default_sym_index.get(LE) as usize)
694    }
695}