1use alloc::fmt;
2use core::convert::TryInto;
3use core::fmt::Debug;
4use core::marker::PhantomData;
5use core::str;
6
7use crate::endian::{BigEndian as BE, U32Bytes};
8use crate::pod::{bytes_of, Pod};
9use crate::read::util::StringTable;
10use crate::xcoff;
11
12use crate::read::{
13 self, Bytes, Error, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex,
14 SymbolFlags, SymbolIndex, SymbolKind, SymbolScope, SymbolSection,
15};
16
17use super::{FileHeader, XcoffFile};
18
19/// A table of symbol entries in an XCOFF file.
20///
21/// Also includes the string table used for the symbol names.
22///
23/// Returned by [`FileHeader::symbols`].
24#[derive(Debug)]
25pub struct SymbolTable<'data, Xcoff, R = &'data [u8]>
26where
27 Xcoff: FileHeader,
28 R: ReadRef<'data>,
29{
30 symbols: &'data [xcoff::SymbolBytes],
31 strings: StringTable<'data, R>,
32 header: PhantomData<Xcoff>,
33}
34
35impl<'data, Xcoff, R> Default for SymbolTable<'data, Xcoff, R>
36where
37 Xcoff: FileHeader,
38 R: ReadRef<'data>,
39{
40 fn default() -> Self {
41 Self {
42 symbols: &[],
43 strings: StringTable::default(),
44 header: PhantomData,
45 }
46 }
47}
48
49impl<'data, Xcoff, R> SymbolTable<'data, Xcoff, R>
50where
51 Xcoff: FileHeader,
52 R: ReadRef<'data>,
53{
54 /// Parse the symbol table.
55 pub fn parse(header: Xcoff, data: R) -> Result<Self> {
56 let mut offset = header.f_symptr().into();
57 let (symbols, strings) = if offset != 0 {
58 let symbols = data
59 .read_slice(&mut offset, header.f_nsyms() as usize)
60 .read_error("Invalid XCOFF symbol table offset or size")?;
61
62 // Parse the string table.
63 // Note: don't update data when reading length; the length includes itself.
64 let length = data
65 .read_at::<U32Bytes<_>>(offset)
66 .read_error("Missing XCOFF string table")?
67 .get(BE);
68 let str_end = offset
69 .checked_add(length as u64)
70 .read_error("Invalid XCOFF string table length")?;
71 let strings = StringTable::new(data, offset, str_end);
72
73 (symbols, strings)
74 } else {
75 (&[][..], StringTable::default())
76 };
77
78 Ok(SymbolTable {
79 symbols,
80 strings,
81 header: PhantomData,
82 })
83 }
84
85 /// Return the string table used for the symbol names.
86 #[inline]
87 pub fn strings(&self) -> StringTable<'data, R> {
88 self.strings
89 }
90
91 /// Iterate over the symbols.
92 #[inline]
93 pub fn iter<'table>(&'table self) -> SymbolIterator<'data, 'table, Xcoff, R> {
94 SymbolIterator {
95 symbols: self,
96 index: 0,
97 }
98 }
99
100 /// Empty symbol iterator.
101 #[inline]
102 pub(super) fn iter_none<'table>(&'table self) -> SymbolIterator<'data, 'table, Xcoff, R> {
103 SymbolIterator {
104 symbols: self,
105 index: self.symbols.len(),
106 }
107 }
108
109 /// Return the symbol entry at the given index and offset.
110 pub fn get<T: Pod>(&self, index: usize, offset: usize) -> Result<&'data T> {
111 let entry = index
112 .checked_add(offset)
113 .and_then(|x| self.symbols.get(x))
114 .read_error("Invalid XCOFF symbol index")?;
115 let bytes = bytes_of(entry);
116 Bytes(bytes).read().read_error("Invalid XCOFF symbol data")
117 }
118
119 /// Return the symbol at the given index.
120 pub fn symbol(&self, index: usize) -> Result<&'data Xcoff::Symbol> {
121 self.get::<Xcoff::Symbol>(index, 0)
122 }
123
124 /// Return a file auxiliary symbol.
125 pub fn aux_file(&self, index: usize, offset: usize) -> Result<&'data Xcoff::FileAux> {
126 debug_assert!(self.symbol(index)?.has_aux_file());
127 let aux_file = self.get::<Xcoff::FileAux>(index, offset)?;
128 if let Some(aux_type) = aux_file.x_auxtype() {
129 if aux_type != xcoff::AUX_FILE {
130 return Err(Error("Invalid index for file auxiliary symbol."));
131 }
132 }
133 Ok(aux_file)
134 }
135
136 /// Return the csect auxiliary symbol.
137 pub fn aux_csect(&self, index: usize, offset: usize) -> Result<&'data Xcoff::CsectAux> {
138 debug_assert!(self.symbol(index)?.has_aux_csect());
139 let aux_csect = self.get::<Xcoff::CsectAux>(index, offset)?;
140 if let Some(aux_type) = aux_csect.x_auxtype() {
141 if aux_type != xcoff::AUX_CSECT {
142 return Err(Error("Invalid index/offset for csect auxiliary symbol."));
143 }
144 }
145 Ok(aux_csect)
146 }
147
148 /// Return true if the symbol table is empty.
149 #[inline]
150 pub fn is_empty(&self) -> bool {
151 self.symbols.is_empty()
152 }
153
154 /// The number of symbol table entries.
155 ///
156 /// This includes auxiliary symbol table entries.
157 #[inline]
158 pub fn len(&self) -> usize {
159 self.symbols.len()
160 }
161}
162
163/// An iterator for symbol entries in an XCOFF file.
164///
165/// Yields the index and symbol structure for each symbol.
166#[derive(Debug)]
167pub struct SymbolIterator<'data, 'table, Xcoff, R = &'data [u8]>
168where
169 Xcoff: FileHeader,
170 R: ReadRef<'data>,
171{
172 symbols: &'table SymbolTable<'data, Xcoff, R>,
173 index: usize,
174}
175
176impl<'data, 'table, Xcoff: FileHeader, R: ReadRef<'data>> Iterator
177 for SymbolIterator<'data, 'table, Xcoff, R>
178{
179 type Item = (SymbolIndex, &'data Xcoff::Symbol);
180
181 fn next(&mut self) -> Option<Self::Item> {
182 let index: usize = self.index;
183 let symbol: &::Symbol = self.symbols.symbol(index).ok()?;
184 self.index += 1 + symbol.n_numaux() as usize;
185 Some((SymbolIndex(index), symbol))
186 }
187}
188
189/// A symbol table in an [`XcoffFile32`](super::XcoffFile32).
190pub type XcoffSymbolTable32<'data, 'file, R = &'data [u8]> =
191 XcoffSymbolTable<'data, 'file, xcoff::FileHeader32, R>;
192/// A symbol table in an [`XcoffFile64`](super::XcoffFile64).
193pub type XcoffSymbolTable64<'data, 'file, R = &'data [u8]> =
194 XcoffSymbolTable<'data, 'file, xcoff::FileHeader64, R>;
195
196/// A symbol table in an [`XcoffFile`].
197#[derive(Debug, Clone, Copy)]
198pub struct XcoffSymbolTable<'data, 'file, Xcoff, R = &'data [u8]>
199where
200 Xcoff: FileHeader,
201 R: ReadRef<'data>,
202{
203 pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
204 pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
205}
206
207impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed
208 for XcoffSymbolTable<'data, 'file, Xcoff, R>
209{
210}
211
212impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data>
213 for XcoffSymbolTable<'data, 'file, Xcoff, R>
214{
215 type Symbol = XcoffSymbol<'data, 'file, Xcoff, R>;
216 type SymbolIterator = XcoffSymbolIterator<'data, 'file, Xcoff, R>;
217
218 fn symbols(&self) -> Self::SymbolIterator {
219 XcoffSymbolIterator {
220 file: self.file,
221 symbols: self.symbols.iter(),
222 }
223 }
224
225 fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<Self::Symbol> {
226 let symbol: &::Symbol = self.symbols.symbol(index:index.0)?;
227 Ok(XcoffSymbol {
228 file: self.file,
229 symbols: self.symbols,
230 index,
231 symbol,
232 })
233 }
234}
235
236/// An iterator for the symbols in an [`XcoffFile32`](super::XcoffFile32).
237pub type XcoffSymbolIterator32<'data, 'file, R = &'data [u8]> =
238 XcoffSymbolIterator<'data, 'file, xcoff::FileHeader32, R>;
239/// An iterator for the symbols in an [`XcoffFile64`](super::XcoffFile64).
240pub type XcoffSymbolIterator64<'data, 'file, R = &'data [u8]> =
241 XcoffSymbolIterator<'data, 'file, xcoff::FileHeader64, R>;
242
243/// An iterator for the symbols in an [`XcoffFile`].
244pub struct XcoffSymbolIterator<'data, 'file, Xcoff, R = &'data [u8]>
245where
246 Xcoff: FileHeader,
247 R: ReadRef<'data>,
248{
249 pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
250 pub(super) symbols: SymbolIterator<'data, 'file, Xcoff, R>,
251}
252
253impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> fmt::Debug
254 for XcoffSymbolIterator<'data, 'file, Xcoff, R>
255{
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 f.debug_struct(name:"XcoffSymbolIterator").finish()
258 }
259}
260
261impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> Iterator
262 for XcoffSymbolIterator<'data, 'file, Xcoff, R>
263{
264 type Item = XcoffSymbol<'data, 'file, Xcoff, R>;
265
266 fn next(&mut self) -> Option<Self::Item> {
267 let (index: SymbolIndex, symbol: &::Symbol) = self.symbols.next()?;
268 Some(XcoffSymbol {
269 file: self.file,
270 symbols: self.symbols.symbols,
271 index,
272 symbol,
273 })
274 }
275}
276
277/// A symbol in an [`XcoffFile32`](super::XcoffFile32).
278pub type XcoffSymbol32<'data, 'file, R = &'data [u8]> =
279 XcoffSymbol<'data, 'file, xcoff::FileHeader32, R>;
280/// A symbol in an [`XcoffFile64`](super::XcoffFile64).
281pub type XcoffSymbol64<'data, 'file, R = &'data [u8]> =
282 XcoffSymbol<'data, 'file, xcoff::FileHeader64, R>;
283
284/// A symbol in an [`XcoffFile`].
285///
286/// Most functionality is provided by the [`ObjectSymbol`] trait implementation.
287#[derive(Debug, Clone, Copy)]
288pub struct XcoffSymbol<'data, 'file, Xcoff, R = &'data [u8]>
289where
290 Xcoff: FileHeader,
291 R: ReadRef<'data>,
292{
293 pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
294 pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
295 pub(super) index: SymbolIndex,
296 pub(super) symbol: &'data Xcoff::Symbol,
297}
298
299impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed
300 for XcoffSymbol<'data, 'file, Xcoff, R>
301{
302}
303
304impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
305 for XcoffSymbol<'data, 'file, Xcoff, R>
306{
307 #[inline]
308 fn index(&self) -> SymbolIndex {
309 self.index
310 }
311
312 fn name_bytes(&self) -> Result<&'data [u8]> {
313 if self.symbol.has_aux_file() {
314 // By convention the file name is in the first auxiliary entry.
315 self.symbols
316 .aux_file(self.index.0, 1)?
317 .fname(self.symbols.strings)
318 } else {
319 self.symbol.name(self.symbols.strings)
320 }
321 }
322
323 fn name(&self) -> Result<&'data str> {
324 let name = self.name_bytes()?;
325 str::from_utf8(name)
326 .ok()
327 .read_error("Non UTF-8 XCOFF symbol name")
328 }
329
330 #[inline]
331 fn address(&self) -> u64 {
332 match self.symbol.n_sclass() {
333 // Relocatable address.
334 xcoff::C_EXT
335 | xcoff::C_WEAKEXT
336 | xcoff::C_HIDEXT
337 | xcoff::C_FCN
338 | xcoff::C_BLOCK
339 | xcoff::C_STAT
340 | xcoff::C_INFO => self.symbol.n_value().into(),
341 _ => 0,
342 }
343 }
344
345 #[inline]
346 fn size(&self) -> u64 {
347 if self.symbol.has_aux_csect() {
348 // XCOFF32 must have the csect auxiliary entry as the last auxiliary entry.
349 // XCOFF64 doesn't require this, but conventionally does.
350 if let Ok(aux_csect) = self
351 .file
352 .symbols
353 .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
354 {
355 let sym_type = aux_csect.sym_type();
356 if sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_CM {
357 return aux_csect.x_scnlen();
358 }
359 }
360 }
361 0
362 }
363
364 fn kind(&self) -> SymbolKind {
365 if self.symbol.has_aux_csect() {
366 if let Ok(aux_csect) = self
367 .file
368 .symbols
369 .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
370 {
371 let sym_type = aux_csect.sym_type();
372 if sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_CM {
373 return match aux_csect.x_smclas() {
374 xcoff::XMC_PR | xcoff::XMC_GL => SymbolKind::Text,
375 xcoff::XMC_RO | xcoff::XMC_RW | xcoff::XMC_TD | xcoff::XMC_BS => {
376 SymbolKind::Data
377 }
378 xcoff::XMC_TL | xcoff::XMC_UL => SymbolKind::Tls,
379 xcoff::XMC_DS | xcoff::XMC_TC0 | xcoff::XMC_TC => {
380 // `Metadata` might be a better kind for these if we had it.
381 SymbolKind::Data
382 }
383 _ => SymbolKind::Unknown,
384 };
385 } else if sym_type == xcoff::XTY_LD {
386 // A function entry point. Neither `Text` nor `Label` are a good fit for this.
387 return SymbolKind::Text;
388 } else if sym_type == xcoff::XTY_ER {
389 return SymbolKind::Unknown;
390 }
391 }
392 }
393 match self.symbol.n_sclass() {
394 xcoff::C_NULL => SymbolKind::Null,
395 xcoff::C_FILE => SymbolKind::File,
396 _ => SymbolKind::Unknown,
397 }
398 }
399
400 fn section(&self) -> SymbolSection {
401 match self.symbol.n_scnum() {
402 xcoff::N_ABS => SymbolSection::Absolute,
403 xcoff::N_UNDEF => SymbolSection::Undefined,
404 xcoff::N_DEBUG => SymbolSection::None,
405 index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)),
406 _ => SymbolSection::Unknown,
407 }
408 }
409
410 #[inline]
411 fn is_undefined(&self) -> bool {
412 self.symbol.is_undefined()
413 }
414
415 /// Return true if the symbol is a definition of a function or data object.
416 #[inline]
417 fn is_definition(&self) -> bool {
418 if self.symbol.n_scnum() <= 0 {
419 return false;
420 }
421 if self.symbol.has_aux_csect() {
422 if let Ok(aux_csect) = self
423 .symbols
424 .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
425 {
426 let sym_type = aux_csect.sym_type();
427 sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_LD || sym_type == xcoff::XTY_CM
428 } else {
429 false
430 }
431 } else {
432 false
433 }
434 }
435
436 #[inline]
437 fn is_common(&self) -> bool {
438 self.symbol.n_sclass() == xcoff::C_EXT && self.symbol.n_scnum() == xcoff::N_UNDEF
439 }
440
441 #[inline]
442 fn is_weak(&self) -> bool {
443 self.symbol.n_sclass() == xcoff::C_WEAKEXT
444 }
445
446 fn scope(&self) -> SymbolScope {
447 if self.symbol.n_scnum() == xcoff::N_UNDEF {
448 SymbolScope::Unknown
449 } else {
450 match self.symbol.n_sclass() {
451 xcoff::C_EXT | xcoff::C_WEAKEXT => {
452 let visibility = self.symbol.n_type() & xcoff::SYM_V_MASK;
453 if visibility == xcoff::SYM_V_HIDDEN {
454 SymbolScope::Linkage
455 } else {
456 SymbolScope::Dynamic
457 }
458 }
459 _ => SymbolScope::Compilation,
460 }
461 }
462 }
463
464 #[inline]
465 fn is_global(&self) -> bool {
466 match self.symbol.n_sclass() {
467 xcoff::C_EXT | xcoff::C_WEAKEXT => true,
468 _ => false,
469 }
470 }
471
472 #[inline]
473 fn is_local(&self) -> bool {
474 !self.is_global()
475 }
476
477 #[inline]
478 fn flags(&self) -> SymbolFlags<SectionIndex, SymbolIndex> {
479 let mut x_smtyp = 0;
480 let mut x_smclas = 0;
481 let mut containing_csect = None;
482 if self.symbol.has_aux_csect() {
483 if let Ok(aux_csect) = self
484 .file
485 .symbols
486 .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
487 {
488 x_smtyp = aux_csect.x_smtyp();
489 x_smclas = aux_csect.x_smclas();
490 if aux_csect.sym_type() == xcoff::XTY_LD {
491 containing_csect = Some(SymbolIndex(aux_csect.x_scnlen() as usize))
492 }
493 }
494 }
495 SymbolFlags::Xcoff {
496 n_sclass: self.symbol.n_sclass(),
497 x_smtyp,
498 x_smclas,
499 containing_csect,
500 }
501 }
502}
503
504/// A trait for generic access to [`xcoff::Symbol32`] and [`xcoff::Symbol64`].
505#[allow(missing_docs)]
506pub trait Symbol: Debug + Pod {
507 type Word: Into<u64>;
508
509 fn n_value(&self) -> Self::Word;
510 fn n_scnum(&self) -> i16;
511 fn n_type(&self) -> u16;
512 fn n_sclass(&self) -> u8;
513 fn n_numaux(&self) -> u8;
514
515 fn name_offset(&self) -> Option<u32>;
516 fn name<'data, R: ReadRef<'data>>(
517 &'data self,
518 strings: StringTable<'data, R>,
519 ) -> Result<&'data [u8]>;
520
521 /// Return true if the symbol is undefined.
522 #[inline]
523 fn is_undefined(&self) -> bool {
524 let n_sclass = self.n_sclass();
525 (n_sclass == xcoff::C_EXT || n_sclass == xcoff::C_WEAKEXT)
526 && self.n_scnum() == xcoff::N_UNDEF
527 }
528
529 /// Return true if the symbol has file auxiliary entry.
530 fn has_aux_file(&self) -> bool {
531 self.n_numaux() > 0 && self.n_sclass() == xcoff::C_FILE
532 }
533
534 /// Return true if the symbol has csect auxiliary entry.
535 ///
536 /// A csect auxiliary entry is required for each symbol table entry that has
537 /// a storage class value of C_EXT, C_WEAKEXT, or C_HIDEXT.
538 fn has_aux_csect(&self) -> bool {
539 let sclass = self.n_sclass();
540 self.n_numaux() > 0
541 && (sclass == xcoff::C_EXT || sclass == xcoff::C_WEAKEXT || sclass == xcoff::C_HIDEXT)
542 }
543}
544
545impl Symbol for xcoff::Symbol64 {
546 type Word = u64;
547
548 fn n_value(&self) -> Self::Word {
549 self.n_value.get(BE)
550 }
551
552 fn n_scnum(&self) -> i16 {
553 self.n_scnum.get(BE)
554 }
555
556 fn n_type(&self) -> u16 {
557 self.n_type.get(BE)
558 }
559
560 fn n_sclass(&self) -> u8 {
561 self.n_sclass
562 }
563
564 fn n_numaux(&self) -> u8 {
565 self.n_numaux
566 }
567
568 fn name_offset(&self) -> Option<u32> {
569 Some(self.n_offset.get(BE))
570 }
571
572 /// Parse the symbol name for XCOFF64.
573 fn name<'data, R: ReadRef<'data>>(
574 &'data self,
575 strings: StringTable<'data, R>,
576 ) -> Result<&'data [u8]> {
577 strings
578 .get(self.n_offset.get(BE))
579 .read_error("Invalid XCOFF symbol name offset")
580 }
581}
582
583impl Symbol for xcoff::Symbol32 {
584 type Word = u32;
585
586 fn n_value(&self) -> Self::Word {
587 self.n_value.get(BE)
588 }
589
590 fn n_scnum(&self) -> i16 {
591 self.n_scnum.get(BE)
592 }
593
594 fn n_type(&self) -> u16 {
595 self.n_type.get(BE)
596 }
597
598 fn n_sclass(&self) -> u8 {
599 self.n_sclass
600 }
601
602 fn n_numaux(&self) -> u8 {
603 self.n_numaux
604 }
605
606 fn name_offset(&self) -> Option<u32> {
607 if self.n_name[0] == 0 {
608 let offset = u32::from_be_bytes(self.n_name[4..8].try_into().unwrap());
609 Some(offset)
610 } else {
611 None
612 }
613 }
614
615 /// Parse the symbol name for XCOFF32.
616 fn name<'data, R: ReadRef<'data>>(
617 &'data self,
618 strings: StringTable<'data, R>,
619 ) -> Result<&'data [u8]> {
620 if let Some(offset) = self.name_offset() {
621 // If the name starts with 0 then the last 4 bytes are a string table offset.
622 strings
623 .get(offset)
624 .read_error("Invalid XCOFF symbol name offset")
625 } else {
626 // The name is inline and padded with nulls.
627 Ok(match memchr::memchr(b'\0', &self.n_name) {
628 Some(end) => &self.n_name[..end],
629 None => &self.n_name,
630 })
631 }
632 }
633}
634
635/// A trait for generic access to [`xcoff::FileAux32`] and [`xcoff::FileAux64`].
636#[allow(missing_docs)]
637pub trait FileAux: Debug + Pod {
638 fn x_fname(&self) -> &[u8; 8];
639 fn x_ftype(&self) -> u8;
640 fn x_auxtype(&self) -> Option<u8>;
641
642 fn name_offset(&self) -> Option<u32> {
643 let x_fname = self.x_fname();
644 if x_fname[0] == 0 {
645 Some(u32::from_be_bytes(x_fname[4..8].try_into().unwrap()))
646 } else {
647 None
648 }
649 }
650
651 /// Parse the x_fname field, which may be an inline string or a string table offset.
652 fn fname<'data, R: ReadRef<'data>>(
653 &'data self,
654 strings: StringTable<'data, R>,
655 ) -> Result<&'data [u8]> {
656 if let Some(offset) = self.name_offset() {
657 // If the name starts with 0 then the last 4 bytes are a string table offset.
658 strings
659 .get(offset)
660 .read_error("Invalid XCOFF symbol name offset")
661 } else {
662 // The name is inline and padded with nulls.
663 let x_fname = self.x_fname();
664 Ok(match memchr::memchr(b'\0', x_fname) {
665 Some(end) => &x_fname[..end],
666 None => x_fname,
667 })
668 }
669 }
670}
671
672impl FileAux for xcoff::FileAux64 {
673 fn x_fname(&self) -> &[u8; 8] {
674 &self.x_fname
675 }
676
677 fn x_ftype(&self) -> u8 {
678 self.x_ftype
679 }
680
681 fn x_auxtype(&self) -> Option<u8> {
682 Some(self.x_auxtype)
683 }
684}
685
686impl FileAux for xcoff::FileAux32 {
687 fn x_fname(&self) -> &[u8; 8] {
688 &self.x_fname
689 }
690
691 fn x_ftype(&self) -> u8 {
692 self.x_ftype
693 }
694
695 fn x_auxtype(&self) -> Option<u8> {
696 None
697 }
698}
699
700/// A trait for generic access to [`xcoff::CsectAux32`] and [`xcoff::CsectAux64`].
701#[allow(missing_docs)]
702pub trait CsectAux: Debug + Pod {
703 fn x_scnlen(&self) -> u64;
704 fn x_parmhash(&self) -> u32;
705 fn x_snhash(&self) -> u16;
706 fn x_smtyp(&self) -> u8;
707 fn x_smclas(&self) -> u8;
708 fn x_stab(&self) -> Option<u32>;
709 fn x_snstab(&self) -> Option<u16>;
710 fn x_auxtype(&self) -> Option<u8>;
711
712 fn alignment(&self) -> u8 {
713 self.x_smtyp() >> 3
714 }
715 fn sym_type(&self) -> u8 {
716 self.x_smtyp() & 0x07
717 }
718}
719
720impl CsectAux for xcoff::CsectAux64 {
721 fn x_scnlen(&self) -> u64 {
722 self.x_scnlen_lo.get(BE) as u64 | ((self.x_scnlen_hi.get(BE) as u64) << 32)
723 }
724
725 fn x_parmhash(&self) -> u32 {
726 self.x_parmhash.get(BE)
727 }
728
729 fn x_snhash(&self) -> u16 {
730 self.x_snhash.get(BE)
731 }
732
733 fn x_smtyp(&self) -> u8 {
734 self.x_smtyp
735 }
736
737 fn x_smclas(&self) -> u8 {
738 self.x_smclas
739 }
740
741 fn x_stab(&self) -> Option<u32> {
742 None
743 }
744
745 fn x_snstab(&self) -> Option<u16> {
746 None
747 }
748
749 fn x_auxtype(&self) -> Option<u8> {
750 Some(self.x_auxtype)
751 }
752}
753
754impl CsectAux for xcoff::CsectAux32 {
755 fn x_scnlen(&self) -> u64 {
756 self.x_scnlen.get(BE) as u64
757 }
758
759 fn x_parmhash(&self) -> u32 {
760 self.x_parmhash.get(BE)
761 }
762
763 fn x_snhash(&self) -> u16 {
764 self.x_snhash.get(BE)
765 }
766
767 fn x_smtyp(&self) -> u8 {
768 self.x_smtyp
769 }
770
771 fn x_smclas(&self) -> u8 {
772 self.x_smclas
773 }
774
775 fn x_stab(&self) -> Option<u32> {
776 Some(self.x_stab.get(BE))
777 }
778
779 fn x_snstab(&self) -> Option<u16> {
780 Some(self.x_snstab.get(BE))
781 }
782
783 fn x_auxtype(&self) -> Option<u8> {
784 None
785 }
786}
787