object/
common.rs

1/// A CPU architecture.
2#[allow(missing_docs)]
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
4#[non_exhaustive]
5pub enum Architecture {
6    Unknown,
7    Aarch64,
8    #[allow(non_camel_case_types)]
9    Aarch64_Ilp32,
10    Arm,
11    Avr,
12    Bpf,
13    Csky,
14    E2K32,
15    E2K64,
16    I386,
17    X86_64,
18    #[allow(non_camel_case_types)]
19    X86_64_X32,
20    Hexagon,
21    LoongArch64,
22    M68k,
23    Mips,
24    Mips64,
25    #[allow(non_camel_case_types)]
26    Mips64_N32,
27    Msp430,
28    PowerPc,
29    PowerPc64,
30    Riscv32,
31    Riscv64,
32    S390x,
33    Sbf,
34    Sharc,
35    Sparc,
36    Sparc32Plus,
37    Sparc64,
38    Wasm32,
39    Wasm64,
40    Xtensa,
41}
42
43/// A CPU sub-architecture.
44#[allow(missing_docs)]
45#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
46#[non_exhaustive]
47pub enum SubArchitecture {
48    Arm64E,
49    Arm64EC,
50}
51
52impl Architecture {
53    /// The size of an address value for this architecture.
54    ///
55    /// Returns `None` for unknown architectures.
56    pub fn address_size(self) -> Option<AddressSize> {
57        match self {
58            Architecture::Unknown => None,
59            Architecture::Aarch64 => Some(AddressSize::U64),
60            Architecture::Aarch64_Ilp32 => Some(AddressSize::U32),
61            Architecture::Arm => Some(AddressSize::U32),
62            Architecture::Avr => Some(AddressSize::U8),
63            Architecture::Bpf => Some(AddressSize::U64),
64            Architecture::Csky => Some(AddressSize::U32),
65            Architecture::E2K32 => Some(AddressSize::U32),
66            Architecture::E2K64 => Some(AddressSize::U64),
67            Architecture::I386 => Some(AddressSize::U32),
68            Architecture::X86_64 => Some(AddressSize::U64),
69            Architecture::X86_64_X32 => Some(AddressSize::U32),
70            Architecture::Hexagon => Some(AddressSize::U32),
71            Architecture::LoongArch64 => Some(AddressSize::U64),
72            Architecture::M68k => Some(AddressSize::U32),
73            Architecture::Mips => Some(AddressSize::U32),
74            Architecture::Mips64 => Some(AddressSize::U64),
75            Architecture::Mips64_N32 => Some(AddressSize::U32),
76            Architecture::Msp430 => Some(AddressSize::U16),
77            Architecture::PowerPc => Some(AddressSize::U32),
78            Architecture::PowerPc64 => Some(AddressSize::U64),
79            Architecture::Riscv32 => Some(AddressSize::U32),
80            Architecture::Riscv64 => Some(AddressSize::U64),
81            Architecture::S390x => Some(AddressSize::U64),
82            Architecture::Sbf => Some(AddressSize::U64),
83            Architecture::Sharc => Some(AddressSize::U32),
84            Architecture::Sparc => Some(AddressSize::U32),
85            Architecture::Sparc32Plus => Some(AddressSize::U32),
86            Architecture::Sparc64 => Some(AddressSize::U64),
87            Architecture::Wasm32 => Some(AddressSize::U32),
88            Architecture::Wasm64 => Some(AddressSize::U64),
89            Architecture::Xtensa => Some(AddressSize::U32),
90        }
91    }
92}
93
94/// The size of an address value for an architecture.
95///
96/// This may differ from the address size supported by the file format (such as for COFF).
97#[allow(missing_docs)]
98#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
99#[non_exhaustive]
100#[repr(u8)]
101pub enum AddressSize {
102    U8 = 1,
103    U16 = 2,
104    U32 = 4,
105    U64 = 8,
106}
107
108impl AddressSize {
109    /// The size in bytes of an address value.
110    #[inline]
111    pub fn bytes(self) -> u8 {
112        self as u8
113    }
114}
115
116/// A binary file format.
117#[allow(missing_docs)]
118#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
119#[non_exhaustive]
120pub enum BinaryFormat {
121    Coff,
122    Elf,
123    MachO,
124    Pe,
125    Wasm,
126    Xcoff,
127}
128
129impl BinaryFormat {
130    /// The target's native binary format for relocatable object files.
131    ///
132    /// Defaults to `Elf` for unknown platforms.
133    pub fn native_object() -> BinaryFormat {
134        if cfg!(target_os = "windows") {
135            BinaryFormat::Coff
136        } else if cfg!(target_os = "macos") {
137            BinaryFormat::MachO
138        } else {
139            BinaryFormat::Elf
140        }
141    }
142}
143
144/// The kind of a section.
145#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
146#[non_exhaustive]
147pub enum SectionKind {
148    /// The section kind is unknown.
149    Unknown,
150    /// An executable code section.
151    ///
152    /// Example ELF sections: `.text`
153    ///
154    /// Example Mach-O sections: `__TEXT/__text`
155    Text,
156    /// A data section.
157    ///
158    /// Example ELF sections: `.data`
159    ///
160    /// Example Mach-O sections: `__DATA/__data`
161    Data,
162    /// A read only data section.
163    ///
164    /// Example ELF sections: `.rodata`
165    ///
166    /// Example Mach-O sections: `__TEXT/__const`, `__DATA/__const`, `__TEXT/__literal4`
167    ReadOnlyData,
168    /// A read only data section with relocations.
169    ///
170    /// This is the same as either `Data` or `ReadOnlyData`, depending on the file format.
171    /// This value is only used in the API for writing files. It is never returned when reading files.
172    ReadOnlyDataWithRel,
173    /// A loadable string section.
174    ///
175    /// Example ELF sections: `.rodata.str`
176    ///
177    /// Example Mach-O sections: `__TEXT/__cstring`
178    ReadOnlyString,
179    /// An uninitialized data section.
180    ///
181    /// Example ELF sections: `.bss`
182    ///
183    /// Example Mach-O sections: `__DATA/__bss`
184    UninitializedData,
185    /// An uninitialized common data section.
186    ///
187    /// Example Mach-O sections: `__DATA/__common`
188    Common,
189    /// A TLS data section.
190    ///
191    /// Example ELF sections: `.tdata`
192    ///
193    /// Example Mach-O sections: `__DATA/__thread_data`
194    Tls,
195    /// An uninitialized TLS data section.
196    ///
197    /// Example ELF sections: `.tbss`
198    ///
199    /// Example Mach-O sections: `__DATA/__thread_bss`
200    UninitializedTls,
201    /// A TLS variables section.
202    ///
203    /// This contains TLS variable structures, rather than the variable initializers.
204    ///
205    /// Example Mach-O sections: `__DATA/__thread_vars`
206    TlsVariables,
207    /// A non-loadable string section.
208    ///
209    /// Example ELF sections: `.comment`, `.debug_str`
210    OtherString,
211    /// Some other non-loadable section.
212    ///
213    /// Example ELF sections: `.debug_info`
214    Other,
215    /// Debug information.
216    ///
217    /// Example Mach-O sections: `__DWARF/__debug_info`
218    Debug,
219    /// Debug strings.
220    ///
221    /// This is the same as either `Debug` or `OtherString`, depending on the file format.
222    /// This value is only used in the API for writing files. It is never returned when reading files.
223    DebugString,
224    /// Information for the linker.
225    ///
226    /// Example COFF sections: `.drectve`
227    Linker,
228    /// ELF note section.
229    Note,
230    /// Metadata such as symbols or relocations.
231    ///
232    /// Example ELF sections: `.symtab`, `.strtab`, `.group`
233    Metadata,
234    /// Some other ELF section type.
235    ///
236    /// This is the `sh_type` field in the section header.
237    /// The meaning may be dependent on the architecture.
238    Elf(u32),
239}
240
241impl SectionKind {
242    /// Return true if this section contains zerofill data.
243    pub fn is_bss(self) -> bool {
244        self == SectionKind::UninitializedData
245            || self == SectionKind::UninitializedTls
246            || self == SectionKind::Common
247    }
248}
249
250/// The selection kind for a COMDAT section group.
251///
252/// This determines the way in which the linker resolves multiple definitions of the COMDAT
253/// sections.
254#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
255#[non_exhaustive]
256pub enum ComdatKind {
257    /// The selection kind is unknown.
258    Unknown,
259    /// Multiple definitions are allowed.
260    ///
261    /// An arbitrary definition is selected, and the rest are removed.
262    ///
263    /// This is the only supported selection kind for ELF.
264    Any,
265    /// Multiple definitions are not allowed.
266    ///
267    /// This is used to group sections without allowing duplicates.
268    NoDuplicates,
269    /// Multiple definitions must have the same size.
270    ///
271    /// An arbitrary definition is selected, and the rest are removed.
272    SameSize,
273    /// Multiple definitions must match exactly.
274    ///
275    /// An arbitrary definition is selected, and the rest are removed.
276    ExactMatch,
277    /// Multiple definitions are allowed, and the largest is selected.
278    ///
279    /// An arbitrary definition with the largest size is selected, and the rest are removed.
280    Largest,
281    /// Multiple definitions are allowed, and the newest is selected.
282    Newest,
283}
284
285/// The kind of a symbol.
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
287#[non_exhaustive]
288pub enum SymbolKind {
289    /// The symbol kind is unknown.
290    Unknown,
291    /// The symbol is for executable code.
292    Text,
293    /// The symbol is for a data object.
294    Data,
295    /// The symbol is for a section.
296    Section,
297    /// The symbol is the name of a file. It precedes symbols within that file.
298    File,
299    /// The symbol is for a code label.
300    Label,
301    /// The symbol is for a thread local storage entity.
302    Tls,
303}
304
305/// A symbol scope.
306#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
307pub enum SymbolScope {
308    /// Unknown scope.
309    Unknown,
310    /// Symbol is visible to the compilation unit.
311    Compilation,
312    /// Symbol is visible to the static linkage unit.
313    Linkage,
314    /// Symbol is visible to dynamically linked objects.
315    Dynamic,
316}
317
318/// The operation used to calculate the result of the relocation.
319///
320/// The relocation descriptions use the following definitions. Note that
321/// these definitions probably don't match any ELF ABI.
322///
323/// * A - The value of the addend.
324/// * G - The address of the symbol's entry within the global offset table.
325/// * L - The address of the symbol's entry within the procedure linkage table.
326/// * P - The address of the place of the relocation.
327/// * S - The address of the symbol.
328/// * GotBase - The address of the global offset table.
329/// * Image - The base address of the image.
330/// * Section - The address of the section containing the symbol.
331///
332/// 'XxxRelative' means 'Xxx + A - P'.  'XxxOffset' means 'S + A - Xxx'.
333#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
334#[non_exhaustive]
335pub enum RelocationKind {
336    /// The operation is unknown.
337    Unknown,
338    /// S + A
339    Absolute,
340    /// S + A - P
341    Relative,
342    /// G + A - GotBase
343    Got,
344    /// G + A - P
345    GotRelative,
346    /// GotBase + A - P
347    GotBaseRelative,
348    /// S + A - GotBase
349    GotBaseOffset,
350    /// L + A - P
351    PltRelative,
352    /// S + A - Image
353    ImageOffset,
354    /// S + A - Section
355    SectionOffset,
356    /// The index of the section containing the symbol.
357    SectionIndex,
358}
359
360/// Information about how the result of the relocation operation is encoded in the place.
361///
362/// This is usually architecture specific, such as specifying an addressing mode or
363/// a specific instruction.
364#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
365#[non_exhaustive]
366pub enum RelocationEncoding {
367    /// The relocation encoding is unknown.
368    Unknown,
369    /// Generic encoding.
370    Generic,
371
372    /// x86 sign extension at runtime.
373    ///
374    /// Used with `RelocationKind::Absolute`.
375    X86Signed,
376    /// x86 rip-relative addressing.
377    ///
378    /// The `RelocationKind` must be PC relative.
379    X86RipRelative,
380    /// x86 rip-relative addressing in movq instruction.
381    ///
382    /// The `RelocationKind` must be PC relative.
383    X86RipRelativeMovq,
384    /// x86 branch instruction.
385    ///
386    /// The `RelocationKind` must be PC relative.
387    X86Branch,
388
389    /// s390x PC-relative offset shifted right by one bit.
390    ///
391    /// The `RelocationKind` must be PC relative.
392    S390xDbl,
393
394    /// AArch64 call target.
395    ///
396    /// The `RelocationKind` must be PC relative.
397    AArch64Call,
398
399    /// LoongArch branch offset with two trailing zeros.
400    ///
401    /// The `RelocationKind` must be PC relative.
402    LoongArchBranch,
403
404    /// SHARC+ 48-bit Type A instruction
405    ///
406    /// Represents these possible variants, each with a corresponding
407    /// `R_SHARC_*` constant:
408    ///
409    /// * 24-bit absolute address
410    /// * 32-bit absolute address
411    /// * 6-bit relative address
412    /// * 24-bit relative address
413    /// * 6-bit absolute address in the immediate value field
414    /// * 16-bit absolute address in the immediate value field
415    SharcTypeA,
416
417    /// SHARC+ 32-bit Type B instruction
418    ///
419    /// Represents these possible variants, each with a corresponding
420    /// `R_SHARC_*` constant:
421    ///
422    /// * 6-bit absolute address in the immediate value field
423    /// * 7-bit absolute address in the immediate value field
424    /// * 16-bit absolute address
425    /// * 6-bit relative address
426    SharcTypeB,
427
428    /// E2K 64-bit value stored in two LTS
429    ///
430    /// Memory representation:
431    /// ```text
432    /// 0: LTS1 = value[63:32]
433    /// 4: LTS0 = value[31:0]
434    /// ```
435    E2KLit,
436
437    /// E2K 28-bit value stored in CS0
438    E2KDisp,
439}
440
441/// File flags that are specific to each file format.
442#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
443#[non_exhaustive]
444pub enum FileFlags {
445    /// No file flags.
446    None,
447    /// ELF file flags.
448    Elf {
449        /// `os_abi` field in the ELF file header.
450        os_abi: u8,
451        /// `abi_version` field in the ELF file header.
452        abi_version: u8,
453        /// `e_flags` field in the ELF file header.
454        e_flags: u32,
455    },
456    /// Mach-O file flags.
457    MachO {
458        /// `flags` field in the Mach-O file header.
459        flags: u32,
460    },
461    /// COFF file flags.
462    Coff {
463        /// `Characteristics` field in the COFF file header.
464        characteristics: u16,
465    },
466    /// XCOFF file flags.
467    Xcoff {
468        /// `f_flags` field in the XCOFF file header.
469        f_flags: u16,
470    },
471}
472
473/// Segment flags that are specific to each file format.
474#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
475#[non_exhaustive]
476pub enum SegmentFlags {
477    /// No segment flags.
478    None,
479    /// ELF segment flags.
480    Elf {
481        /// `p_flags` field in the segment header.
482        p_flags: u32,
483    },
484    /// Mach-O segment flags.
485    MachO {
486        /// `flags` field in the segment header.
487        flags: u32,
488        /// `maxprot` field in the segment header.
489        maxprot: u32,
490        /// `initprot` field in the segment header.
491        initprot: u32,
492    },
493    /// COFF segment flags.
494    Coff {
495        /// `Characteristics` field in the segment header.
496        characteristics: u32,
497    },
498}
499
500/// Section flags that are specific to each file format.
501#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
502#[non_exhaustive]
503pub enum SectionFlags {
504    /// No section flags.
505    None,
506    /// ELF section flags.
507    Elf {
508        /// `sh_flags` field in the section header.
509        sh_flags: u64,
510    },
511    /// Mach-O section flags.
512    MachO {
513        /// `flags` field in the section header.
514        flags: u32,
515    },
516    /// COFF section flags.
517    Coff {
518        /// `Characteristics` field in the section header.
519        characteristics: u32,
520    },
521    /// XCOFF section flags.
522    Xcoff {
523        /// `s_flags` field in the section header.
524        s_flags: u32,
525    },
526}
527
528/// Symbol flags that are specific to each file format.
529#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
530#[non_exhaustive]
531pub enum SymbolFlags<Section, Symbol> {
532    /// No symbol flags.
533    None,
534    /// ELF symbol flags.
535    Elf {
536        /// `st_info` field in the ELF symbol.
537        st_info: u8,
538        /// `st_other` field in the ELF symbol.
539        st_other: u8,
540    },
541    /// Mach-O symbol flags.
542    MachO {
543        /// `n_desc` field in the Mach-O symbol.
544        n_desc: u16,
545    },
546    /// COFF flags for a section symbol.
547    CoffSection {
548        /// `Selection` field in the auxiliary symbol for the section.
549        selection: u8,
550        /// `Number` field in the auxiliary symbol for the section.
551        associative_section: Option<Section>,
552    },
553    /// XCOFF symbol flags.
554    Xcoff {
555        /// `n_sclass` field in the XCOFF symbol.
556        n_sclass: u8,
557        /// `x_smtyp` field in the CSECT auxiliary symbol.
558        ///
559        /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`.
560        x_smtyp: u8,
561        /// `x_smclas` field in the CSECT auxiliary symbol.
562        ///
563        /// Only valid if `n_sclass` is `C_EXT`, `C_WEAKEXT`, or `C_HIDEXT`.
564        x_smclas: u8,
565        /// The containing csect for the symbol.
566        ///
567        /// Only valid if `x_smtyp` is `XTY_LD`.
568        containing_csect: Option<Symbol>,
569    },
570}
571
572/// Relocation fields that are specific to each file format and architecture.
573#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
574#[non_exhaustive]
575pub enum RelocationFlags {
576    /// Format independent representation.
577    Generic {
578        /// The operation used to calculate the result of the relocation.
579        kind: RelocationKind,
580        /// Information about how the result of the relocation operation is encoded in the place.
581        encoding: RelocationEncoding,
582        /// The size in bits of the place of relocation.
583        size: u8,
584    },
585    /// ELF relocation fields.
586    Elf {
587        /// `r_type` field in the ELF relocation.
588        r_type: u32,
589    },
590    /// Mach-O relocation fields.
591    MachO {
592        /// `r_type` field in the Mach-O relocation.
593        r_type: u8,
594        /// `r_pcrel` field in the Mach-O relocation.
595        r_pcrel: bool,
596        /// `r_length` field in the Mach-O relocation.
597        r_length: u8,
598    },
599    /// COFF relocation fields.
600    Coff {
601        /// `typ` field in the COFF relocation.
602        typ: u16,
603    },
604    /// XCOFF relocation fields.
605    Xcoff {
606        /// `r_rtype` field in the XCOFF relocation.
607        r_rtype: u8,
608        /// `r_rsize` field in the XCOFF relocation.
609        r_rsize: u8,
610    },
611}