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 pub fn default_section_flags(&self, section: &Section<'_>) -> SectionFlags {
346 match self.format {
347 #[cfg(feature = "coff")]
348 BinaryFormat::Coff => self.coff_section_flags(section),
349 #[cfg(feature = "elf")]
350 BinaryFormat::Elf => self.elf_section_flags(section),
351 #[cfg(feature = "macho")]
352 BinaryFormat::MachO => self.macho_section_flags(section),
353 #[cfg(feature = "xcoff")]
354 BinaryFormat::Xcoff => self.xcoff_section_flags(section),
355 _ => SectionFlags::None,
356 }
357 }
358
359 pub fn section_flags(&self, section: &Section<'_>) -> SectionFlags {
365 if section.flags != SectionFlags::None {
366 section.flags
367 } else {
368 self.default_section_flags(section)
369 }
370 }
371
372 pub fn section_flags_mut(&mut self, section_id: SectionId) -> &mut SectionFlags {
378 if self.section(section_id).flags != SectionFlags::None {
379 &mut self.section_mut(section_id).flags
380 } else {
381 let flags = self.default_section_flags(self.section(section_id));
382 let section = self.section_mut(section_id);
383 section.flags = flags;
384 &mut section.flags
385 }
386 }
387
388 #[inline]
390 pub fn comdat(&self, comdat: ComdatId) -> &Comdat {
391 &self.comdats[comdat.0]
392 }
393
394 #[inline]
396 pub fn comdat_mut(&mut self, comdat: ComdatId) -> &mut Comdat {
397 &mut self.comdats[comdat.0]
398 }
399
400 pub fn add_comdat(&mut self, comdat: Comdat) -> ComdatId {
402 let comdat_id = ComdatId(self.comdats.len());
403 self.comdats.push(comdat);
404 comdat_id
405 }
406
407 pub fn symbol_id(&self, name: &[u8]) -> Option<SymbolId> {
409 self.symbol_map.get(name).cloned()
410 }
411
412 #[inline]
414 pub fn symbol(&self, symbol: SymbolId) -> &Symbol {
415 &self.symbols[symbol.0]
416 }
417
418 #[inline]
420 pub fn symbol_mut(&mut self, symbol: SymbolId) -> &mut Symbol {
421 &mut self.symbols[symbol.0]
422 }
423
424 pub fn add_symbol(&mut self, mut symbol: Symbol) -> SymbolId {
433 debug_assert!(symbol.is_undefined() || symbol.scope != SymbolScope::Unknown);
435 if symbol.kind == SymbolKind::Section {
436 let symbol_id = self.section_symbol(symbol.section.id().unwrap());
439 if symbol.flags != SymbolFlags::None {
440 self.symbol_mut(symbol_id).flags = symbol.flags;
441 }
442 return symbol_id;
443 }
444 if !symbol.name.is_empty()
445 && (symbol.kind == SymbolKind::Text
446 || symbol.kind == SymbolKind::Data
447 || symbol.kind == SymbolKind::Tls)
448 {
449 let unmangled_name = symbol.name.clone();
450 if let Some(prefix) = self.mangling.global_prefix() {
451 symbol.name.insert(0, prefix);
452 }
453 let symbol_id = self.add_raw_symbol(symbol);
454 self.symbol_map.insert(unmangled_name, symbol_id);
455 symbol_id
456 } else {
457 self.add_raw_symbol(symbol)
458 }
459 }
460
461 fn add_raw_symbol(&mut self, symbol: Symbol) -> SymbolId {
462 let symbol_id = SymbolId(self.symbols.len());
463 self.symbols.push(symbol);
464 symbol_id
465 }
466
467 pub fn default_symbol_flags(&self, symbol: &Symbol) -> SymbolFlags<SectionId, SymbolId> {
478 match self.format {
479 #[cfg(feature = "coff")]
480 BinaryFormat::Coff => self.coff_symbol_flags(symbol),
481 #[cfg(feature = "elf")]
482 BinaryFormat::Elf => self.elf_symbol_flags(symbol),
483 #[cfg(feature = "macho")]
484 BinaryFormat::MachO => self.macho_symbol_flags(symbol),
485 #[cfg(feature = "xcoff")]
486 BinaryFormat::Xcoff => self.xcoff_symbol_flags(symbol),
487 _ => SymbolFlags::None,
488 }
489 }
490
491 pub fn symbol_flags(&self, symbol: &Symbol) -> SymbolFlags<SectionId, SymbolId> {
497 if symbol.flags != SymbolFlags::None {
498 symbol.flags
499 } else {
500 self.default_symbol_flags(symbol)
501 }
502 }
503
504 pub fn symbol_flags_mut(
510 &mut self,
511 symbol_id: SymbolId,
512 ) -> &mut SymbolFlags<SectionId, SymbolId> {
513 if self.symbol(symbol_id).flags != SymbolFlags::None {
514 &mut self.symbol_mut(symbol_id).flags
515 } else {
516 let flags = self.default_symbol_flags(self.symbol(symbol_id));
517 let symbol = self.symbol_mut(symbol_id);
518 symbol.flags = flags;
519 &mut symbol.flags
520 }
521 }
522
523 #[inline]
525 pub fn has_uninitialized_tls(&self) -> bool {
526 self.format != BinaryFormat::Coff
527 }
528
529 #[inline]
531 pub fn has_common(&self) -> bool {
532 self.format == BinaryFormat::MachO
533 }
534
535 pub fn add_common_symbol(&mut self, mut symbol: Symbol, size: u64, align: u64) -> SymbolId {
541 if self.has_common() {
542 let symbol_id = self.add_symbol(symbol);
543 let section = self.section_id(StandardSection::Common);
544 self.add_symbol_bss(symbol_id, section, size, align);
545 symbol_id
546 } else {
547 symbol.section = SymbolSection::Common;
548 symbol.size = size;
549 self.add_symbol(symbol)
550 }
551 }
552
553 pub fn add_file_symbol(&mut self, name: Vec<u8>) -> SymbolId {
555 self.add_raw_symbol(Symbol {
556 name,
557 value: 0,
558 size: 0,
559 kind: SymbolKind::File,
560 scope: SymbolScope::Compilation,
561 weak: false,
562 section: SymbolSection::None,
563 flags: SymbolFlags::None,
564 })
565 }
566
567 pub fn section_symbol(&mut self, section_id: SectionId) -> SymbolId {
569 let section = &mut self.sections[section_id.0];
570 if let Some(symbol) = section.symbol {
571 return symbol;
572 }
573 let name = if self.format == BinaryFormat::Coff {
574 section.name.clone()
575 } else {
576 Vec::new()
577 };
578 let symbol_id = SymbolId(self.symbols.len());
579 self.symbols.push(Symbol {
580 name,
581 value: 0,
582 size: 0,
583 kind: SymbolKind::Section,
584 scope: SymbolScope::Compilation,
585 weak: false,
586 section: SymbolSection::Section(section_id),
587 flags: SymbolFlags::None,
588 });
589 section.symbol = Some(symbol_id);
590 symbol_id
591 }
592
593 pub fn add_symbol_data(
606 &mut self,
607 symbol_id: SymbolId,
608 section: SectionId,
609 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut data: &[u8],
610 align: u64,
611 ) -> u64 {
612 #[cfg(feature = "macho")]
613 if data.is_empty() && self.macho_subsections_via_symbols {
614 data = &[0];
615 }
616 let offset = self.append_section_data(section, data, align);
617 self.set_symbol_data(symbol_id, section, offset, data.len() as u64);
618 offset
619 }
620
621 pub fn add_symbol_bss(
634 &mut self,
635 symbol_id: SymbolId,
636 section: SectionId,
637 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut size: u64,
638 align: u64,
639 ) -> u64 {
640 #[cfg(feature = "macho")]
641 if size == 0 && self.macho_subsections_via_symbols {
642 size = 1;
643 }
644 let offset = self.append_section_bss(section, size, align);
645 self.set_symbol_data(symbol_id, section, offset, size);
646 offset
647 }
648
649 #[allow(unused_mut)]
654 pub fn set_symbol_data(
655 &mut self,
656 mut symbol_id: SymbolId,
657 section: SectionId,
658 offset: u64,
659 size: u64,
660 ) {
661 debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown);
663 match self.format {
664 #[cfg(feature = "macho")]
665 BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id),
666 _ => {}
667 }
668 let symbol = self.symbol_mut(symbol_id);
669 symbol.value = offset;
670 symbol.size = size;
671 symbol.section = SymbolSection::Section(section);
672 }
673
674 pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> {
678 let symbol = self.symbol(symbol_id);
679 if symbol.kind == SymbolKind::Section {
680 return Some((symbol_id, 0));
681 }
682 let symbol_offset = symbol.value;
683 let section = symbol.section.id()?;
684 let section_symbol = self.section_symbol(section);
685 Some((section_symbol, symbol_offset))
686 }
687
688 pub fn add_relocation(&mut self, section: SectionId, mut relocation: Relocation) -> Result<()> {
693 match self.format {
694 #[cfg(feature = "coff")]
695 BinaryFormat::Coff => self.coff_translate_relocation(&mut relocation)?,
696 #[cfg(feature = "elf")]
697 BinaryFormat::Elf => self.elf_translate_relocation(&mut relocation)?,
698 #[cfg(feature = "macho")]
699 BinaryFormat::MachO => self.macho_translate_relocation(&mut relocation)?,
700 #[cfg(feature = "xcoff")]
701 BinaryFormat::Xcoff => self.xcoff_translate_relocation(&mut relocation)?,
702 _ => unimplemented!(),
703 }
704 let implicit = match self.format {
705 #[cfg(feature = "coff")]
706 BinaryFormat::Coff => self.coff_adjust_addend(&mut relocation)?,
707 #[cfg(feature = "elf")]
708 BinaryFormat::Elf => self.elf_adjust_addend(&mut relocation)?,
709 #[cfg(feature = "macho")]
710 BinaryFormat::MachO => self.macho_adjust_addend(&mut relocation)?,
711 #[cfg(feature = "xcoff")]
712 BinaryFormat::Xcoff => self.xcoff_adjust_addend(&mut relocation)?,
713 _ => unimplemented!(),
714 };
715 if implicit && relocation.addend != 0 {
716 self.write_relocation_addend(section, &relocation)?;
717 relocation.addend = 0;
718 }
719 self.sections[section.0].relocations.push(relocation);
720 Ok(())
721 }
722
723 fn write_relocation_addend(
724 &mut self,
725 section: SectionId,
726 relocation: &Relocation,
727 ) -> Result<()> {
728 let size = match self.format {
729 #[cfg(feature = "coff")]
730 BinaryFormat::Coff => self.coff_relocation_size(relocation)?,
731 #[cfg(feature = "elf")]
732 BinaryFormat::Elf => self.elf_relocation_size(relocation)?,
733 #[cfg(feature = "macho")]
734 BinaryFormat::MachO => self.macho_relocation_size(relocation)?,
735 #[cfg(feature = "xcoff")]
736 BinaryFormat::Xcoff => self.xcoff_relocation_size(relocation)?,
737 _ => unimplemented!(),
738 };
739 let data = self.sections[section.0].data_mut();
740 let offset = relocation.offset as usize;
741 match size {
742 32 => data.write_at(offset, &U32::new(self.endian, relocation.addend as u32)),
743 64 => data.write_at(offset, &U64::new(self.endian, relocation.addend as u64)),
744 _ => {
745 return Err(Error(format!(
746 "unimplemented relocation addend {:?}",
747 relocation
748 )));
749 }
750 }
751 .map_err(|_| {
752 Error(format!(
753 "invalid relocation offset {}+{} (max {})",
754 relocation.offset,
755 size,
756 data.len()
757 ))
758 })
759 }
760
761 pub fn write(&self) -> Result<Vec<u8>> {
763 let mut buffer = Vec::new();
764 self.emit(&mut buffer)?;
765 Ok(buffer)
766 }
767
768 #[cfg(feature = "std")]
775 pub fn write_stream<W: io::Write>(&self, w: W) -> result::Result<(), Box<dyn error::Error>> {
776 let mut stream = StreamingBuffer::new(w);
777 self.emit(&mut stream)?;
778 stream.result()?;
779 stream.into_inner().flush()?;
780 Ok(())
781 }
782
783 pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
785 match self.format {
786 #[cfg(feature = "coff")]
787 BinaryFormat::Coff => self.coff_write(buffer),
788 #[cfg(feature = "elf")]
789 BinaryFormat::Elf => self.elf_write(buffer),
790 #[cfg(feature = "macho")]
791 BinaryFormat::MachO => self.macho_write(buffer),
792 #[cfg(feature = "xcoff")]
793 BinaryFormat::Xcoff => self.xcoff_write(buffer),
794 _ => unimplemented!(),
795 }
796 }
797}
798
799#[allow(missing_docs)]
801#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
802#[non_exhaustive]
803pub enum StandardSegment {
804 Text,
805 Data,
806 Debug,
807}
808
809#[allow(missing_docs)]
811#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
812#[non_exhaustive]
813pub enum StandardSection {
814 Text,
815 Data,
816 ReadOnlyData,
817 ReadOnlyDataWithRel,
818 ReadOnlyString,
819 UninitializedData,
820 Tls,
821 UninitializedTls,
823 TlsVariables,
825 Common,
827 GnuProperty,
829}
830
831impl StandardSection {
832 pub fn kind(self) -> SectionKind {
834 match self {
835 StandardSection::Text => SectionKind::Text,
836 StandardSection::Data => SectionKind::Data,
837 StandardSection::ReadOnlyData => SectionKind::ReadOnlyData,
838 StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel,
839 StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
840 StandardSection::UninitializedData => SectionKind::UninitializedData,
841 StandardSection::Tls => SectionKind::Tls,
842 StandardSection::UninitializedTls => SectionKind::UninitializedTls,
843 StandardSection::TlsVariables => SectionKind::TlsVariables,
844 StandardSection::Common => SectionKind::Common,
845 StandardSection::GnuProperty => SectionKind::Note,
846 }
847 }
848
849 fn all() -> &'static [StandardSection] {
851 &[
852 StandardSection::Text,
853 StandardSection::Data,
854 StandardSection::ReadOnlyData,
855 StandardSection::ReadOnlyDataWithRel,
856 StandardSection::ReadOnlyString,
857 StandardSection::UninitializedData,
858 StandardSection::Tls,
859 StandardSection::UninitializedTls,
860 StandardSection::TlsVariables,
861 StandardSection::Common,
862 StandardSection::GnuProperty,
863 ]
864 }
865}
866
867#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
869pub struct SectionId(usize);
870
871#[derive(Debug)]
873pub struct Section<'a> {
874 segment: Vec<u8>,
875 name: Vec<u8>,
876 kind: SectionKind,
877 size: u64,
878 align: u64,
879 data: Cow<'a, [u8]>,
880 relocations: Vec<Relocation>,
881 symbol: Option<SymbolId>,
882 pub flags: SectionFlags,
884}
885
886impl<'a> Section<'a> {
887 #[inline]
889 pub fn name(&self) -> Option<&str> {
890 str::from_utf8(&self.name).ok()
891 }
892
893 #[inline]
895 pub fn segment(&self) -> Option<&str> {
896 str::from_utf8(&self.segment).ok()
897 }
898
899 #[inline]
901 pub fn is_bss(&self) -> bool {
902 self.kind.is_bss()
903 }
904
905 pub fn set_data<T>(&mut self, data: T, align: u64)
910 where
911 T: Into<Cow<'a, [u8]>>,
912 {
913 debug_assert!(!self.is_bss());
914 debug_assert_eq!(align & (align - 1), 0);
915 debug_assert!(self.data.is_empty());
916 self.data = data.into();
917 self.size = self.data.len() as u64;
918 self.align = align;
919 }
920
921 pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 {
926 debug_assert!(!self.is_bss());
927 debug_assert_eq!(align & (align - 1), 0);
928 if self.align < align {
929 self.align = align;
930 }
931 let align = align as usize;
932 let data = self.data.to_mut();
933 let mut offset = data.len();
934 if offset & (align - 1) != 0 {
935 offset += align - (offset & (align - 1));
936 data.resize(offset, 0);
937 }
938 data.extend_from_slice(append_data);
939 self.size = data.len() as u64;
940 offset as u64
941 }
942
943 pub fn append_bss(&mut self, size: u64, align: u64) -> u64 {
948 debug_assert!(self.is_bss());
949 debug_assert_eq!(align & (align - 1), 0);
950 if self.align < align {
951 self.align = align;
952 }
953 let mut offset = self.size;
954 if offset & (align - 1) != 0 {
955 offset += align - (offset & (align - 1));
956 self.size = offset;
957 }
958 self.size += size;
959 offset
960 }
961
962 pub fn data(&self) -> &[u8] {
966 debug_assert!(!self.is_bss());
967 &self.data
968 }
969
970 pub fn data_mut(&mut self) -> &mut [u8] {
974 debug_assert!(!self.is_bss());
975 self.data.to_mut()
976 }
977}
978
979#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
981#[non_exhaustive]
982pub enum SymbolSection {
983 None,
985 Undefined,
987 Absolute,
989 Common,
991 Section(SectionId),
993}
994
995impl SymbolSection {
996 #[inline]
1000 pub fn id(self) -> Option<SectionId> {
1001 if let SymbolSection::Section(id) = self {
1002 Some(id)
1003 } else {
1004 None
1005 }
1006 }
1007}
1008
1009#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1011pub struct SymbolId(usize);
1012
1013#[derive(Debug)]
1015pub struct Symbol {
1016 pub name: Vec<u8>,
1018 pub value: u64,
1022 pub size: u64,
1024 pub kind: SymbolKind,
1026 pub scope: SymbolScope,
1028 pub weak: bool,
1030 pub section: SymbolSection,
1032 pub flags: SymbolFlags<SectionId, SymbolId>,
1034}
1035
1036impl Symbol {
1037 #[inline]
1039 pub fn name(&self) -> Option<&str> {
1040 str::from_utf8(&self.name).ok()
1041 }
1042
1043 #[inline]
1045 pub fn is_undefined(&self) -> bool {
1046 self.section == SymbolSection::Undefined
1047 }
1048
1049 #[inline]
1053 pub fn is_common(&self) -> bool {
1054 self.section == SymbolSection::Common
1055 }
1056
1057 #[inline]
1059 pub fn is_local(&self) -> bool {
1060 self.scope == SymbolScope::Compilation
1061 }
1062}
1063
1064#[derive(Debug)]
1066pub struct Relocation {
1067 pub offset: u64,
1069 pub symbol: SymbolId,
1073 pub addend: i64,
1077 pub flags: RelocationFlags,
1079}
1080
1081#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1083pub struct ComdatId(usize);
1084
1085#[derive(Debug)]
1087pub struct Comdat {
1088 pub kind: ComdatKind,
1093 pub symbol: SymbolId,
1098 pub sections: Vec<SectionId>,
1100}
1101
1102#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1104#[non_exhaustive]
1105pub enum Mangling {
1106 None,
1108 Coff,
1110 CoffI386,
1112 Elf,
1114 MachO,
1116 Xcoff,
1118}
1119
1120impl Mangling {
1121 pub fn default(format: BinaryFormat, architecture: Architecture) -> Self {
1123 match (format, architecture) {
1124 (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386,
1125 (BinaryFormat::Coff, _) => Mangling::Coff,
1126 (BinaryFormat::Elf, _) => Mangling::Elf,
1127 (BinaryFormat::MachO, _) => Mangling::MachO,
1128 (BinaryFormat::Xcoff, _) => Mangling::Xcoff,
1129 _ => Mangling::None,
1130 }
1131 }
1132
1133 pub fn global_prefix(self) -> Option<u8> {
1135 match self {
1136 Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None,
1137 Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
1138 }
1139 }
1140}