Skip to content

Commit

Permalink
elf: add basic support for E2K arch (#727)
Browse files Browse the repository at this point in the history
  • Loading branch information
numas13 authored Sep 10, 2024
1 parent 7e292fc commit 34f6dce
Show file tree
Hide file tree
Showing 6 changed files with 206 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub enum Architecture {
Avr,
Bpf,
Csky,
E2K32,
E2K64,
I386,
X86_64,
#[allow(non_camel_case_types)]
Expand Down Expand Up @@ -57,6 +59,8 @@ impl Architecture {
Architecture::Avr => Some(AddressSize::U8),
Architecture::Bpf => Some(AddressSize::U64),
Architecture::Csky => Some(AddressSize::U32),
Architecture::E2K32 => Some(AddressSize::U32),
Architecture::E2K64 => Some(AddressSize::U64),
Architecture::I386 => Some(AddressSize::U32),
Architecture::X86_64 => Some(AddressSize::U64),
Architecture::X86_64_X32 => Some(AddressSize::U32),
Expand Down Expand Up @@ -415,6 +419,18 @@ pub enum RelocationEncoding {
/// * 16-bit absolute address
/// * 6-bit relative address
SharcTypeB,

/// E2K 64-bit value stored in two LTS
///
/// Memory representation:
/// ```text
/// 0: LTS1 = value[63:32]
/// 4: LTS0 = value[31:0]
/// ```
E2KLit,

/// E2K 28-bit value stored in CS0
E2KDisp,
}

/// File flags that are specific to each file format.
Expand Down
166 changes: 166 additions & 0 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6270,6 +6270,172 @@ pub const R_XTENSA_NDIFF8: u32 = 60;
pub const R_XTENSA_NDIFF16: u32 = 61;
pub const R_XTENSA_NDIFF32: u32 = 62;

// E2K values for `FileHeader*::e_flags`.
pub const EF_E2K_IPD: u32 = 3;
pub const EF_E2K_X86APP: u32 = 4;
pub const EF_E2K_4MB_PAGES: u32 = 8;
pub const EF_E2K_INCOMPAT: u32 = 16;
pub const EF_E2K_PM: u32 = 32;
pub const EF_E2K_PACK_SEGMENTS: u32 = 64;

/// Encode `E_E2K_MACH_*` into `FileHeader*::e_flags`.
pub const fn ef_e2k_mach_to_flag(e_flags: u32, x: u32) -> u32 {
(e_flags & 0xffffff) | (x << 24)
}

/// Decode `E_E2K_MACH_*` from `FileHeader*::e_flags`.
pub const fn ef_e2k_flag_to_mach(e_flags: u32) -> u32 {
e_flags >> 24
}

// Codes of supported E2K machines.

/// -march=generic code.
///
/// Legacy. Shouldn't be created nowadays.
pub const E_E2K_MACH_BASE: u32 = 0;
/// -march=elbrus-v1 code.
///
/// Legacy. Shouldn't be created nowadays.
pub const E_E2K_MACH_EV1: u32 = 1;
/// -march=elbrus-v2 code.
pub const E_E2K_MACH_EV2: u32 = 2;
/// -march=elbrus-v3 code.
pub const E_E2K_MACH_EV3: u32 = 3;
/// -march=elbrus-v4 code.
pub const E_E2K_MACH_EV4: u32 = 4;
/// -march=elbrus-v5 code.
pub const E_E2K_MACH_EV5: u32 = 5;
/// -march=elbrus-v6 code.
pub const E_E2K_MACH_EV6: u32 = 6;
/// -march=elbrus-v7 code.
pub const E_E2K_MACH_EV7: u32 = 7;
/// -mtune=elbrus-8c code.
pub const E_E2K_MACH_8C: u32 = 19;
/// -mtune=elbrus-1c+ code.
pub const E_E2K_MACH_1CPLUS: u32 = 20;
/// -mtune=elbrus-12c code.
pub const E_E2K_MACH_12C: u32 = 21;
/// -mtune=elbrus-16c code.
pub const E_E2K_MACH_16C: u32 = 22;
/// -mtune=elbrus-2c3 code.
pub const E_E2K_MACH_2C3: u32 = 23;
/// -mtune=elbrus-48c code.
pub const E_E2K_MACH_48C: u32 = 24;
/// -mtune=elbrus-8v7 code.
pub const E_E2K_MACH_8V7: u32 = 25;

// E2K values `Rel*::r_type`.

/// Direct 32 bit.
pub const R_E2K_32_ABS: u32 = 0;
/// PC relative 32 bit.
pub const R_E2K_32_PC: u32 = 2;
/// 32-bit offset of AP GOT entry.
pub const R_E2K_AP_GOT: u32 = 3;
/// 32-bit offset of PL GOT entry.
pub const R_E2K_PL_GOT: u32 = 4;
/// Create PLT entry.
pub const R_E2K_32_JMP_SLOT: u32 = 8;
/// Copy relocation, 32-bit case.
pub const R_E2K_32_COPY: u32 = 9;
/// Adjust by program base, 32-bit case.
pub const R_E2K_32_RELATIVE: u32 = 10;
/// Adjust indirectly by program base, 32-bit case.
pub const R_E2K_32_IRELATIVE: u32 = 11;
/// Size of symbol plus 32-bit addend.
pub const R_E2K_32_SIZE: u32 = 12;
/// Symbol value if resolved by the definition in the same
/// compilation unit or NULL otherwise, 32-bit case.
pub const R_E2K_32_DYNOPT: u32 = 13;
/// Direct 64 bit.
pub const R_E2K_64_ABS: u32 = 50;
/// Direct 64 bit for literal.
pub const R_E2K_64_ABS_LIT: u32 = 51;
/// PC relative 64 bit for literal.
pub const R_E2K_64_PC_LIT: u32 = 54;
/// Create PLT entry, 64-bit case.
pub const R_E2K_64_JMP_SLOT: u32 = 63;
/// Copy relocation, 64-bit case.
pub const R_E2K_64_COPY: u32 = 64;
/// Adjust by program base, 64-bit case.
pub const R_E2K_64_RELATIVE: u32 = 65;
/// Adjust by program base for literal, 64-bit case.
pub const R_E2K_64_RELATIVE_LIT: u32 = 66;
/// Adjust indirectly by program base, 64-bit case.
pub const R_E2K_64_IRELATIVE: u32 = 67;
/// Size of symbol plus 64-bit addend.
pub const R_E2K_64_SIZE: u32 = 68;
/// 64-bit offset of the symbol from GOT.
pub const R_E2K_64_GOTOFF: u32 = 69;

/// GOT entry for ID of module containing symbol.
pub const R_E2K_TLS_GDMOD: u32 = 70;
/// GOT entry for offset in module TLS block.
pub const R_E2K_TLS_GDREL: u32 = 71;
/// Static TLS block offset GOT entry.
pub const R_E2K_TLS_IE: u32 = 74;
/// Offset relative to static TLS block, 32-bit case.
pub const R_E2K_32_TLS_LE: u32 = 75;
/// Offset relative to static TLS block, 64-bit case.
pub const R_E2K_64_TLS_LE: u32 = 76;
/// ID of module containing symbol, 32-bit case.
pub const R_E2K_TLS_32_DTPMOD: u32 = 80;
/// Offset in module TLS block, 32-bit case.
pub const R_E2K_TLS_32_DTPREL: u32 = 81;
/// ID of module containing symbol, 64-bit case.
pub const R_E2K_TLS_64_DTPMOD: u32 = 82;
/// Offset in module TLS block, 64-bit case.
pub const R_E2K_TLS_64_DTPREL: u32 = 83;
/// Offset in static TLS block, 32-bit case.
pub const R_E2K_TLS_32_TPREL: u32 = 84;
/// Offset in static TLS block, 64-bit case.
pub const R_E2K_TLS_64_TPREL: u32 = 85;

/// Direct AP.
pub const R_E2K_AP: u32 = 100;
/// Direct PL.
pub const R_E2K_PL: u32 = 101;

/// 32-bit offset of the symbol's entry in GOT.
pub const R_E2K_GOT: u32 = 108;
/// 32-bit offset of the symbol from GOT.
pub const R_E2K_GOTOFF: u32 = 109;
/// PC relative 28 bit for DISP.
pub const R_E2K_DISP: u32 = 110;
/// Prefetch insn line containing the label (symbol).
pub const R_E2K_PREF: u32 = 111;
/// No reloc.
pub const R_E2K_NONE: u32 = 112;
/// 32-bit offset of the symbol's entry in .got.plt.
pub const R_E2K_GOTPLT: u32 = 114;
/// Is symbol resolved locally during the link.
/// The result is encoded in 5-bit ALS.src1.
pub const R_E2K_ISLOCAL: u32 = 115;
/// Is symbol resloved locally during the link.
/// The result is encoded in a long 32-bit LTS.
pub const R_E2K_ISLOCAL32: u32 = 118;
/// The symbol's offset from GOT encoded within a 64-bit literal.
pub const R_E2K_64_GOTOFF_LIT: u32 = 256;
/// Symbol value if resolved by the definition in the same
/// compilation unit or NULL otherwise, 64-bit case.
pub const R_E2K_64_DYNOPT: u32 = 257;
/// PC relative 64 bit in data.
pub const R_E2K_64_PC: u32 = 258;

// E2K values for `Dyn32::d_tag`.

pub const DT_E2K_LAZY: u32 = DT_LOPROC + 1;
pub const DT_E2K_LAZY_GOT: u32 = DT_LOPROC + 3;

pub const DT_E2K_INIT_GOT: u32 = DT_LOPROC + 0x101c;
pub const DT_E2K_EXPORT_PL: u32 = DT_LOPROC + 0x101d;
pub const DT_E2K_EXPORT_PLSZ: u32 = DT_LOPROC + 0x101e;
pub const DT_E2K_REAL_PLTGOT: u32 = DT_LOPROC + 0x101f;
pub const DT_E2K_NO_SELFINIT: u32 = DT_LOPROC + 0x1020;

pub const DT_E2K_NUM: u32 = 0x1021;

#[allow(non_upper_case_globals)]
pub const Tag_File: u8 = 1;
#[allow(non_upper_case_globals)]
Expand Down
2 changes: 2 additions & 0 deletions src/read/elf/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ where
(elf::EM_AVR, _) => Architecture::Avr,
(elf::EM_BPF, _) => Architecture::Bpf,
(elf::EM_CSKY, _) => Architecture::Csky,
(elf::EM_MCST_ELBRUS, false) => Architecture::E2K32,
(elf::EM_MCST_ELBRUS, true) => Architecture::E2K64,
(elf::EM_386, _) => Architecture::I386,
(elf::EM_X86_64, false) => Architecture::X86_64_X32,
(elf::EM_X86_64, true) => Architecture::X86_64,
Expand Down
8 changes: 8 additions & 0 deletions src/read/elf/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,14 @@ fn parse_relocation<Elf: FileHeader>(
elf::R_CKCORE_PCREL32 => (K::Relative, g, 32),
_ => unknown,
},
elf::EM_MCST_ELBRUS => match r_type {
elf::R_E2K_32_ABS => (K::Absolute, g, 32),
elf::R_E2K_64_ABS => (K::Absolute, g, 64),
elf::R_E2K_64_ABS_LIT => (K::Absolute, E::E2KLit, 64),
elf::R_E2K_DISP => (K::Relative, E::E2KDisp, 28),
elf::R_E2K_GOT => (K::Got, g, 32),
_ => unknown,
},
elf::EM_386 => match r_type {
elf::R_386_32 => (K::Absolute, g, 32),
elf::R_386_PC32 => (K::Relative, g, 32),
Expand Down
12 changes: 12 additions & 0 deletions src/write/elf/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ impl<'a> Object<'a> {
Architecture::Avr => true,
Architecture::Bpf => false,
Architecture::Csky => true,
Architecture::E2K32 => true,
Architecture::E2K64 => true,
Architecture::I386 => false,
Architecture::X86_64 => true,
Architecture::X86_64_X32 => true,
Expand Down Expand Up @@ -218,6 +220,14 @@ impl<'a> Object<'a> {
(K::Relative, 8) => elf::R_386_PC8,
_ => return unsupported_reloc(),
},
Architecture::E2K32 | Architecture::E2K64 => match (kind, encoding, size) {
(K::Absolute, E::Generic, 32) => elf::R_E2K_32_ABS,
(K::Absolute, E::E2KLit, 64) => elf::R_E2K_64_ABS_LIT,
(K::Absolute, E::Generic, 64) => elf::R_E2K_64_ABS,
(K::Relative, E::E2KDisp, 28) => elf::R_E2K_DISP,
(K::Got, _, 32) => elf::R_E2K_GOT,
_ => return unsupported_reloc(),
},
Architecture::X86_64 | Architecture::X86_64_X32 => match (kind, encoding, size) {
(K::Absolute, E::Generic, 64) => elf::R_X86_64_64,
(K::Relative, E::X86Branch, 32) => elf::R_X86_64_PLT32,
Expand Down Expand Up @@ -521,6 +531,8 @@ impl<'a> Object<'a> {
(Architecture::Avr, None) => elf::EM_AVR,
(Architecture::Bpf, None) => elf::EM_BPF,
(Architecture::Csky, None) => elf::EM_CSKY,
(Architecture::E2K32, None) => elf::EM_MCST_ELBRUS,
(Architecture::E2K64, None) => elf::EM_MCST_ELBRUS,
(Architecture::I386, None) => elf::EM_386,
(Architecture::X86_64, None) => elf::EM_X86_64,
(Architecture::X86_64_X32, None) => elf::EM_X86_64,
Expand Down
2 changes: 2 additions & 0 deletions tests/round_trip/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,8 @@ fn elf_any() {
(Architecture::Avr, Endianness::Little),
(Architecture::Bpf, Endianness::Little),
(Architecture::Csky, Endianness::Little),
(Architecture::E2K32, Endianness::Little),
(Architecture::E2K64, Endianness::Little),
(Architecture::I386, Endianness::Little),
(Architecture::X86_64, Endianness::Little),
(Architecture::X86_64_X32, Endianness::Little),
Expand Down

0 comments on commit 34f6dce

Please sign in to comment.