1use alloc::borrow::Cow;
13use alloc::string::String;
14use alloc::vec::Vec;
15use core::{fmt, result, str};
16#[cfg(not(feature = "std"))]
17use hashbrown::HashMap;
18#[cfg(feature = "std")]
19use std::{boxed::Box, collections::HashMap, error, io};
20
21use crate::endian::{Endianness, U32, U64};
22
23pub use crate::common::*;
24
25#[cfg(feature = "coff")]
26pub mod coff;
27#[cfg(feature = "coff")]
28pub use coff::CoffExportStyle;
29
30#[cfg(feature = "elf")]
31pub mod elf;
32
33#[cfg(feature = "macho")]
34mod macho;
35#[cfg(feature = "macho")]
36pub use macho::MachOBuildVersion;
37
38#[cfg(feature = "pe")]
39pub mod pe;
40
41#[cfg(feature = "xcoff")]
42mod xcoff;
43
44pub(crate) mod string;
45pub use string::StringId;
46
47mod util;
48pub use util::*;
49
50#[derive(Debug, Clone, PartialEq, Eq)]
52pub struct Error(pub(crate) String);
53
54impl fmt::Display for Error {
55 #[inline]
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 f.write_str(&self.0)
58 }
59}
60
61#[cfg(feature = "std")]
62impl error::Error for Error {}
63#[cfg(all(not(feature = "std"), core_error))]
64impl core::error::Error for Error {}
65
66pub type Result<T> = result::Result<T, Error>;
68
69#[derive(Debug)]
71pub struct Object<'a> {
72 format: BinaryFormat,
73 architecture: Architecture,
74 sub_architecture: Option<SubArchitecture>,
75 endian: Endianness,
76 sections: Vec<Section<'a>>,
77 standard_sections: HashMap<StandardSection, SectionId>,
78 symbols: Vec<Symbol>,
79 symbol_map: HashMap<Vec<u8>, SymbolId>,
80 comdats: Vec<Comdat>,
81 pub flags: FileFlags,
83 pub mangling: Mangling,
85 #[cfg(feature = "coff")]
86 stub_symbols: HashMap<SymbolId, SymbolId>,
87 #[cfg(feature = "macho")]
89 tlv_bootstrap: Option<SymbolId>,
90 #[cfg(feature = "macho")]
92 macho_cpu_subtype: Option<u32>,
93 #[cfg(feature = "macho")]
94 macho_build_version: Option<MachOBuildVersion>,
95 #[cfg(feature = "macho")]
97 macho_subsections_via_symbols: bool,
98}
99
100impl<'a> Object<'a> {
101 pub fn new(format: BinaryFormat, architecture: Architecture, endian: Endianness) -> Object<'a> {
103 Object {
104 format,
105 architecture,
106 sub_architecture: None,
107 endian,
108 sections: Vec::new(),
109 standard_sections: HashMap::new(),
110 symbols: Vec::new(),
111 symbol_map: HashMap::new(),
112 comdats: Vec::new(),
113 flags: FileFlags::None,
114 mangling: Mangling::default(format, architecture),
115 #[cfg(feature = "coff")]
116 stub_symbols: HashMap::new(),
117 #[cfg(feature = "macho")]
118 tlv_bootstrap: None,
119 #[cfg(feature = "macho")]
120 macho_cpu_subtype: None,
121 #[cfg(feature = "macho")]
122 macho_build_version: None,
123 #[cfg(feature = "macho")]
124 macho_subsections_via_symbols: false,
125 }
126 }
127
128 #[inline]
130 pub fn format(&self) -> BinaryFormat {
131 self.format
132 }
133
134 #[inline]
136 pub fn architecture(&self) -> Architecture {
137 self.architecture
138 }
139
140 #[inline]
142 pub fn sub_architecture(&self) -> Option<SubArchitecture> {
143 self.sub_architecture
144 }
145
146 pub fn set_sub_architecture(&mut self, sub_architecture: Option<SubArchitecture>) {
148 self.sub_architecture = sub_architecture;
149 }
150
151 #[inline]
153 pub fn mangling(&self) -> Mangling {
154 self.mangling
155 }
156
157 #[inline]
159 pub fn set_mangling(&mut self, mangling: Mangling) {
160 self.mangling = mangling;
161 }
162
163 #[allow(unused_variables)]
167 pub fn segment_name(&self, segment: StandardSegment) -> &'static [u8] {
168 match self.format {
169 #[cfg(feature = "coff")]
170 BinaryFormat::Coff => &[],
171 #[cfg(feature = "elf")]
172 BinaryFormat::Elf => &[],
173 #[cfg(feature = "macho")]
174 BinaryFormat::MachO => self.macho_segment_name(segment),
175 _ => unimplemented!(),
176 }
177 }
178
179 #[inline]
181 pub fn section(&self, section: SectionId) -> &Section<'a> {
182 &self.sections[section.0]
183 }
184
185 #[inline]
187 pub fn section_mut(&mut self, section: SectionId) -> &mut Section<'a> {
188 &mut self.sections[section.0]
189 }
190
191 pub fn set_section_data<T>(&mut self, section: SectionId, data: T, align: u64)
196 where
197 T: Into<Cow<'a, [u8]>>,
198 {
199 self.sections[section.0].set_data(data, align)
200 }
201
202 pub fn append_section_data(&mut self, section: SectionId, data: &[u8], align: u64) -> u64 {
207 self.sections[section.0].append_data(data, align)
208 }
209
210 pub fn append_section_bss(&mut self, section: SectionId, size: u64, align: u64) -> u64 {
215 self.sections[section.0].append_bss(size, align)
216 }
217
218 pub fn section_id(&mut self, section: StandardSection) -> SectionId {
222 self.standard_sections
223 .get(§ion)
224 .cloned()
225 .unwrap_or_else(|| {
226 let (segment, name, kind, flags) = self.section_info(section);
227 let id = self.add_section(segment.to_vec(), name.to_vec(), kind);
228 self.section_mut(id).flags = flags;
229 id
230 })
231 }
232
233 pub fn add_section(&mut self, segment: Vec<u8>, name: Vec<u8>, kind: SectionKind) -> SectionId {
237 let id = SectionId(self.sections.len());
238 self.sections.push(Section {
239 segment,
240 name,
241 kind,
242 size: 0,
243 align: 1,
244 data: Cow::Borrowed(&[]),
245 relocations: Vec::new(),
246 symbol: None,
247 flags: SectionFlags::None,
248 });
249
250 let section = &self.sections[id.0];
252 for standard_section in StandardSection::all() {
253 if !self.standard_sections.contains_key(standard_section) {
254 let (segment, name, kind, _flags) = self.section_info(*standard_section);
255 if segment == &*section.segment && name == &*section.name && kind == section.kind {
256 self.standard_sections.insert(*standard_section, id);
257 }
258 }
259 }
260
261 id
262 }
263
264 fn section_info(
265 &self,
266 section: StandardSection,
267 ) -> (&'static [u8], &'static [u8], SectionKind, SectionFlags) {
268 match self.format {
269 #[cfg(feature = "coff")]
270 BinaryFormat::Coff => self.coff_section_info(section),
271 #[cfg(feature = "elf")]
272 BinaryFormat::Elf => self.elf_section_info(section),
273 #[cfg(feature = "macho")]
274 BinaryFormat::MachO => self.macho_section_info(section),
275 #[cfg(feature = "xcoff")]
276 BinaryFormat::Xcoff => self.xcoff_section_info(section),
277 _ => unimplemented!(),
278 }
279 }
280
281 pub fn add_subsection(&mut self, section: StandardSection, name: &[u8]) -> SectionId {
287 if self.has_subsections_via_symbols() {
288 self.section_id(section)
289 } else {
290 let (segment, name, kind, flags) = self.subsection_info(section, name);
291 let id = self.add_section(segment.to_vec(), name, kind);
292 self.section_mut(id).flags = flags;
293 id
294 }
295 }
296
297 fn has_subsections_via_symbols(&self) -> bool {
298 self.format == BinaryFormat::MachO
299 }
300
301 pub fn set_subsections_via_symbols(&mut self) {
308 #[cfg(feature = "macho")]
309 if self.format == BinaryFormat::MachO {
310 self.macho_subsections_via_symbols = true;
311 }
312 }
313
314 fn subsection_info(
315 &self,
316 section: StandardSection,
317 value: &[u8],
318 ) -> (&'static [u8], Vec<u8>, SectionKind, SectionFlags) {
319 let (segment, section, kind, flags) = self.section_info(section);
320 let name = self.subsection_name(section, value);
321 (segment, name, kind, flags)
322 }
323
324 #[allow(unused_variables)]
325 fn subsection_name(&self, section: &[u8], value: &[u8]) -> Vec<u8> {
326 debug_assert!(!self.has_subsections_via_symbols());
327 match self.format {
328 #[cfg(feature = "coff")]
329 BinaryFormat::Coff => self.coff_subsection_name(section, value),
330 #[cfg(feature = "elf")]
331 BinaryFormat::Elf => self.elf_subsection_name(section, value),
332 _ => unimplemented!(),
333 }
334 }
335
336 #[inline]
338 pub fn comdat(&self, comdat: ComdatId) -> &Comdat {
339 &self.comdats[comdat.0]
340 }
341
342 #[inline]
344 pub fn comdat_mut(&mut self, comdat: ComdatId) -> &mut Comdat {
345 &mut self.comdats[comdat.0]
346 }
347
348 pub fn add_comdat(&mut self, comdat: Comdat) -> ComdatId {
350 let comdat_id = ComdatId(self.comdats.len());
351 self.comdats.push(comdat);
352 comdat_id
353 }
354
355 pub fn symbol_id(&self, name: &[u8]) -> Option<SymbolId> {
357 self.symbol_map.get(name).cloned()
358 }
359
360 #[inline]
362 pub fn symbol(&self, symbol: SymbolId) -> &Symbol {
363 &self.symbols[symbol.0]
364 }
365
366 #[inline]
368 pub fn symbol_mut(&mut self, symbol: SymbolId) -> &mut Symbol {
369 &mut self.symbols[symbol.0]
370 }
371
372 pub fn add_symbol(&mut self, mut symbol: Symbol) -> SymbolId {
374 debug_assert!(symbol.is_undefined() || symbol.scope != SymbolScope::Unknown);
376 if symbol.kind == SymbolKind::Section {
377 let symbol_id = self.section_symbol(symbol.section.id().unwrap());
380 if symbol.flags != SymbolFlags::None {
381 self.symbol_mut(symbol_id).flags = symbol.flags;
382 }
383 return symbol_id;
384 }
385 if !symbol.name.is_empty()
386 && (symbol.kind == SymbolKind::Text
387 || symbol.kind == SymbolKind::Data
388 || symbol.kind == SymbolKind::Tls)
389 {
390 let unmangled_name = symbol.name.clone();
391 if let Some(prefix) = self.mangling.global_prefix() {
392 symbol.name.insert(0, prefix);
393 }
394 let symbol_id = self.add_raw_symbol(symbol);
395 self.symbol_map.insert(unmangled_name, symbol_id);
396 symbol_id
397 } else {
398 self.add_raw_symbol(symbol)
399 }
400 }
401
402 fn add_raw_symbol(&mut self, symbol: Symbol) -> SymbolId {
403 let symbol_id = SymbolId(self.symbols.len());
404 self.symbols.push(symbol);
405 symbol_id
406 }
407
408 #[inline]
410 pub fn has_uninitialized_tls(&self) -> bool {
411 self.format != BinaryFormat::Coff
412 }
413
414 #[inline]
416 pub fn has_common(&self) -> bool {
417 self.format == BinaryFormat::MachO
418 }
419
420 pub fn add_common_symbol(&mut self, mut symbol: Symbol, size: u64, align: u64) -> SymbolId {
426 if self.has_common() {
427 let symbol_id = self.add_symbol(symbol);
428 let section = self.section_id(StandardSection::Common);
429 self.add_symbol_bss(symbol_id, section, size, align);
430 symbol_id
431 } else {
432 symbol.section = SymbolSection::Common;
433 symbol.size = size;
434 self.add_symbol(symbol)
435 }
436 }
437
438 pub fn add_file_symbol(&mut self, name: Vec<u8>) -> SymbolId {
440 self.add_raw_symbol(Symbol {
441 name,
442 value: 0,
443 size: 0,
444 kind: SymbolKind::File,
445 scope: SymbolScope::Compilation,
446 weak: false,
447 section: SymbolSection::None,
448 flags: SymbolFlags::None,
449 })
450 }
451
452 pub fn section_symbol(&mut self, section_id: SectionId) -> SymbolId {
454 let section = &mut self.sections[section_id.0];
455 if let Some(symbol) = section.symbol {
456 return symbol;
457 }
458 let name = if self.format == BinaryFormat::Coff {
459 section.name.clone()
460 } else {
461 Vec::new()
462 };
463 let symbol_id = SymbolId(self.symbols.len());
464 self.symbols.push(Symbol {
465 name,
466 value: 0,
467 size: 0,
468 kind: SymbolKind::Section,
469 scope: SymbolScope::Compilation,
470 weak: false,
471 section: SymbolSection::Section(section_id),
472 flags: SymbolFlags::None,
473 });
474 section.symbol = Some(symbol_id);
475 symbol_id
476 }
477
478 pub fn add_symbol_data(
491 &mut self,
492 symbol_id: SymbolId,
493 section: SectionId,
494 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut data: &[u8],
495 align: u64,
496 ) -> u64 {
497 #[cfg(feature = "macho")]
498 if data.is_empty() && self.macho_subsections_via_symbols {
499 data = &[0];
500 }
501 let offset = self.append_section_data(section, data, align);
502 self.set_symbol_data(symbol_id, section, offset, data.len() as u64);
503 offset
504 }
505
506 pub fn add_symbol_bss(
519 &mut self,
520 symbol_id: SymbolId,
521 section: SectionId,
522 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut size: u64,
523 align: u64,
524 ) -> u64 {
525 #[cfg(feature = "macho")]
526 if size == 0 && self.macho_subsections_via_symbols {
527 size = 1;
528 }
529 let offset = self.append_section_bss(section, size, align);
530 self.set_symbol_data(symbol_id, section, offset, size);
531 offset
532 }
533
534 #[allow(unused_mut)]
539 pub fn set_symbol_data(
540 &mut self,
541 mut symbol_id: SymbolId,
542 section: SectionId,
543 offset: u64,
544 size: u64,
545 ) {
546 debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown);
548 match self.format {
549 #[cfg(feature = "macho")]
550 BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id),
551 _ => {}
552 }
553 let symbol = self.symbol_mut(symbol_id);
554 symbol.value = offset;
555 symbol.size = size;
556 symbol.section = SymbolSection::Section(section);
557 }
558
559 pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> {
563 let symbol = self.symbol(symbol_id);
564 if symbol.kind == SymbolKind::Section {
565 return Some((symbol_id, 0));
566 }
567 let symbol_offset = symbol.value;
568 let section = symbol.section.id()?;
569 let section_symbol = self.section_symbol(section);
570 Some((section_symbol, symbol_offset))
571 }
572
573 pub fn add_relocation(&mut self, section: SectionId, mut relocation: Relocation) -> Result<()> {
578 match self.format {
579 #[cfg(feature = "coff")]
580 BinaryFormat::Coff => self.coff_translate_relocation(&mut relocation)?,
581 #[cfg(feature = "elf")]
582 BinaryFormat::Elf => self.elf_translate_relocation(&mut relocation)?,
583 #[cfg(feature = "macho")]
584 BinaryFormat::MachO => self.macho_translate_relocation(&mut relocation)?,
585 #[cfg(feature = "xcoff")]
586 BinaryFormat::Xcoff => self.xcoff_translate_relocation(&mut relocation)?,
587 _ => unimplemented!(),
588 }
589 let implicit = match self.format {
590 #[cfg(feature = "coff")]
591 BinaryFormat::Coff => self.coff_adjust_addend(&mut relocation)?,
592 #[cfg(feature = "elf")]
593 BinaryFormat::Elf => self.elf_adjust_addend(&mut relocation)?,
594 #[cfg(feature = "macho")]
595 BinaryFormat::MachO => self.macho_adjust_addend(&mut relocation)?,
596 #[cfg(feature = "xcoff")]
597 BinaryFormat::Xcoff => self.xcoff_adjust_addend(&mut relocation)?,
598 _ => unimplemented!(),
599 };
600 if implicit && relocation.addend != 0 {
601 self.write_relocation_addend(section, &relocation)?;
602 relocation.addend = 0;
603 }
604 self.sections[section.0].relocations.push(relocation);
605 Ok(())
606 }
607
608 fn write_relocation_addend(
609 &mut self,
610 section: SectionId,
611 relocation: &Relocation,
612 ) -> Result<()> {
613 let size = match self.format {
614 #[cfg(feature = "coff")]
615 BinaryFormat::Coff => self.coff_relocation_size(relocation)?,
616 #[cfg(feature = "elf")]
617 BinaryFormat::Elf => self.elf_relocation_size(relocation)?,
618 #[cfg(feature = "macho")]
619 BinaryFormat::MachO => self.macho_relocation_size(relocation)?,
620 #[cfg(feature = "xcoff")]
621 BinaryFormat::Xcoff => self.xcoff_relocation_size(relocation)?,
622 _ => unimplemented!(),
623 };
624 let data = self.sections[section.0].data_mut();
625 let offset = relocation.offset as usize;
626 match size {
627 32 => data.write_at(offset, &U32::new(self.endian, relocation.addend as u32)),
628 64 => data.write_at(offset, &U64::new(self.endian, relocation.addend as u64)),
629 _ => {
630 return Err(Error(format!(
631 "unimplemented relocation addend {:?}",
632 relocation
633 )));
634 }
635 }
636 .map_err(|_| {
637 Error(format!(
638 "invalid relocation offset {}+{} (max {})",
639 relocation.offset,
640 size,
641 data.len()
642 ))
643 })
644 }
645
646 pub fn write(&self) -> Result<Vec<u8>> {
648 let mut buffer = Vec::new();
649 self.emit(&mut buffer)?;
650 Ok(buffer)
651 }
652
653 #[cfg(feature = "std")]
660 pub fn write_stream<W: io::Write>(&self, w: W) -> result::Result<(), Box<dyn error::Error>> {
661 let mut stream = StreamingBuffer::new(w);
662 self.emit(&mut stream)?;
663 stream.result()?;
664 stream.into_inner().flush()?;
665 Ok(())
666 }
667
668 pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
670 match self.format {
671 #[cfg(feature = "coff")]
672 BinaryFormat::Coff => self.coff_write(buffer),
673 #[cfg(feature = "elf")]
674 BinaryFormat::Elf => self.elf_write(buffer),
675 #[cfg(feature = "macho")]
676 BinaryFormat::MachO => self.macho_write(buffer),
677 #[cfg(feature = "xcoff")]
678 BinaryFormat::Xcoff => self.xcoff_write(buffer),
679 _ => unimplemented!(),
680 }
681 }
682}
683
684#[allow(missing_docs)]
686#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
687#[non_exhaustive]
688pub enum StandardSegment {
689 Text,
690 Data,
691 Debug,
692}
693
694#[allow(missing_docs)]
696#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
697#[non_exhaustive]
698pub enum StandardSection {
699 Text,
700 Data,
701 ReadOnlyData,
702 ReadOnlyDataWithRel,
703 ReadOnlyString,
704 UninitializedData,
705 Tls,
706 UninitializedTls,
708 TlsVariables,
710 Common,
712 GnuProperty,
714}
715
716impl StandardSection {
717 pub fn kind(self) -> SectionKind {
719 match self {
720 StandardSection::Text => SectionKind::Text,
721 StandardSection::Data => SectionKind::Data,
722 StandardSection::ReadOnlyData => SectionKind::ReadOnlyData,
723 StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel,
724 StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
725 StandardSection::UninitializedData => SectionKind::UninitializedData,
726 StandardSection::Tls => SectionKind::Tls,
727 StandardSection::UninitializedTls => SectionKind::UninitializedTls,
728 StandardSection::TlsVariables => SectionKind::TlsVariables,
729 StandardSection::Common => SectionKind::Common,
730 StandardSection::GnuProperty => SectionKind::Note,
731 }
732 }
733
734 fn all() -> &'static [StandardSection] {
736 &[
737 StandardSection::Text,
738 StandardSection::Data,
739 StandardSection::ReadOnlyData,
740 StandardSection::ReadOnlyDataWithRel,
741 StandardSection::ReadOnlyString,
742 StandardSection::UninitializedData,
743 StandardSection::Tls,
744 StandardSection::UninitializedTls,
745 StandardSection::TlsVariables,
746 StandardSection::Common,
747 StandardSection::GnuProperty,
748 ]
749 }
750}
751
752#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
754pub struct SectionId(usize);
755
756#[derive(Debug)]
758pub struct Section<'a> {
759 segment: Vec<u8>,
760 name: Vec<u8>,
761 kind: SectionKind,
762 size: u64,
763 align: u64,
764 data: Cow<'a, [u8]>,
765 relocations: Vec<Relocation>,
766 symbol: Option<SymbolId>,
767 pub flags: SectionFlags,
769}
770
771impl<'a> Section<'a> {
772 #[inline]
774 pub fn name(&self) -> Option<&str> {
775 str::from_utf8(&self.name).ok()
776 }
777
778 #[inline]
780 pub fn segment(&self) -> Option<&str> {
781 str::from_utf8(&self.segment).ok()
782 }
783
784 #[inline]
786 pub fn is_bss(&self) -> bool {
787 self.kind.is_bss()
788 }
789
790 pub fn set_data<T>(&mut self, data: T, align: u64)
795 where
796 T: Into<Cow<'a, [u8]>>,
797 {
798 debug_assert!(!self.is_bss());
799 debug_assert_eq!(align & (align - 1), 0);
800 debug_assert!(self.data.is_empty());
801 self.data = data.into();
802 self.size = self.data.len() as u64;
803 self.align = align;
804 }
805
806 pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 {
811 debug_assert!(!self.is_bss());
812 debug_assert_eq!(align & (align - 1), 0);
813 if self.align < align {
814 self.align = align;
815 }
816 let align = align as usize;
817 let data = self.data.to_mut();
818 let mut offset = data.len();
819 if offset & (align - 1) != 0 {
820 offset += align - (offset & (align - 1));
821 data.resize(offset, 0);
822 }
823 data.extend_from_slice(append_data);
824 self.size = data.len() as u64;
825 offset as u64
826 }
827
828 pub fn append_bss(&mut self, size: u64, align: u64) -> u64 {
833 debug_assert!(self.is_bss());
834 debug_assert_eq!(align & (align - 1), 0);
835 if self.align < align {
836 self.align = align;
837 }
838 let mut offset = self.size;
839 if offset & (align - 1) != 0 {
840 offset += align - (offset & (align - 1));
841 self.size = offset;
842 }
843 self.size += size;
844 offset
845 }
846
847 pub fn data(&self) -> &[u8] {
851 debug_assert!(!self.is_bss());
852 &self.data
853 }
854
855 pub fn data_mut(&mut self) -> &mut [u8] {
859 debug_assert!(!self.is_bss());
860 self.data.to_mut()
861 }
862}
863
864#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
866#[non_exhaustive]
867pub enum SymbolSection {
868 None,
870 Undefined,
872 Absolute,
874 Common,
876 Section(SectionId),
878}
879
880impl SymbolSection {
881 #[inline]
885 pub fn id(self) -> Option<SectionId> {
886 if let SymbolSection::Section(id) = self {
887 Some(id)
888 } else {
889 None
890 }
891 }
892}
893
894#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
896pub struct SymbolId(usize);
897
898#[derive(Debug)]
900pub struct Symbol {
901 pub name: Vec<u8>,
903 pub value: u64,
907 pub size: u64,
909 pub kind: SymbolKind,
911 pub scope: SymbolScope,
913 pub weak: bool,
915 pub section: SymbolSection,
917 pub flags: SymbolFlags<SectionId, SymbolId>,
919}
920
921impl Symbol {
922 #[inline]
924 pub fn name(&self) -> Option<&str> {
925 str::from_utf8(&self.name).ok()
926 }
927
928 #[inline]
930 pub fn is_undefined(&self) -> bool {
931 self.section == SymbolSection::Undefined
932 }
933
934 #[inline]
938 pub fn is_common(&self) -> bool {
939 self.section == SymbolSection::Common
940 }
941
942 #[inline]
944 pub fn is_local(&self) -> bool {
945 self.scope == SymbolScope::Compilation
946 }
947}
948
949#[derive(Debug)]
951pub struct Relocation {
952 pub offset: u64,
954 pub symbol: SymbolId,
958 pub addend: i64,
962 pub flags: RelocationFlags,
964}
965
966#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
968pub struct ComdatId(usize);
969
970#[derive(Debug)]
972pub struct Comdat {
973 pub kind: ComdatKind,
978 pub symbol: SymbolId,
983 pub sections: Vec<SectionId>,
985}
986
987#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
989#[non_exhaustive]
990pub enum Mangling {
991 None,
993 Coff,
995 CoffI386,
997 Elf,
999 MachO,
1001 Xcoff,
1003}
1004
1005impl Mangling {
1006 pub fn default(format: BinaryFormat, architecture: Architecture) -> Self {
1008 match (format, architecture) {
1009 (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386,
1010 (BinaryFormat::Coff, _) => Mangling::Coff,
1011 (BinaryFormat::Elf, _) => Mangling::Elf,
1012 (BinaryFormat::MachO, _) => Mangling::MachO,
1013 (BinaryFormat::Xcoff, _) => Mangling::Xcoff,
1014 _ => Mangling::None,
1015 }
1016 }
1017
1018 pub fn global_prefix(self) -> Option<u8> {
1020 match self {
1021 Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None,
1022 Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
1023 }
1024 }
1025}