orecc_elf/
structs.rs

1use super::{Error, Result, RW};
2
3macro_rules! int_enum {
4    ($name: ident as $type: ty: $($variant: ident = $value: expr,)+) => {
5        impl $name {
6            pub(super) fn int_value(self) -> $type {
7                match self {
8                    $(Self::$variant => $value,)+
9                    Self::Custom(value) => value,
10                }
11            }
12
13            pub(super) fn from_int(value: $type) -> Self {
14                match value {
15                    $($value => Self::$variant,)+
16                    value => Self::Custom(value),
17                }
18            }
19        }
20    };
21
22    // No custom
23    (!$name: ident as $type: ty: $($variant: ident = $value: expr,)+) => {
24        impl $name {
25            pub(super) fn int_value(self) -> $type {
26                match self {
27                    $(Self::$variant => $value,)+
28                }
29            }
30
31            pub(super) fn from_int(value: $type) -> Result<Self> {
32                match value {
33                    $($value => Ok(Self::$variant),)+
34                    value => Err(Error::Error(format!("Invalid value for {}: {value}", stringify!($name)))),
35                }
36            }
37        }
38    };
39}
40
41// * ------------------------------------ Structs ----------------------------------- * //
42/// Class, stored in e_ident. ELF32/ELF64
43#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
44pub enum Class {
45    /// 32 bit ELF file. Adresses are encoded as u32
46    ELF32,
47    /// 64 bit ELF file. Adresses are encoded as u64
48    #[default]
49    ELF64,
50    /// Custom value
51    Custom(u8),
52}
53
54int_enum! {
55    Class as u8:
56    ELF32 = 1,
57    ELF64 = 2,
58}
59
60/// Byte order, stored in e_ident.
61#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
62pub enum ByteOrder {
63    /// Little Endian
64    #[default]
65    LSB,
66    /// Big endian
67    MSB,
68}
69
70int_enum! {
71    !ByteOrder as u8:
72    LSB = 1,
73    MSB = 2,
74}
75
76#[cfg(feature = "target-lexicon")]
77impl From<target_lexicon::Endianness> for ByteOrder {
78    fn from(value: target_lexicon::Endianness) -> Self {
79        match value {
80            target_lexicon::Endianness::Little => Self::LSB,
81            target_lexicon::Endianness::Big => Self::MSB,
82        }
83    }
84}
85
86/// ABI. There is planety to chose from, but you probably should just use [ABI::None]
87#[derive(Clone, Copy, Debug, Default, Hash, PartialEq, Eq, PartialOrd, Ord)]
88pub enum ABI {
89    #[default]
90    /// System V
91    None,
92    /// HP-UX
93    HPUX,
94    /// NetBSD
95    NetBSD,
96    /// Linux
97    Linux,
98    /// GNU Hurd
99    Hurd,
100    /// Solaris
101    Solaris,
102    /// AIX (Monterey)
103    AIX,
104    /// IRIX
105    IRIX,
106    /// FreeBSD
107    FreeBSD,
108    /// Tru64
109    Tru64,
110    /// Novell Modesto
111    Modesto,
112    /// OpenBSD
113    OpenBSD,
114    /// OpenVMS
115    OpenVMS,
116    /// NonStop Kernel
117    NSK,
118    /// AROS
119    AROS,
120    /// FenixOS
121    FenixOS,
122    /// Nuxi CloudABI
123    CloudABI,
124    /// Stratus Technologies OpenVOS
125    OpenVOS,
126    /// Custom value
127    Custom(u8),
128}
129
130int_enum! {
131    ABI as u8:
132    None = 0x00,
133    HPUX = 0x01,
134    NetBSD = 0x02,
135    Linux = 0x03,
136    Hurd = 0x04,
137    Solaris = 0x06,
138    AIX = 0x07,
139    IRIX = 0x08,
140    FreeBSD = 0x09,
141    Tru64 = 0x0A,
142    Modesto = 0x0B,
143    OpenBSD = 0x0C,
144    OpenVMS = 0x0D,
145    NSK = 0x0E,
146    AROS = 0x0F,
147    FenixOS = 0x10,
148    CloudABI = 0x11,
149    OpenVOS = 0x12,
150}
151
152#[cfg(feature = "target-lexicon")]
153impl From<target_lexicon::OperatingSystem> for ABI {
154    fn from(value: target_lexicon::OperatingSystem) -> Self {
155        match value {
156            target_lexicon::OperatingSystem::Unknown => Self::None,
157            target_lexicon::OperatingSystem::Aix => Self::AIX,
158            target_lexicon::OperatingSystem::Cloudabi => Self::CloudABI,
159            target_lexicon::OperatingSystem::Freebsd => Self::FreeBSD,
160            target_lexicon::OperatingSystem::Linux => Self::Linux,
161            target_lexicon::OperatingSystem::Netbsd => Self::NetBSD,
162            target_lexicon::OperatingSystem::None_ => Self::None,
163            target_lexicon::OperatingSystem::Openbsd => Self::OpenBSD,
164            target_lexicon::OperatingSystem::Solaris => Self::Solaris,
165            _ => Self::None,
166        }
167    }
168}
169
170/// Type of the ELF.
171#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
172pub enum Type {
173    /// Relocatable file
174    Rel,
175    /// Executable file
176    Exec,
177    /// Shared object
178    Dyn,
179    /// Core file
180    Core,
181    /// Custom value
182    Custom(u16),
183}
184
185int_enum! {
186    Type as u16:
187    Rel = 1,
188    Exec = 2,
189    Dyn = 3,
190    Core = 4,
191}
192
193/// Machine. There is A LOT of them. Most common are [Machine::X86], [Machine::X86_64], [Machine::ARM] and [Machine::ARM64]
194#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
195pub enum Machine {
196    /// No specific instruction set
197    None,
198    /// AT&T WE 32100
199    M32,
200    /// SPARC
201    SPARC,
202    /// x86, Intel 80386
203    X86,
204    /// Motorola 68000 (M68k)
205    M68k,
206    /// Motorola 88000 (M88k)
207    M88k,
208    /// Intel MCU
209    IntelMCU,
210    /// Intel 80860
211    Intel80860,
212    /// MIPS
213    MIPS,
214    /// IBM System/370
215    S370,
216    /// MIPS RS3000 Little-endian
217    MipsRS3LE,
218    /// Hewlett-Packard PA-RISC
219    PARISC,
220    /// Intel 80960
221    Intel80960,
222    /// PowerPC
223    PowerPC,
224    /// PowerPC (64-bit)
225    PowerPC64,
226    /// S390, including S390x
227    S390,
228    /// IBM SPU/SPC
229    SPU,
230    /// NEC V800
231    V800,
232    /// Fujitsu FR20
233    FR20,
234    /// TRW RH-32
235    RH32,
236    /// Motorola RCE
237    RCE,
238    /// Arm (up to Armv7/AArch32)
239    ARM,
240    /// Digital Alpha
241    DigitalAlpha,
242    /// SuperH
243    SuperH,
244    /// SPARC Version 9
245    SPARC9,
246    /// Siemens TriCore embedded processor
247    TriCore,
248    /// Argonaut RISC Core
249    ARC,
250    /// Hitachi H8/300
251    H8_300,
252    /// Hitachi H8/300H
253    H8_300H,
254    /// Hitachi H8S
255    H8S,
256    /// Hitachi H8/500
257    H8_500,
258    /// IA-64
259    IA64,
260    /// Stanford MIPS-X
261    MipsX,
262    /// Motorola ColdFire
263    ColdFire,
264    /// Motorola M68HC12
265    M68HC12,
266    /// Fujitsu MMA Multimedia Accelerator
267    MMA,
268    /// Siemens PCP
269    PCP,
270    /// Sony nCPU embedded RISC processor
271    NCPU,
272    /// Denso NDR1 microprocessor
273    NDR1,
274    /// Motorola Star*Core processor
275    StarCore,
276    /// Toyota ME16 processor
277    ME16,
278    /// STMicroelectronics ST100 processor
279    ST100,
280    /// Advanced Logic Corp. TinyJ embedded processor family
281    TinyJ,
282    /// AMD x86-64
283    X86_64,
284    /// Sony DSP Processor
285    SonyDSP,
286    /// Digital Equipment Corp. PDP-10
287    PDP10,
288    /// Digital Equipment Corp. PDP-11
289    PDP11,
290    /// Siemens FX66 microcontroller
291    FX66,
292    /// STMicroelectronics ST9+ 8/16 bit microcontroller
293    ST9,
294    /// STMicroelectronics ST7 8-bit microcontroller
295    ST7,
296    /// Motorola MC68HC16 Microcontroller
297    MC68HC16,
298    /// Motorola MC68HC11 Microcontroller
299    MC68HC11,
300    /// Motorola MC68HC08 Microcontroller
301    MC68HC08,
302    /// Motorola MC68HC05 Microcontroller
303    MC68HC05,
304    /// Silicon Graphics SVx
305    SVx,
306    /// STMicroelectronics ST19 8-bit microcontroller
307    ST19,
308    /// Digital VAX
309    DigitalVAX,
310    /// Axis Communications 32-bit embedded processor
311    AxisCommunications,
312    /// Infineon Technologies 32-bit embedded processor
313    InfineonTechnologies,
314    /// Element 14 64-bit DSP Processor
315    Element14,
316    /// LSI Logic 16-bit DSP Processor
317    LSILogic,
318    /// TMS320C6000 Family
319    TMS320C6000,
320    /// MCST Elbrus e2k
321    MCSTElbrusE2k,
322    /// Arm 64-bits (Armv8/AArch64)
323    ARM64,
324    /// Zilog Z80
325    Z80,
326    /// RISC-V
327    RISCV,
328    /// Berkeley Packet Filter
329    BerkeleyPacketFilter,
330    /// WDC 65C816
331    WDC65C816,
332    /// Custom value
333    Custom(u16),
334}
335
336int_enum! {
337    Machine as u16:
338    None = 0x00,
339    M32 = 0x01,
340    SPARC = 0x02,
341    X86 = 0x03,
342    M68k = 0x04,
343    M88k = 0x05,
344    IntelMCU = 0x06,
345    Intel80860 = 0x07,
346    MIPS = 0x08,
347    S370 = 0x09,
348    MipsRS3LE = 0x0A,
349    PARISC = 0x0F,
350    Intel80960 = 0x13,
351    PowerPC = 0x14,
352    PowerPC64 = 0x15,
353    S390 = 0x16,
354    SPU = 0x17,
355    V800 = 0x24,
356    FR20 = 0x25,
357    RH32 = 0x26,
358    RCE = 0x27,
359    ARM = 0x28,
360    DigitalAlpha = 0x29,
361    SuperH = 0x2A,
362    SPARC9 = 0x2B,
363    TriCore = 0x2C,
364    ARC = 0x2D,
365    H8_300 = 0x2E,
366    H8_300H = 0x2F,
367    H8S = 0x30,
368    H8_500 = 0x31,
369    IA64 = 0x32,
370    MipsX = 0x33,
371    ColdFire = 0x34,
372    M68HC12 = 0x35,
373    MMA = 0x36,
374    PCP = 0x37,
375    NCPU = 0x38,
376    NDR1 = 0x39,
377    StarCore = 0x3A,
378    ME16 = 0x3B,
379    ST100 = 0x3C,
380    TinyJ = 0x3D,
381    X86_64 = 0x3E,
382    SonyDSP = 0x3F,
383    PDP10 = 0x40,
384    PDP11 = 0x41,
385    FX66 = 0x42,
386    ST9 = 0x43,
387    ST7 = 0x44,
388    MC68HC16 = 0x45,
389    MC68HC11 = 0x46,
390    MC68HC08 = 0x47,
391    MC68HC05 = 0x48,
392    SVx = 0x49,
393    ST19 = 0x4A,
394    DigitalVAX = 0x4B,
395    AxisCommunications = 0x4C,
396    InfineonTechnologies = 0x4D,
397    Element14 = 0x4E,
398    LSILogic = 0x4F,
399    TMS320C6000 = 0x8C,
400    MCSTElbrusE2k = 0xAF,
401    ARM64 = 0xB7,
402    Z80 = 0xDC,
403    RISCV = 0xF3,
404    BerkeleyPacketFilter = 0xF7,
405    WDC65C816 = 0x101,
406}
407
408#[cfg(feature = "target-lexicon")]
409impl From<target_lexicon::Architecture> for Machine {
410    fn from(value: target_lexicon::Architecture) -> Self {
411        match value {
412            target_lexicon::Architecture::Unknown => Self::None,
413            target_lexicon::Architecture::Arm(_) => Self::ARM,
414            target_lexicon::Architecture::Aarch64(_) => Self::ARM64,
415            target_lexicon::Architecture::X86_32(_) => Self::X86,
416            target_lexicon::Architecture::M68k => Self::M68k,
417            target_lexicon::Architecture::Mips32(_) => Self::MIPS,
418            target_lexicon::Architecture::Mips64(_) => Self::MIPS,
419            target_lexicon::Architecture::Powerpc => Self::PowerPC,
420            target_lexicon::Architecture::Powerpc64 => Self::PowerPC64,
421            target_lexicon::Architecture::Powerpc64le => Self::PowerPC64,
422            target_lexicon::Architecture::Riscv32(_) => Self::RISCV,
423            target_lexicon::Architecture::Riscv64(_) => Self::RISCV,
424            target_lexicon::Architecture::S390x => Self::S390,
425            target_lexicon::Architecture::Sparc => Self::SPARC,
426            target_lexicon::Architecture::Sparc64 => Self::SPARC9,
427            target_lexicon::Architecture::Sparcv9 => Self::SPARC9,
428            target_lexicon::Architecture::X86_64 => Self::X86_64,
429            target_lexicon::Architecture::X86_64h => Self::X86_64,
430            _ => todo!(),
431        }
432    }
433}
434
435/// ELF is supposed to be 32/64. This is a trait to specify this. It's implemented for [u32] and [u64].
436pub trait SizeT: Sized + RW {
437    fn new(value: u64) -> Self;
438    fn value(&self) -> u64;
439    const CLASS: Class;
440    const ELF_HEADER_SIZE: u16;
441    const SEGMENT_HEADER_SIZE: u16;
442    const SECTION_HEADER_SIZE: u16;
443    const MOVE_PFLAGS: bool;
444}
445
446// * Segment
447
448/// p_type. A segment type (type of a program header). Most segments will probably have type [SegmentType::Load]
449#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
450pub enum SegmentType {
451    /// Program header table entry unused.
452    None,
453    /// Loadable segment.
454    Load,
455    /// Dynamic linking information.
456    Dynamic,
457    /// Interpreter information.
458    Interpreter,
459    /// Auxiliary information.
460    Note,
461    /// Reserved.
462    ShLib,
463    /// Segment containing program header table itself.
464    Phdr,
465    /// Thread-Local Storage template.
466    Tls,
467    /// Custom value
468    Custom(u32),
469}
470
471int_enum! {
472    SegmentType as u32:
473    None = 0x00,
474    Load = 0x01,
475    Dynamic = 0x02,
476    Interpreter = 0x03,
477    Note = 0x04,
478    ShLib = 0x05,
479    Phdr = 0x06,
480    Tls = 0x07,
481}
482
483/// p_flags. Essentially permissions. See [`Segment::flags`] for details
484#[repr(u32)]
485#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
486pub enum SegmentFlags {
487    ///  Executable segment
488    Executable = 0x01,
489    ///  Writeable segment
490    Writeable = 0x02,
491    ///  Readable segment
492    Readable = 0x04,
493}