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 if self.format == BinaryFormat::MachO {
576 format!("ltmp{}", section_id.0).into_bytes()
578 } else {
579 Vec::new()
580 };
581 let symbol_id = SymbolId(self.symbols.len());
582 self.symbols.push(Symbol {
583 name,
584 value: 0,
585 size: 0,
586 kind: SymbolKind::Section,
587 scope: SymbolScope::Compilation,
588 weak: false,
589 section: SymbolSection::Section(section_id),
590 flags: SymbolFlags::None,
591 });
592 section.symbol = Some(symbol_id);
593 symbol_id
594 }
595
596 pub fn add_symbol_data(
609 &mut self,
610 symbol_id: SymbolId,
611 section: SectionId,
612 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut data: &[u8],
613 align: u64,
614 ) -> u64 {
615 #[cfg(feature = "macho")]
616 if data.is_empty() && self.macho_subsections_via_symbols {
617 data = &[0];
618 }
619 let offset = self.append_section_data(section, data, align);
620 self.set_symbol_data(symbol_id, section, offset, data.len() as u64);
621 offset
622 }
623
624 pub fn add_symbol_bss(
637 &mut self,
638 symbol_id: SymbolId,
639 section: SectionId,
640 #[cfg_attr(not(feature = "macho"), allow(unused_mut))] mut size: u64,
641 align: u64,
642 ) -> u64 {
643 #[cfg(feature = "macho")]
644 if size == 0 && self.macho_subsections_via_symbols {
645 size = 1;
646 }
647 let offset = self.append_section_bss(section, size, align);
648 self.set_symbol_data(symbol_id, section, offset, size);
649 offset
650 }
651
652 #[allow(unused_mut)]
657 pub fn set_symbol_data(
658 &mut self,
659 mut symbol_id: SymbolId,
660 section: SectionId,
661 offset: u64,
662 size: u64,
663 ) {
664 debug_assert!(self.symbol(symbol_id).scope != SymbolScope::Unknown);
666 match self.format {
667 #[cfg(feature = "macho")]
668 BinaryFormat::MachO => symbol_id = self.macho_add_thread_var(symbol_id),
669 _ => {}
670 }
671 let symbol = self.symbol_mut(symbol_id);
672 symbol.value = offset;
673 symbol.size = size;
674 symbol.section = SymbolSection::Section(section);
675 }
676
677 pub fn symbol_section_and_offset(&mut self, symbol_id: SymbolId) -> Option<(SymbolId, u64)> {
681 let symbol = self.symbol(symbol_id);
682 if symbol.kind == SymbolKind::Section {
683 return Some((symbol_id, 0));
684 }
685 let symbol_offset = symbol.value;
686 let section = symbol.section.id()?;
687 let section_symbol = self.section_symbol(section);
688 Some((section_symbol, symbol_offset))
689 }
690
691 pub fn add_relocation(&mut self, section: SectionId, relocation: Relocation) -> Result<()> {
696 self.add_relocation_internal(section, relocation.into())
697 }
698
699 pub fn add_relocation_with_subtractor(
708 &mut self,
709 section: SectionId,
710 relocation: Relocation,
711 subtractor: Option<SymbolId>,
712 ) -> Result<()> {
713 if let Some(subtractor) = subtractor {
714 if self.format != BinaryFormat::MachO {
715 return Err(Error(format!(
716 "unsupported relocation subtractor {:?} for {:?}",
717 subtractor, relocation,
718 )));
719 }
720 }
721 self.add_relocation_internal(
722 section,
723 RelocationInternal {
724 subtractor,
725 ..relocation.into()
726 },
727 )
728 }
729
730 fn add_relocation_internal(
731 &mut self,
732 section: SectionId,
733 mut relocation: RelocationInternal,
734 ) -> Result<()> {
735 match self.format {
736 #[cfg(feature = "coff")]
737 BinaryFormat::Coff => self.coff_translate_relocation(&mut relocation)?,
738 #[cfg(feature = "elf")]
739 BinaryFormat::Elf => self.elf_translate_relocation(&mut relocation)?,
740 #[cfg(feature = "macho")]
741 BinaryFormat::MachO => self.macho_translate_relocation(section, &mut relocation)?,
742 #[cfg(feature = "xcoff")]
743 BinaryFormat::Xcoff => self.xcoff_translate_relocation(&mut relocation)?,
744 _ => unimplemented!(),
745 }
746 let implicit = match self.format {
747 #[cfg(feature = "coff")]
748 BinaryFormat::Coff => self.coff_adjust_addend(&mut relocation)?,
749 #[cfg(feature = "elf")]
750 BinaryFormat::Elf => self.elf_adjust_addend(&mut relocation)?,
751 #[cfg(feature = "macho")]
752 BinaryFormat::MachO => self.macho_adjust_addend(&mut relocation)?,
753 #[cfg(feature = "xcoff")]
754 BinaryFormat::Xcoff => self.xcoff_adjust_addend(&mut relocation)?,
755 _ => unimplemented!(),
756 };
757 if implicit && relocation.addend != 0 {
758 self.write_relocation_addend(section, &relocation)?;
759 relocation.addend = 0;
760 }
761 self.sections[section.0].relocations.push(relocation);
762 Ok(())
763 }
764
765 fn write_relocation_addend(
766 &mut self,
767 section: SectionId,
768 relocation: &RelocationInternal,
769 ) -> Result<()> {
770 let size = match self.format {
771 #[cfg(feature = "coff")]
772 BinaryFormat::Coff => self.coff_relocation_size(relocation)?,
773 #[cfg(feature = "elf")]
774 BinaryFormat::Elf => self.elf_relocation_size(relocation)?,
775 #[cfg(feature = "macho")]
776 BinaryFormat::MachO => self.macho_relocation_size(relocation)?,
777 #[cfg(feature = "xcoff")]
778 BinaryFormat::Xcoff => self.xcoff_relocation_size(relocation)?,
779 _ => unimplemented!(),
780 };
781 let data = self.sections[section.0].data_mut();
782 let offset = relocation.offset as usize;
783 match size {
784 32 => data.write_at(offset, &U32::new(self.endian, relocation.addend as u32)),
785 64 => data.write_at(offset, &U64::new(self.endian, relocation.addend as u64)),
786 _ => {
787 return Err(Error(format!(
788 "unimplemented relocation addend {:?}",
789 relocation
790 )));
791 }
792 }
793 .map_err(|_| {
794 Error(format!(
795 "invalid relocation offset {}+{} (max {})",
796 relocation.offset,
797 size,
798 data.len()
799 ))
800 })
801 }
802
803 pub fn write(&self) -> Result<Vec<u8>> {
805 let mut buffer = Vec::new();
806 self.emit(&mut buffer)?;
807 Ok(buffer)
808 }
809
810 #[cfg(feature = "std")]
817 pub fn write_stream<W: io::Write>(&self, w: W) -> result::Result<(), Box<dyn error::Error>> {
818 let mut stream = StreamingBuffer::new(w);
819 self.emit(&mut stream)?;
820 stream.flush()?;
821 Ok(())
822 }
823
824 pub fn emit(&self, buffer: &mut dyn WritableBuffer) -> Result<()> {
826 match self.format {
827 #[cfg(feature = "coff")]
828 BinaryFormat::Coff => self.coff_write(buffer),
829 #[cfg(feature = "elf")]
830 BinaryFormat::Elf => self.elf_write(buffer),
831 #[cfg(feature = "macho")]
832 BinaryFormat::MachO => self.macho_write(buffer),
833 #[cfg(feature = "xcoff")]
834 BinaryFormat::Xcoff => self.xcoff_write(buffer),
835 _ => unimplemented!(),
836 }
837 }
838}
839
840#[allow(missing_docs)]
842#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
843#[non_exhaustive]
844pub enum StandardSegment {
845 Text,
846 Data,
847 Debug,
848}
849
850#[allow(missing_docs)]
852#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
853#[non_exhaustive]
854pub enum StandardSection {
855 Text,
856 Data,
857 ReadOnlyData,
858 ReadOnlyDataWithRel,
859 ReadOnlyString,
860 UninitializedData,
861 Tls,
862 UninitializedTls,
864 TlsVariables,
866 Common,
868 GnuProperty,
870 EhFrame,
871}
872
873impl StandardSection {
874 pub fn kind(self) -> SectionKind {
876 match self {
877 StandardSection::Text => SectionKind::Text,
878 StandardSection::Data => SectionKind::Data,
879 StandardSection::ReadOnlyData => SectionKind::ReadOnlyData,
880 StandardSection::ReadOnlyDataWithRel => SectionKind::ReadOnlyDataWithRel,
881 StandardSection::ReadOnlyString => SectionKind::ReadOnlyString,
882 StandardSection::UninitializedData => SectionKind::UninitializedData,
883 StandardSection::Tls => SectionKind::Tls,
884 StandardSection::UninitializedTls => SectionKind::UninitializedTls,
885 StandardSection::TlsVariables => SectionKind::TlsVariables,
886 StandardSection::Common => SectionKind::Common,
887 StandardSection::GnuProperty => SectionKind::Note,
888 StandardSection::EhFrame => SectionKind::ReadOnlyData,
889 }
890 }
891
892 fn all() -> &'static [StandardSection] {
894 &[
895 StandardSection::Text,
896 StandardSection::Data,
897 StandardSection::ReadOnlyData,
898 StandardSection::ReadOnlyDataWithRel,
899 StandardSection::ReadOnlyString,
900 StandardSection::UninitializedData,
901 StandardSection::Tls,
902 StandardSection::UninitializedTls,
903 StandardSection::TlsVariables,
904 StandardSection::Common,
905 StandardSection::GnuProperty,
906 StandardSection::EhFrame,
907 ]
908 }
909}
910
911#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
913pub struct SectionId(usize);
914
915#[derive(Debug)]
917pub struct Section<'a> {
918 segment: Vec<u8>,
919 name: Vec<u8>,
920 kind: SectionKind,
921 size: u64,
922 align: u64,
923 data: Cow<'a, [u8]>,
924 relocations: Vec<RelocationInternal>,
925 symbol: Option<SymbolId>,
926 pub flags: SectionFlags,
928}
929
930impl<'a> Section<'a> {
931 #[inline]
933 pub fn name(&self) -> Option<&str> {
934 str::from_utf8(&self.name).ok()
935 }
936
937 #[inline]
939 pub fn segment(&self) -> Option<&str> {
940 str::from_utf8(&self.segment).ok()
941 }
942
943 #[inline]
945 pub fn is_bss(&self) -> bool {
946 self.kind.is_bss()
947 }
948
949 pub fn set_data<T>(&mut self, data: T, align: u64)
954 where
955 T: Into<Cow<'a, [u8]>>,
956 {
957 debug_assert!(!self.is_bss());
958 debug_assert_eq!(align & (align - 1), 0);
959 debug_assert!(self.data.is_empty());
960 self.data = data.into();
961 self.size = self.data.len() as u64;
962 self.align = align;
963 }
964
965 pub fn append_data(&mut self, append_data: &[u8], align: u64) -> u64 {
970 debug_assert!(!self.is_bss());
971 debug_assert_eq!(align & (align - 1), 0);
972 if self.align < align {
973 self.align = align;
974 }
975 let align = align as usize;
976 let data = self.data.to_mut();
977 let mut offset = data.len();
978 if offset & (align - 1) != 0 {
979 offset += align - (offset & (align - 1));
980 data.resize(offset, 0);
981 }
982 data.extend_from_slice(append_data);
983 self.size = data.len() as u64;
984 offset as u64
985 }
986
987 pub fn append_bss(&mut self, size: u64, align: u64) -> u64 {
992 debug_assert!(self.is_bss());
993 debug_assert_eq!(align & (align - 1), 0);
994 if self.align < align {
995 self.align = align;
996 }
997 let mut offset = self.size;
998 if offset & (align - 1) != 0 {
999 offset += align - (offset & (align - 1));
1000 self.size = offset;
1001 }
1002 self.size += size;
1003 offset
1004 }
1005
1006 pub fn data(&self) -> &[u8] {
1010 debug_assert!(!self.is_bss());
1011 &self.data
1012 }
1013
1014 pub fn data_mut(&mut self) -> &mut [u8] {
1018 debug_assert!(!self.is_bss());
1019 self.data.to_mut()
1020 }
1021}
1022
1023#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1025#[non_exhaustive]
1026pub enum SymbolSection {
1027 None,
1029 Undefined,
1031 Absolute,
1033 Common,
1035 Section(SectionId),
1037}
1038
1039impl SymbolSection {
1040 #[inline]
1044 pub fn id(self) -> Option<SectionId> {
1045 if let SymbolSection::Section(id) = self {
1046 Some(id)
1047 } else {
1048 None
1049 }
1050 }
1051}
1052
1053#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1055pub struct SymbolId(usize);
1056
1057#[derive(Debug)]
1059pub struct Symbol {
1060 pub name: Vec<u8>,
1062 pub value: u64,
1066 pub size: u64,
1068 pub kind: SymbolKind,
1070 pub scope: SymbolScope,
1072 pub weak: bool,
1074 pub section: SymbolSection,
1076 pub flags: SymbolFlags<SectionId, SymbolId>,
1078}
1079
1080impl Symbol {
1081 #[inline]
1083 pub fn name(&self) -> Option<&str> {
1084 str::from_utf8(&self.name).ok()
1085 }
1086
1087 #[inline]
1089 pub fn is_undefined(&self) -> bool {
1090 self.section == SymbolSection::Undefined
1091 }
1092
1093 #[inline]
1097 pub fn is_common(&self) -> bool {
1098 self.section == SymbolSection::Common
1099 }
1100
1101 #[inline]
1103 pub fn is_local(&self) -> bool {
1104 self.scope == SymbolScope::Compilation
1105 }
1106}
1107
1108#[derive(Debug)]
1110pub struct Relocation {
1111 pub offset: u64,
1113 pub symbol: SymbolId,
1117 pub addend: i64,
1121 pub flags: RelocationFlags,
1123}
1124
1125#[derive(Debug)]
1126pub(crate) struct RelocationInternal {
1127 offset: u64,
1128 symbol: SymbolId,
1129 #[cfg_attr(not(feature = "macho"), allow(unused))]
1130 subtractor: Option<SymbolId>,
1131 addend: i64,
1132 flags: RelocationFlags,
1133}
1134
1135impl From<Relocation> for RelocationInternal {
1136 fn from(value: Relocation) -> Self {
1137 RelocationInternal {
1138 offset: value.offset,
1139 symbol: value.symbol,
1140 subtractor: None,
1141 addend: value.addend,
1142 flags: value.flags,
1143 }
1144 }
1145}
1146
1147#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
1149pub struct ComdatId(usize);
1150
1151#[derive(Debug)]
1153pub struct Comdat {
1154 pub kind: ComdatKind,
1159 pub symbol: SymbolId,
1164 pub sections: Vec<SectionId>,
1166}
1167
1168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1170#[non_exhaustive]
1171pub enum Mangling {
1172 None,
1174 Coff,
1176 CoffI386,
1178 Elf,
1180 MachO,
1182 Xcoff,
1184}
1185
1186impl Mangling {
1187 pub fn default(format: BinaryFormat, architecture: Architecture) -> Self {
1189 match (format, architecture) {
1190 (BinaryFormat::Coff, Architecture::I386) => Mangling::CoffI386,
1191 (BinaryFormat::Coff, _) => Mangling::Coff,
1192 (BinaryFormat::Elf, _) => Mangling::Elf,
1193 (BinaryFormat::MachO, _) => Mangling::MachO,
1194 (BinaryFormat::Xcoff, _) => Mangling::Xcoff,
1195 _ => Mangling::None,
1196 }
1197 }
1198
1199 pub fn global_prefix(self) -> Option<u8> {
1201 match self {
1202 Mangling::None | Mangling::Elf | Mangling::Coff | Mangling::Xcoff => None,
1203 Mangling::CoffI386 | Mangling::MachO => Some(b'_'),
1204 }
1205 }
1206}