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