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