Skip to content

Commit 34f6dce

Browse files
authored
elf: add basic support for E2K arch (#727)
1 parent 7e292fc commit 34f6dce

File tree

6 files changed

+206
-0
lines changed

6 files changed

+206
-0
lines changed

src/common.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub enum Architecture {
1111
Avr,
1212
Bpf,
1313
Csky,
14+
E2K32,
15+
E2K64,
1416
I386,
1517
X86_64,
1618
#[allow(non_camel_case_types)]
@@ -57,6 +59,8 @@ impl Architecture {
5759
Architecture::Avr => Some(AddressSize::U8),
5860
Architecture::Bpf => Some(AddressSize::U64),
5961
Architecture::Csky => Some(AddressSize::U32),
62+
Architecture::E2K32 => Some(AddressSize::U32),
63+
Architecture::E2K64 => Some(AddressSize::U64),
6064
Architecture::I386 => Some(AddressSize::U32),
6165
Architecture::X86_64 => Some(AddressSize::U64),
6266
Architecture::X86_64_X32 => Some(AddressSize::U32),
@@ -415,6 +419,18 @@ pub enum RelocationEncoding {
415419
/// * 16-bit absolute address
416420
/// * 6-bit relative address
417421
SharcTypeB,
422+
423+
/// E2K 64-bit value stored in two LTS
424+
///
425+
/// Memory representation:
426+
/// ```text
427+
/// 0: LTS1 = value[63:32]
428+
/// 4: LTS0 = value[31:0]
429+
/// ```
430+
E2KLit,
431+
432+
/// E2K 28-bit value stored in CS0
433+
E2KDisp,
418434
}
419435

420436
/// File flags that are specific to each file format.

src/elf.rs

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6270,6 +6270,172 @@ pub const R_XTENSA_NDIFF8: u32 = 60;
62706270
pub const R_XTENSA_NDIFF16: u32 = 61;
62716271
pub const R_XTENSA_NDIFF32: u32 = 62;
62726272

6273+
// E2K values for `FileHeader*::e_flags`.
6274+
pub const EF_E2K_IPD: u32 = 3;
6275+
pub const EF_E2K_X86APP: u32 = 4;
6276+
pub const EF_E2K_4MB_PAGES: u32 = 8;
6277+
pub const EF_E2K_INCOMPAT: u32 = 16;
6278+
pub const EF_E2K_PM: u32 = 32;
6279+
pub const EF_E2K_PACK_SEGMENTS: u32 = 64;
6280+
6281+
/// Encode `E_E2K_MACH_*` into `FileHeader*::e_flags`.
6282+
pub const fn ef_e2k_mach_to_flag(e_flags: u32, x: u32) -> u32 {
6283+
(e_flags & 0xffffff) | (x << 24)
6284+
}
6285+
6286+
/// Decode `E_E2K_MACH_*` from `FileHeader*::e_flags`.
6287+
pub const fn ef_e2k_flag_to_mach(e_flags: u32) -> u32 {
6288+
e_flags >> 24
6289+
}
6290+
6291+
// Codes of supported E2K machines.
6292+
6293+
/// -march=generic code.
6294+
///
6295+
/// Legacy. Shouldn't be created nowadays.
6296+
pub const E_E2K_MACH_BASE: u32 = 0;
6297+
/// -march=elbrus-v1 code.
6298+
///
6299+
/// Legacy. Shouldn't be created nowadays.
6300+
pub const E_E2K_MACH_EV1: u32 = 1;
6301+
/// -march=elbrus-v2 code.
6302+
pub const E_E2K_MACH_EV2: u32 = 2;
6303+
/// -march=elbrus-v3 code.
6304+
pub const E_E2K_MACH_EV3: u32 = 3;
6305+
/// -march=elbrus-v4 code.
6306+
pub const E_E2K_MACH_EV4: u32 = 4;
6307+
/// -march=elbrus-v5 code.
6308+
pub const E_E2K_MACH_EV5: u32 = 5;
6309+
/// -march=elbrus-v6 code.
6310+
pub const E_E2K_MACH_EV6: u32 = 6;
6311+
/// -march=elbrus-v7 code.
6312+
pub const E_E2K_MACH_EV7: u32 = 7;
6313+
/// -mtune=elbrus-8c code.
6314+
pub const E_E2K_MACH_8C: u32 = 19;
6315+
/// -mtune=elbrus-1c+ code.
6316+
pub const E_E2K_MACH_1CPLUS: u32 = 20;
6317+
/// -mtune=elbrus-12c code.
6318+
pub const E_E2K_MACH_12C: u32 = 21;
6319+
/// -mtune=elbrus-16c code.
6320+
pub const E_E2K_MACH_16C: u32 = 22;
6321+
/// -mtune=elbrus-2c3 code.
6322+
pub const E_E2K_MACH_2C3: u32 = 23;
6323+
/// -mtune=elbrus-48c code.
6324+
pub const E_E2K_MACH_48C: u32 = 24;
6325+
/// -mtune=elbrus-8v7 code.
6326+
pub const E_E2K_MACH_8V7: u32 = 25;
6327+
6328+
// E2K values `Rel*::r_type`.
6329+
6330+
/// Direct 32 bit.
6331+
pub const R_E2K_32_ABS: u32 = 0;
6332+
/// PC relative 32 bit.
6333+
pub const R_E2K_32_PC: u32 = 2;
6334+
/// 32-bit offset of AP GOT entry.
6335+
pub const R_E2K_AP_GOT: u32 = 3;
6336+
/// 32-bit offset of PL GOT entry.
6337+
pub const R_E2K_PL_GOT: u32 = 4;
6338+
/// Create PLT entry.
6339+
pub const R_E2K_32_JMP_SLOT: u32 = 8;
6340+
/// Copy relocation, 32-bit case.
6341+
pub const R_E2K_32_COPY: u32 = 9;
6342+
/// Adjust by program base, 32-bit case.
6343+
pub const R_E2K_32_RELATIVE: u32 = 10;
6344+
/// Adjust indirectly by program base, 32-bit case.
6345+
pub const R_E2K_32_IRELATIVE: u32 = 11;
6346+
/// Size of symbol plus 32-bit addend.
6347+
pub const R_E2K_32_SIZE: u32 = 12;
6348+
/// Symbol value if resolved by the definition in the same
6349+
/// compilation unit or NULL otherwise, 32-bit case.
6350+
pub const R_E2K_32_DYNOPT: u32 = 13;
6351+
/// Direct 64 bit.
6352+
pub const R_E2K_64_ABS: u32 = 50;
6353+
/// Direct 64 bit for literal.
6354+
pub const R_E2K_64_ABS_LIT: u32 = 51;
6355+
/// PC relative 64 bit for literal.
6356+
pub const R_E2K_64_PC_LIT: u32 = 54;
6357+
/// Create PLT entry, 64-bit case.
6358+
pub const R_E2K_64_JMP_SLOT: u32 = 63;
6359+
/// Copy relocation, 64-bit case.
6360+
pub const R_E2K_64_COPY: u32 = 64;
6361+
/// Adjust by program base, 64-bit case.
6362+
pub const R_E2K_64_RELATIVE: u32 = 65;
6363+
/// Adjust by program base for literal, 64-bit case.
6364+
pub const R_E2K_64_RELATIVE_LIT: u32 = 66;
6365+
/// Adjust indirectly by program base, 64-bit case.
6366+
pub const R_E2K_64_IRELATIVE: u32 = 67;
6367+
/// Size of symbol plus 64-bit addend.
6368+
pub const R_E2K_64_SIZE: u32 = 68;
6369+
/// 64-bit offset of the symbol from GOT.
6370+
pub const R_E2K_64_GOTOFF: u32 = 69;
6371+
6372+
/// GOT entry for ID of module containing symbol.
6373+
pub const R_E2K_TLS_GDMOD: u32 = 70;
6374+
/// GOT entry for offset in module TLS block.
6375+
pub const R_E2K_TLS_GDREL: u32 = 71;
6376+
/// Static TLS block offset GOT entry.
6377+
pub const R_E2K_TLS_IE: u32 = 74;
6378+
/// Offset relative to static TLS block, 32-bit case.
6379+
pub const R_E2K_32_TLS_LE: u32 = 75;
6380+
/// Offset relative to static TLS block, 64-bit case.
6381+
pub const R_E2K_64_TLS_LE: u32 = 76;
6382+
/// ID of module containing symbol, 32-bit case.
6383+
pub const R_E2K_TLS_32_DTPMOD: u32 = 80;
6384+
/// Offset in module TLS block, 32-bit case.
6385+
pub const R_E2K_TLS_32_DTPREL: u32 = 81;
6386+
/// ID of module containing symbol, 64-bit case.
6387+
pub const R_E2K_TLS_64_DTPMOD: u32 = 82;
6388+
/// Offset in module TLS block, 64-bit case.
6389+
pub const R_E2K_TLS_64_DTPREL: u32 = 83;
6390+
/// Offset in static TLS block, 32-bit case.
6391+
pub const R_E2K_TLS_32_TPREL: u32 = 84;
6392+
/// Offset in static TLS block, 64-bit case.
6393+
pub const R_E2K_TLS_64_TPREL: u32 = 85;
6394+
6395+
/// Direct AP.
6396+
pub const R_E2K_AP: u32 = 100;
6397+
/// Direct PL.
6398+
pub const R_E2K_PL: u32 = 101;
6399+
6400+
/// 32-bit offset of the symbol's entry in GOT.
6401+
pub const R_E2K_GOT: u32 = 108;
6402+
/// 32-bit offset of the symbol from GOT.
6403+
pub const R_E2K_GOTOFF: u32 = 109;
6404+
/// PC relative 28 bit for DISP.
6405+
pub const R_E2K_DISP: u32 = 110;
6406+
/// Prefetch insn line containing the label (symbol).
6407+
pub const R_E2K_PREF: u32 = 111;
6408+
/// No reloc.
6409+
pub const R_E2K_NONE: u32 = 112;
6410+
/// 32-bit offset of the symbol's entry in .got.plt.
6411+
pub const R_E2K_GOTPLT: u32 = 114;
6412+
/// Is symbol resolved locally during the link.
6413+
/// The result is encoded in 5-bit ALS.src1.
6414+
pub const R_E2K_ISLOCAL: u32 = 115;
6415+
/// Is symbol resloved locally during the link.
6416+
/// The result is encoded in a long 32-bit LTS.
6417+
pub const R_E2K_ISLOCAL32: u32 = 118;
6418+
/// The symbol's offset from GOT encoded within a 64-bit literal.
6419+
pub const R_E2K_64_GOTOFF_LIT: u32 = 256;
6420+
/// Symbol value if resolved by the definition in the same
6421+
/// compilation unit or NULL otherwise, 64-bit case.
6422+
pub const R_E2K_64_DYNOPT: u32 = 257;
6423+
/// PC relative 64 bit in data.
6424+
pub const R_E2K_64_PC: u32 = 258;
6425+
6426+
// E2K values for `Dyn32::d_tag`.
6427+
6428+
pub const DT_E2K_LAZY: u32 = DT_LOPROC + 1;
6429+
pub const DT_E2K_LAZY_GOT: u32 = DT_LOPROC + 3;
6430+
6431+
pub const DT_E2K_INIT_GOT: u32 = DT_LOPROC + 0x101c;
6432+
pub const DT_E2K_EXPORT_PL: u32 = DT_LOPROC + 0x101d;
6433+
pub const DT_E2K_EXPORT_PLSZ: u32 = DT_LOPROC + 0x101e;
6434+
pub const DT_E2K_REAL_PLTGOT: u32 = DT_LOPROC + 0x101f;
6435+
pub const DT_E2K_NO_SELFINIT: u32 = DT_LOPROC + 0x1020;
6436+
6437+
pub const DT_E2K_NUM: u32 = 0x1021;
6438+
62736439
#[allow(non_upper_case_globals)]
62746440
pub const Tag_File: u8 = 1;
62756441
#[allow(non_upper_case_globals)]

src/read/elf/file.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ where
209209
(elf::EM_AVR, _) => Architecture::Avr,
210210
(elf::EM_BPF, _) => Architecture::Bpf,
211211
(elf::EM_CSKY, _) => Architecture::Csky,
212+
(elf::EM_MCST_ELBRUS, false) => Architecture::E2K32,
213+
(elf::EM_MCST_ELBRUS, true) => Architecture::E2K64,
212214
(elf::EM_386, _) => Architecture::I386,
213215
(elf::EM_X86_64, false) => Architecture::X86_64_X32,
214216
(elf::EM_X86_64, true) => Architecture::X86_64,

src/read/elf/relocation.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,14 @@ fn parse_relocation<Elf: FileHeader>(
294294
elf::R_CKCORE_PCREL32 => (K::Relative, g, 32),
295295
_ => unknown,
296296
},
297+
elf::EM_MCST_ELBRUS => match r_type {
298+
elf::R_E2K_32_ABS => (K::Absolute, g, 32),
299+
elf::R_E2K_64_ABS => (K::Absolute, g, 64),
300+
elf::R_E2K_64_ABS_LIT => (K::Absolute, E::E2KLit, 64),
301+
elf::R_E2K_DISP => (K::Relative, E::E2KDisp, 28),
302+
elf::R_E2K_GOT => (K::Got, g, 32),
303+
_ => unknown,
304+
},
297305
elf::EM_386 => match r_type {
298306
elf::R_386_32 => (K::Absolute, g, 32),
299307
elf::R_386_PC32 => (K::Relative, g, 32),

src/write/elf/object.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ impl<'a> Object<'a> {
126126
Architecture::Avr => true,
127127
Architecture::Bpf => false,
128128
Architecture::Csky => true,
129+
Architecture::E2K32 => true,
130+
Architecture::E2K64 => true,
129131
Architecture::I386 => false,
130132
Architecture::X86_64 => true,
131133
Architecture::X86_64_X32 => true,
@@ -218,6 +220,14 @@ impl<'a> Object<'a> {
218220
(K::Relative, 8) => elf::R_386_PC8,
219221
_ => return unsupported_reloc(),
220222
},
223+
Architecture::E2K32 | Architecture::E2K64 => match (kind, encoding, size) {
224+
(K::Absolute, E::Generic, 32) => elf::R_E2K_32_ABS,
225+
(K::Absolute, E::E2KLit, 64) => elf::R_E2K_64_ABS_LIT,
226+
(K::Absolute, E::Generic, 64) => elf::R_E2K_64_ABS,
227+
(K::Relative, E::E2KDisp, 28) => elf::R_E2K_DISP,
228+
(K::Got, _, 32) => elf::R_E2K_GOT,
229+
_ => return unsupported_reloc(),
230+
},
221231
Architecture::X86_64 | Architecture::X86_64_X32 => match (kind, encoding, size) {
222232
(K::Absolute, E::Generic, 64) => elf::R_X86_64_64,
223233
(K::Relative, E::X86Branch, 32) => elf::R_X86_64_PLT32,
@@ -521,6 +531,8 @@ impl<'a> Object<'a> {
521531
(Architecture::Avr, None) => elf::EM_AVR,
522532
(Architecture::Bpf, None) => elf::EM_BPF,
523533
(Architecture::Csky, None) => elf::EM_CSKY,
534+
(Architecture::E2K32, None) => elf::EM_MCST_ELBRUS,
535+
(Architecture::E2K64, None) => elf::EM_MCST_ELBRUS,
524536
(Architecture::I386, None) => elf::EM_386,
525537
(Architecture::X86_64, None) => elf::EM_X86_64,
526538
(Architecture::X86_64_X32, None) => elf::EM_X86_64,

tests/round_trip/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ fn elf_any() {
265265
(Architecture::Avr, Endianness::Little),
266266
(Architecture::Bpf, Endianness::Little),
267267
(Architecture::Csky, Endianness::Little),
268+
(Architecture::E2K32, Endianness::Little),
269+
(Architecture::E2K64, Endianness::Little),
268270
(Architecture::I386, Endianness::Little),
269271
(Architecture::X86_64, Endianness::Little),
270272
(Architecture::X86_64_X32, Endianness::Little),

0 commit comments

Comments
 (0)