1 //! Interface for writing object files.
3 use alloc
::borrow
::Cow
;
4 use alloc
::string
::String
;
6 use core
::{fmt, result, str}
;
7 #[cfg(not(feature = "std"))]
8 use hashbrown
::HashMap
;
9 #[cfg(feature = "std")]
10 use std
::{boxed::Box, collections::HashMap, error, io}
;
12 use crate::endian
::{Endianness, U32, U64}
;
14 Architecture
, BinaryFormat
, ComdatKind
, FileFlags
, RelocationEncoding
, RelocationKind
,
15 SectionFlags
, SectionKind
, SymbolFlags
, SymbolKind
, SymbolScope
,
18 #[cfg(feature = "coff")]
20 #[cfg(feature = "coff")]
21 pub use coff
::CoffExportStyle
;
23 #[cfg(feature = "elf")]
26 #[cfg(feature = "macho")]
28 #[cfg(feature = "macho")]
29 pub use macho
::MachOBuildVersion
;
31 #[cfg(feature = "pe")]
34 #[cfg(feature = "xcoff")]
38 pub use string
::StringId
;
43 /// The error type used within the write module.
44 #[derive(Debug, Clone, PartialEq, Eq)]
45 pub struct Error(String
);
47 impl fmt
::Display
for Error
{
49 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
54 #[cfg(feature = "std")]
55 impl error
::Error
for Error {}
57 /// The result type used within the write module.
58 pub type Result
<T
> = result
::Result
<T
, Error
>;
60 /// A writable relocatable object file.
62 pub struct Object
<'a
> {
64 architecture
: Architecture
,
66 sections
: Vec
<Section
<'a
>>,
67 standard_sections
: HashMap
<StandardSection
, SectionId
>,
69 symbol_map
: HashMap
<Vec
<u8>, SymbolId
>,
70 stub_symbols
: HashMap
<SymbolId
, SymbolId
>,
72 /// File flags that are specific to each file format.
74 /// The symbol name mangling scheme.
75 pub mangling
: Mangling
,
76 /// Mach-O "_tlv_bootstrap" symbol.
77 tlv_bootstrap
: Option
<SymbolId
>,
78 /// Mach-O CPU subtype.
79 #[cfg(feature = "macho")]
80 macho_cpu_subtype
: Option
<u32>,
81 #[cfg(feature = "macho")]
82 macho_build_version
: Option
<MachOBuildVersion
>,
86 /// Create an empty object file.
87 pub fn new(format
: BinaryFormat
, architecture
: Architecture
, endian
: Endianness
) -> Object
<'a
> {
93 standard_sections
: HashMap
::new(),
95 symbol_map
: HashMap
::new(),
96 stub_symbols
: HashMap
::new(),
98 flags
: FileFlags
::None
,
99 mangling
: Mangling
::default(format
, architecture
),
101 #[cfg(feature = "macho")]
102 macho_cpu_subtype
: None
,
103 #[cfg(feature = "macho")]
104 macho_build_version
: None
,
108 /// Return the file format.
110 pub fn format(&self) -> BinaryFormat
{
114 /// Return the architecture.
116 pub fn architecture(&self) -> Architecture
{
120 /// Return the current mangling setting.
122 pub fn mangling(&self) -> Mangling
{
126 /// Specify the mangling setting.
128 pub fn set_mangling(&mut self, mangling
: Mangling
) {
129 self.mangling
= mangling
;
132 /// Return the name for a standard segment.
134 /// This will vary based on the file format.
135 #[allow(unused_variables)]
136 pub fn segment_name(&self, segment
: StandardSegment
) -> &'
static [u8] {
138 #[cfg(feature = "coff")]
139 BinaryFormat
::Coff
=> &[],
140 #[cfg(feature = "elf")]
141 BinaryFormat
::Elf
=> &[],
142 #[cfg(feature = "macho")]
143 BinaryFormat
::MachO
=> self.macho_segment_name(segment
),
144 _
=> unimplemented
!(),
148 /// Get the section with the given `SectionId`.
150 pub fn section(&self, section
: SectionId
) -> &Section
<'a
> {
151 &self.sections
[section
.0]
154 /// Mutably get the section with the given `SectionId`.
156 pub fn section_mut(&mut self, section
: SectionId
) -> &mut Section
<'a
> {
157 &mut self.sections
[section
.0]
160 /// Set the data for an existing section.
162 /// Must not be called for sections that already have data, or that contain uninitialized data.
163 pub fn set_section_data
<T
>(&mut self, section
: SectionId
, data
: T
, align
: u64)
165 T
: Into
<Cow
<'a
, [u8]>>,
167 self.sections
[section
.0].set_data(data
, align
)
170 /// Append data to an existing section. Returns the section offset of the data.
171 pub fn append_section_data(&mut self, section
: SectionId
, data
: &[u8], align
: u64) -> u64 {
172 self.sections
[section
.0].append_data(data
, align
)
175 /// Append zero-initialized data to an existing section. Returns the section offset of the data.
176 pub fn append_section_bss(&mut self, section
: SectionId
, size
: u64, align
: u64) -> u64 {
177 self.sections
[section
.0].append_bss(size
, align
)
180 /// Return the `SectionId` of a standard section.
182 /// If the section doesn't already exist then it is created.
183 pub fn section_id(&mut self, section
: StandardSection
) -> SectionId
{
184 self.standard_sections
188 let (segment
, name
, kind
, flags
) = self.section_info(section
);
189 let id
= self.add_section(segment
.to_vec(), name
.to_vec(), kind
);
190 self.section_mut(id
).flags
= flags
;
195 /// Add a new section and return its `SectionId`.
197 /// This also creates a section symbol.
198 pub fn add_section(&mut self, segment
: Vec
<u8>, name
: Vec
<u8>, kind
: SectionKind
) -> SectionId
{
199 let id
= SectionId(self.sections
.len());
200 self.sections
.push(Section
{
206 data
: Cow
::Borrowed(&[]),
207 relocations
: Vec
::new(),
209 flags
: SectionFlags
::None
,
212 // Add to self.standard_sections if required. This may match multiple standard sections.
213 let section
= &self.sections
[id
.0];
214 for standard_section
in StandardSection
::all() {
215 if !self.standard_sections
.contains_key(standard_section
) {
216 let (segment
, name
, kind
, _flags
) = self.section_info(*standard_section
);
217 if segment
== &*section
.segment
&& name
== &*section
.name
&& kind
== section
.kind
{
218 self.standard_sections
.insert(*standard_section
, id
);
228 section
: StandardSection
,
229 ) -> (&'
static [u8], &'
static [u8], SectionKind
, SectionFlags
) {
231 #[cfg(feature = "coff")]
232 BinaryFormat
::Coff
=> self.coff_section_info(section
),
233 #[cfg(feature = "elf")]
234 BinaryFormat
::Elf
=> self.elf_section_info(section
),
235 #[cfg(feature = "macho")]
236 BinaryFormat
::MachO
=> self.macho_section_info(section
),
237 #[cfg(feature = "xcoff")]
238 BinaryFormat
::Xcoff
=> self.xcoff_section_info(section
),
239 _
=> unimplemented
!(),
243 /// Add a subsection. Returns the `SectionId` and section offset of the data.
244 pub fn add_subsection(
246 section
: StandardSection
,
250 ) -> (SectionId
, u64) {
251 let section_id
= if self.has_subsections_via_symbols() {
252 self.set_subsections_via_symbols();
253 self.section_id(section
)
255 let (segment
, name
, kind
, flags
) = self.subsection_info(section
, name
);
256 let id
= self.add_section(segment
.to_vec(), name
, kind
);
257 self.section_mut(id
).flags
= flags
;
260 let offset
= self.append_section_data(section_id
, data
, align
);
264 fn has_subsections_via_symbols(&self) -> bool
{
266 BinaryFormat
::Coff
| BinaryFormat
::Elf
| BinaryFormat
::Xcoff
=> false,
267 BinaryFormat
::MachO
=> true,
268 _
=> unimplemented
!(),
272 fn set_subsections_via_symbols(&mut self) {
274 #[cfg(feature = "macho")]
275 BinaryFormat
::MachO
=> self.macho_set_subsections_via_symbols(),
276 _
=> unimplemented
!(),
282 section
: StandardSection
,
284 ) -> (&'
static [u8], Vec
<u8>, SectionKind
, SectionFlags
) {
285 let (segment
, section
, kind
, flags
) = self.section_info(section
);
286 let name
= self.subsection_name(section
, value
);
287 (segment
, name
, kind
, flags
)
290 #[allow(unused_variables)]
291 fn subsection_name(&self, section
: &[u8], value
: &[u8]) -> Vec
<u8> {
292 debug_assert
!(!self.has_subsections_via_symbols());
294 #[cfg(feature = "coff")]
295 BinaryFormat
::Coff
=> self.coff_subsection_name(section
, value
),
296 #[cfg(feature = "elf")]
297 BinaryFormat
::Elf
=> self.elf_subsection_name(section
, value
),
298 _
=> unimplemented
!(),
302 /// Get the COMDAT section group with the given `ComdatId`.
304 pub fn comdat(&self, comdat
: ComdatId
) -> &Comdat
{
305 &self.comdats
[comdat
.0]
308 /// Mutably get the COMDAT section group with the given `ComdatId`.
310 pub fn comdat_mut(&mut self, comdat
: ComdatId
) -> &mut Comdat
{
311 &mut self.comdats
[comdat
.0]
314 /// Add a new COMDAT section group and return its `ComdatId`.
315 pub fn add_comdat(&mut self, comdat
: Comdat
) -> ComdatId
{
316 let comdat_id
= ComdatId(self.comdats
.len());
317 self.comdats
.push(comdat
);
321 /// Get the `SymbolId` of the symbol with the given name.
322 pub fn symbol_id(&self, name
: &[u8]) -> Option
<SymbolId
> {
323 self.symbol_map
.get(name
).cloned()
326 /// Get the symbol with the given `SymbolId`.
328 pub fn symbol(&self, symbol
: SymbolId
) -> &Symbol
{
329 &self.symbols
[symbol
.0]
332 /// Mutably get the symbol with the given `SymbolId`.
334 pub fn symbol_mut(&mut self, symbol
: SymbolId
) -> &mut Symbol
{
335 &mut self.symbols
[symbol
.0]
338 /// Add a new symbol and return its `SymbolId`.
339 pub fn add_symbol(&mut self, mut symbol
: Symbol
) -> SymbolId
{
340 // Defined symbols must have a scope.
341 debug_assert
!(symbol
.is_undefined() || symbol
.scope
!= SymbolScope
::Unknown
);
342 if symbol
.kind
== SymbolKind
::Section
{
343 // There can only be one section symbol, but update its flags, since
344 // the automatically generated section symbol will have none.
345 let symbol_id
= self.section_symbol(symbol
.section
.id().unwrap());
346 if symbol
.flags
!= SymbolFlags
::None
{
347 self.symbol_mut(symbol_id
).flags
= symbol
.flags
;
351 if !symbol
.name
.is_empty()
352 && (symbol
.kind
== SymbolKind
::Text
353 || symbol
.kind
== SymbolKind
::Data
354 || symbol
.kind
== SymbolKind
::Tls
)
356 let unmangled_name
= symbol
.name
.clone();
357 if let Some(prefix
) = self.mangling
.global_prefix() {
358 symbol
.name
.insert(0, prefix
);
360 let symbol_id
= self.add_raw_symbol(symbol
);
361 self.symbol_map
.insert(unmangled_name
, symbol_id
);
364 self.add_raw_symbol(symbol
)
368 fn add_raw_symbol(&mut self, symbol
: Symbol
) -> SymbolId
{
369 let symbol_id
= SymbolId(self.symbols
.len());
370 self.symbols
.push(symbol
);
374 /// Return true if the file format supports `StandardSection::UninitializedTls`.
376 pub fn has_uninitialized_tls(&self) -> bool
{
377 self.format
!= BinaryFormat
::Coff
380 /// Return true if the file format supports `StandardSection::Common`.
382 pub fn has_common(&self) -> bool
{
383 self.format
== BinaryFormat
::MachO
386 /// Add a new common symbol and return its `SymbolId`.
388 /// For Mach-O, this appends the symbol to the `__common` section.
389 pub fn add_common_symbol(&mut self, mut symbol
: Symbol
, size
: u64, align
: u64) -> SymbolId
{
390 if self.has_common() {
391 let symbol_id
= self.add_symbol(symbol
);
392 let section
= self.section_id(StandardSection
::Common
);
393 self.add_symbol_bss(symbol_id
, section
, size
, align
);
396 symbol
.section
= SymbolSection
::Common
;
398 self.add_symbol(symbol
)
402 /// Add a new file symbol and return its `SymbolId`.
403 pub fn add_file_symbol(&mut self, name
: Vec
<u8>) -> SymbolId
{
404 self.add_raw_symbol(Symbol
{
408 kind
: SymbolKind
::File
,
409 scope
: SymbolScope
::Compilation
,
411 section
: SymbolSection
::None
,
412 flags
: SymbolFlags
::None
,
416 /// Get the symbol for a section.
417 pub fn section_symbol(&mut self, section_id
: SectionId
) -> SymbolId
{
418 let section
= &mut self.sections
[section_id
.0];
419 if let Some(symbol
) = section
.symbol
{
422 let name
= if self.format
== BinaryFormat
::Coff
{
427 let symbol_id
= SymbolId(self.symbols
.len());
428 self.symbols
.push(Symbol
{
432 kind
: SymbolKind
::Section
,
433 scope
: SymbolScope
::Compilation
,
435 section
: SymbolSection
::Section(section_id
),
436 flags
: SymbolFlags
::None
,
438 section
.symbol
= Some(symbol_id
);
442 /// Append data to an existing section, and update a symbol to refer to it.
444 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
445 /// symbol will indirectly point to the added data via the `__thread_vars` entry.
447 /// Returns the section offset of the data.
448 pub fn add_symbol_data(
455 let offset
= self.append_section_data(section
, data
, align
);
456 self.set_symbol_data(symbol_id
, section
, offset
, data
.len() as u64);
460 /// Append zero-initialized data to an existing section, and update a symbol to refer to it.
462 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
463 /// symbol will indirectly point to the added data via the `__thread_vars` entry.
465 /// Returns the section offset of the data.
466 pub fn add_symbol_bss(
473 let offset
= self.append_section_bss(section
, size
, align
);
474 self.set_symbol_data(symbol_id
, section
, offset
, size
);
478 /// Update a symbol to refer to the given data within a section.
480 /// For Mach-O, this also creates a `__thread_vars` entry for TLS symbols, and the
481 /// symbol will indirectly point to the data via the `__thread_vars` entry.
483 pub fn set_symbol_data(
485 mut symbol_id
: SymbolId
,
490 // Defined symbols must have a scope.
491 debug_assert
!(self.symbol(symbol_id
).scope
!= SymbolScope
::Unknown
);
493 #[cfg(feature = "macho")]
494 BinaryFormat
::MachO
=> symbol_id
= self.macho_add_thread_var(symbol_id
),
497 let symbol
= self.symbol_mut(symbol_id
);
498 symbol
.value
= offset
;
500 symbol
.section
= SymbolSection
::Section(section
);
503 /// Convert a symbol to a section symbol and offset.
505 /// Returns `None` if the symbol does not have a section.
506 pub fn symbol_section_and_offset(&mut self, symbol_id
: SymbolId
) -> Option
<(SymbolId
, u64)> {
507 let symbol
= self.symbol(symbol_id
);
508 if symbol
.kind
== SymbolKind
::Section
{
509 return Some((symbol_id
, 0));
511 let symbol_offset
= symbol
.value
;
512 let section
= symbol
.section
.id()?
;
513 let section_symbol
= self.section_symbol(section
);
514 Some((section_symbol
, symbol_offset
))
517 /// Add a relocation to a section.
519 /// Relocations must only be added after the referenced symbols have been added
520 /// and defined (if applicable).
521 pub fn add_relocation(&mut self, section
: SectionId
, mut relocation
: Relocation
) -> Result
<()> {
522 let addend
= match self.format
{
523 #[cfg(feature = "coff")]
524 BinaryFormat
::Coff
=> self.coff_fixup_relocation(&mut relocation
),
525 #[cfg(feature = "elf")]
526 BinaryFormat
::Elf
=> self.elf_fixup_relocation(&mut relocation
)?
,
527 #[cfg(feature = "macho")]
528 BinaryFormat
::MachO
=> self.macho_fixup_relocation(&mut relocation
),
529 #[cfg(feature = "xcoff")]
530 BinaryFormat
::Xcoff
=> self.xcoff_fixup_relocation(&mut relocation
),
531 _
=> unimplemented
!(),
534 self.write_relocation_addend(section
, &relocation
, addend
)?
;
536 self.sections
[section
.0].relocations
.push(relocation
);
540 fn write_relocation_addend(
543 relocation
: &Relocation
,
546 let data
= self.sections
[section
.0].data_mut();
547 let offset
= relocation
.offset
as usize;
548 match relocation
.size
{
549 32 => data
.write_at(offset
, &U32
::new(self.endian
, addend
as u32)),
550 64 => data
.write_at(offset
, &U64
::new(self.endian
, addend
as u64)),
552 return Err(Error(format
!(
553 "unimplemented relocation addend {:?}",
560 "invalid relocation offset {}+{} (max {})",
568 /// Write the object to a `Vec`.
569 pub fn write(&self) -> Result
<Vec
<u8>> {
570 let mut buffer
= Vec
::new();
571 self.emit(&mut buffer
)?
;
575 /// Write the object to a `Write` implementation.
577 /// Also flushes the writer.
579 /// It is advisable to use a buffered writer like [`BufWriter`](std::io::BufWriter)
580 /// instead of an unbuffered writer like [`File`](std::fs::File).
581 #[cfg(feature = "std")]
582 pub fn write_stream
<W
: io
::Write
>(&self, w
: W
) -> result
::Result
<(), Box
<dyn error
::Error
>> {
583 let mut stream
= StreamingBuffer
::new(w
);
584 self.emit(&mut stream
)?
;
586 stream
.into_inner().flush()?
;
590 /// Write the object to a `WritableBuffer`.
591 pub fn emit(&self, buffer
: &mut dyn WritableBuffer
) -> Result
<()> {
593 #[cfg(feature = "coff")]
594 BinaryFormat
::Coff
=> self.coff_write(buffer
),
595 #[cfg(feature = "elf")]
596 BinaryFormat
::Elf
=> self.elf_write(buffer
),
597 #[cfg(feature = "macho")]
598 BinaryFormat
::MachO
=> self.macho_write(buffer
),
599 #[cfg(feature = "xcoff")]
600 BinaryFormat
::Xcoff
=> self.xcoff_write(buffer
),
601 _
=> unimplemented
!(),
606 /// A standard segment kind.
607 #[allow(missing_docs)]
608 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
610 pub enum StandardSegment
{
616 /// A standard section kind.
617 #[allow(missing_docs)]
618 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
620 pub enum StandardSection
{
628 /// Zero-fill TLS initializers. Unsupported for COFF.
630 /// TLS variable structures. Only supported for Mach-O.
632 /// Common data. Only supported for Mach-O.
634 /// Notes for GNU properties. Only supported for ELF.
638 impl StandardSection
{
639 /// Return the section kind of a standard section.
640 pub fn kind(self) -> SectionKind
{
642 StandardSection
::Text
=> SectionKind
::Text
,
643 StandardSection
::Data
=> SectionKind
::Data
,
644 StandardSection
::ReadOnlyData
=> SectionKind
::ReadOnlyData
,
645 StandardSection
::ReadOnlyDataWithRel
=> SectionKind
::ReadOnlyDataWithRel
,
646 StandardSection
::ReadOnlyString
=> SectionKind
::ReadOnlyString
,
647 StandardSection
::UninitializedData
=> SectionKind
::UninitializedData
,
648 StandardSection
::Tls
=> SectionKind
::Tls
,
649 StandardSection
::UninitializedTls
=> SectionKind
::UninitializedTls
,
650 StandardSection
::TlsVariables
=> SectionKind
::TlsVariables
,
651 StandardSection
::Common
=> SectionKind
::Common
,
652 StandardSection
::GnuProperty
=> SectionKind
::Note
,
656 // TODO: remembering to update this is error-prone, can we do better?
657 fn all() -> &'
static [StandardSection
] {
659 StandardSection
::Text
,
660 StandardSection
::Data
,
661 StandardSection
::ReadOnlyData
,
662 StandardSection
::ReadOnlyDataWithRel
,
663 StandardSection
::ReadOnlyString
,
664 StandardSection
::UninitializedData
,
665 StandardSection
::Tls
,
666 StandardSection
::UninitializedTls
,
667 StandardSection
::TlsVariables
,
668 StandardSection
::Common
,
669 StandardSection
::GnuProperty
,
674 /// An identifier used to reference a section.
675 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
676 pub struct SectionId(usize);
678 /// A section in an object file.
680 pub struct Section
<'a
> {
687 relocations
: Vec
<Relocation
>,
688 symbol
: Option
<SymbolId
>,
689 /// Section flags that are specific to each file format.
690 pub flags
: SectionFlags
,
693 impl<'a
> Section
<'a
> {
694 /// Try to convert the name to a utf8 string.
696 pub fn name(&self) -> Option
<&str> {
697 str::from_utf8(&self.name
).ok()
700 /// Try to convert the segment to a utf8 string.
702 pub fn segment(&self) -> Option
<&str> {
703 str::from_utf8(&self.segment
).ok()
706 /// Return true if this section contains zerofill data.
708 pub fn is_bss(&self) -> bool
{
712 /// Set the data for a section.
714 /// Must not be called for sections that already have data, or that contain uninitialized data.
715 pub fn set_data
<T
>(&mut self, data
: T
, align
: u64)
717 T
: Into
<Cow
<'a
, [u8]>>,
719 debug_assert
!(!self.is_bss());
720 debug_assert_eq
!(align
& (align
- 1), 0);
721 debug_assert
!(self.data
.is_empty());
722 self.data
= data
.into();
723 self.size
= self.data
.len() as u64;
727 /// Append data to a section.
729 /// Must not be called for sections that contain uninitialized data.
730 pub fn append_data(&mut self, append_data
: &[u8], align
: u64) -> u64 {
731 debug_assert
!(!self.is_bss());
732 debug_assert_eq
!(align
& (align
- 1), 0);
733 if self.align
< align
{
736 let align
= align
as usize;
737 let data
= self.data
.to_mut();
738 let mut offset
= data
.len();
739 if offset
& (align
- 1) != 0 {
740 offset
+= align
- (offset
& (align
- 1));
741 data
.resize(offset
, 0);
743 data
.extend_from_slice(append_data
);
744 self.size
= data
.len() as u64;
748 /// Append uninitialized data to a section.
750 /// Must not be called for sections that contain initialized data.
751 pub fn append_bss(&mut self, size
: u64, align
: u64) -> u64 {
752 debug_assert
!(self.is_bss());
753 debug_assert_eq
!(align
& (align
- 1), 0);
754 if self.align
< align
{
757 let mut offset
= self.size
;
758 if offset
& (align
- 1) != 0 {
759 offset
+= align
- (offset
& (align
- 1));
766 /// Returns the section as-built so far.
768 /// This requires that the section is not a bss section.
769 pub fn data(&self) -> &[u8] {
770 debug_assert
!(!self.is_bss());
774 /// Returns the section as-built so far.
776 /// This requires that the section is not a bss section.
777 pub fn data_mut(&mut self) -> &mut [u8] {
778 debug_assert
!(!self.is_bss());
783 /// The section where a symbol is defined.
784 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
786 pub enum SymbolSection
{
787 /// The section is not applicable for this symbol (such as file symbols).
789 /// The symbol is undefined.
791 /// The symbol has an absolute value.
793 /// The symbol is a zero-initialized symbol that will be combined with duplicate definitions.
795 /// The symbol is defined in the given section.
800 /// Returns the section id for the section where the symbol is defined.
802 /// May return `None` if the symbol is not defined in a section.
804 pub fn id(self) -> Option
<SectionId
> {
805 if let SymbolSection
::Section(id
) = self {
813 /// An identifier used to reference a symbol.
814 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
815 pub struct SymbolId(usize);
817 /// A symbol in an object file.
820 /// The name of the symbol.
822 /// The value of the symbol.
824 /// If the symbol defined in a section, then this is the section offset of the symbol.
826 /// The size of the symbol.
828 /// The kind of the symbol.
829 pub kind
: SymbolKind
,
830 /// The scope of the symbol.
831 pub scope
: SymbolScope
,
832 /// Whether the symbol has weak binding.
834 /// The section containing the symbol.
835 pub section
: SymbolSection
,
836 /// Symbol flags that are specific to each file format.
837 pub flags
: SymbolFlags
<SectionId
, SymbolId
>,
841 /// Try to convert the name to a utf8 string.
843 pub fn name(&self) -> Option
<&str> {
844 str::from_utf8(&self.name
).ok()
847 /// Return true if the symbol is undefined.
849 pub fn is_undefined(&self) -> bool
{
850 self.section
== SymbolSection
::Undefined
853 /// Return true if the symbol is common data.
855 /// Note: does not check for `SymbolSection::Section` with `SectionKind::Common`.
857 pub fn is_common(&self) -> bool
{
858 self.section
== SymbolSection
::Common
861 /// Return true if the symbol scope is local.
863 pub fn is_local(&self) -> bool
{
864 self.scope
== SymbolScope
::Compilation
868 /// A relocation in an object file.
870 pub struct Relocation
{
871 /// The section offset of the place of the relocation.
873 /// The size in bits of the place of relocation.
875 /// The operation used to calculate the result of the relocation.
876 pub kind
: RelocationKind
,
877 /// Information about how the result of the relocation operation is encoded in the place.
878 pub encoding
: RelocationEncoding
,
879 /// The symbol referred to by the relocation.
881 /// This may be a section symbol.
882 pub symbol
: SymbolId
,
883 /// The addend to use in the relocation calculation.
885 /// This may be in addition to an implicit addend stored at the place of the relocation.
889 /// An identifier used to reference a COMDAT section group.
890 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
891 pub struct ComdatId(usize);
893 /// A COMDAT section group.
896 /// The COMDAT selection kind.
898 /// This determines the way in which the linker resolves multiple definitions of the COMDAT
900 pub kind
: ComdatKind
,
901 /// The COMDAT symbol.
903 /// If this symbol is referenced, then all sections in the group will be included by the
905 pub symbol
: SymbolId
,
906 /// The sections in the group.
907 pub sections
: Vec
<SectionId
>,
910 /// The symbol name mangling scheme.
911 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
914 /// No symbol mangling.
916 /// Windows COFF symbol mangling.
918 /// Windows COFF i386 symbol mangling.
920 /// ELF symbol mangling.
922 /// Mach-O symbol mangling.
924 /// Xcoff symbol mangling.
929 /// Return the default symboling mangling for the given format and architecture.
930 pub fn default(format
: BinaryFormat
, architecture
: Architecture
) -> Self {
931 match (format
, architecture
) {
932 (BinaryFormat
::Coff
, Architecture
::I386
) => Mangling
::CoffI386
,
933 (BinaryFormat
::Coff
, _
) => Mangling
::Coff
,
934 (BinaryFormat
::Elf
, _
) => Mangling
::Elf
,
935 (BinaryFormat
::MachO
, _
) => Mangling
::MachO
,
936 (BinaryFormat
::Xcoff
, _
) => Mangling
::Xcoff
,
941 /// Return the prefix to use for global symbols.
942 pub fn global_prefix(self) -> Option
<u8> {
944 Mangling
::None
| Mangling
::Elf
| Mangling
::Coff
| Mangling
::Xcoff
=> None
,
945 Mangling
::CoffI386
| Mangling
::MachO
=> Some(b'_'
),