From 7d84f88825bcba7eefdcb075cfd5a42d4c8af446 Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Thu, 24 Mar 2022 02:24:25 +0800 Subject: [PATCH 1/2] add LoongArch64 ELF basic support --- src/common.rs | 2 + src/elf.rs | 125 ++++++++++++++++++++++++++++++++++++++++ src/read/elf/file.rs | 1 + src/write/elf/object.rs | 2 + 4 files changed, 130 insertions(+) diff --git a/src/common.rs b/src/common.rs index 917172e0..987c6f88 100644 --- a/src/common.rs +++ b/src/common.rs @@ -13,6 +13,7 @@ pub enum Architecture { #[allow(non_camel_case_types)] X86_64_X32, Hexagon, + LoongArch64, Mips, Mips64, Msp430, @@ -40,6 +41,7 @@ impl Architecture { Architecture::X86_64 => Some(AddressSize::U64), Architecture::X86_64_X32 => Some(AddressSize::U32), Architecture::Hexagon => Some(AddressSize::U32), + Architecture::LoongArch64 => Some(AddressSize::U64), Architecture::Mips => Some(AddressSize::U32), Architecture::Mips64 => Some(AddressSize::U64), Architecture::Msp430 => Some(AddressSize::U16), diff --git a/src/elf.rs b/src/elf.rs index 1818a0ad..73b97292 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -562,6 +562,8 @@ pub const EM_RISCV: u16 = 243; pub const EM_BPF: u16 = 247; /// C-SKY pub const EM_CSKY: u16 = 252; +/// Loongson LoongArch +pub const EM_LOONGARCH: u16 = 258; /// Digital Alpha pub const EM_ALPHA: u16 = 0x9026; @@ -6225,6 +6227,129 @@ pub const R_NDS32_TLS_TPOFF: u32 = 102; #[allow(missing_docs)] pub const R_NDS32_TLS_DESC: u32 = 119; +// LoongArch values `FileHeader*::e_flags`. +/// Uses 64-bit GPRs and the stack for parameter passing +pub const EF_LARCH_ABI_LP64S: u32 = 0x1; +/// Uses 64-bit GPRs, 32-bit FPRs and the stack for parameter passing +pub const EF_LARCH_ABI_LP64F: u32 = 0x2; +/// Uses 64-bit GPRs, 64-bit FPRs and the stack for parameter passing +pub const EF_LARCH_ABI_LP64D: u32 = 0x3; +/// Uses 32-bit GPRs and the stack for parameter passing +pub const EF_LARCH_ABI_ILP32S: u32 = 0x5; +/// Uses 32-bit GPRs, 32-bit FPRs and the stack for parameter passing +pub const EF_LARCH_ABI_ILP32F: u32 = 0x6; +/// Uses 32-bit GPRs, 64-bit FPRs and the stack for parameter passing +pub const EF_LARCH_ABI_ILP32D: u32 = 0x7; + +// LoongArch values `Rel*::r_type`. +/// No reloc +pub const R_LARCH_NONE: u32 = 0; +/// Runtime address resolving +pub const R_LARCH_32: u32 = 1; +/// Runtime address resolving +pub const R_LARCH_64: u32 = 2; +/// Runtime fixup for load-address +pub const R_LARCH_RELATIVE: u32 = 3; +/// Runtime memory copy in executable +pub const R_LARCH_COPY: u32 = 4; +/// Runtime PLT supporting +pub const R_LARCH_JUMP_SLOT: u32 = 5; +/// Runtime relocation for TLS-GD +pub const R_LARCH_TLS_DTPMOD32: u32 = 6; +/// Runtime relocation for TLS-GD +pub const R_LARCH_TLS_DTPMOD64: u32 = 7; +/// Runtime relocation for TLS-GD +pub const R_LARCH_TLS_DTPREL32: u32 = 8; +/// Runtime relocation for TLS-GD +pub const R_LARCH_TLS_DTPREL64: u32 = 9; +/// Runtime relocation for TLE-IE +pub const R_LARCH_TLS_TPREL32: u32 = 10; +/// Runtime relocation for TLE-IE +pub const R_LARCH_TLS_TPREL64: u32 = 11; +/// Runtime local indirect function resolving +pub const R_LARCH_IRELATIVE: u32 = 12; +/// Mark la.abs: load absolute address for static link. +pub const R_LARCH_MARK_LA: u32 = 20; +/// Mark external label branch: access PC relative address for static link. +pub const R_LARCH_MARK_PCREL: u32 = 21; +/// Push PC-relative offset +pub const R_LARCH_SOP_PUSH_PCREL: u32 = 22; +/// Push constant or absolute address +pub const R_LARCH_SOP_PUSH_ABSOLUTE: u32 = 23; +/// Duplicate stack top +pub const R_LARCH_SOP_PUSH_DUP: u32 = 24; +/// Push for access GOT entry +pub const R_LARCH_SOP_PUSH_GPREL: u32 = 25; +/// Push for TLS-LE +pub const R_LARCH_SOP_PUSH_TLS_TPREL: u32 = 26; +/// Push for TLS-IE +pub const R_LARCH_SOP_PUSH_TLS_GOT: u32 = 27; +/// Push for TLS-GD +pub const R_LARCH_SOP_PUSH_TLS_GD: u32 = 28; +/// Push for external function calling +pub const R_LARCH_SOP_PUSH_PLT_PCREL: u32 = 29; +/// Assert stack top +pub const R_LARCH_SOP_ASSERT: u32 = 30; +/// Stack top logical not (unary) +pub const R_LARCH_SOP_NOT: u32 = 31; +/// Stack top subtraction (binary) +pub const R_LARCH_SOP_SUB: u32 = 32; +/// Stack top left shift (binary) +pub const R_LARCH_SOP_SL: u32 = 33; +/// Stack top right shift (binary) +pub const R_LARCH_SOP_SR: u32 = 34; +/// Stack top addition (binary) +pub const R_LARCH_SOP_ADD: u32 = 35; +/// Stack top bitwise and (binary) +pub const R_LARCH_SOP_AND: u32 = 36; +/// Stack top selection (tertiary) +pub const R_LARCH_SOP_IF_ELSE: u32 = 37; +/// Pop stack top to fill 5-bit signed immediate operand +pub const R_LARCH_SOP_POP_32_S_10_5: u32 = 38; +/// Pop stack top to fill 12-bit unsigned immediate operand +pub const R_LARCH_SOP_POP_32_U_10_12: u32 = 39; +/// Pop stack top to fill 12-bit signed immediate operand +pub const R_LARCH_SOP_POP_32_S_10_12: u32 = 40; +/// Pop stack top to fill 16-bit signed immediate operand +pub const R_LARCH_SOP_POP_32_S_10_16: u32 = 41; +/// Pop stack top to fill 18-bit signed immediate operand with two trailing +/// zeros implied +pub const R_LARCH_SOP_POP_32_S_10_16_S2: u32 = 42; +/// Pop stack top to fill 20-bit signed immediate operand +pub const R_LARCH_SOP_POP_32_S_5_20: u32 = 43; +/// Pop stack top to fill 23-bit signed immediate operand with two trailing +/// zeros implied +pub const R_LARCH_SOP_POP_32_S_0_5_10_16_S2: u32 = 44; +/// Pop stack top to fill 28-bit signed immediate operand with two trailing +/// zeros implied +pub const R_LARCH_SOP_POP_32_S_0_10_10_16_S2: u32 = 45; +/// Pop stack top to fill an instruction +pub const R_LARCH_SOP_POP_32_U: u32 = 46; +/// 8-bit in-place addition +pub const R_LARCH_ADD8: u32 = 47; +/// 16-bit in-place addition +pub const R_LARCH_ADD16: u32 = 48; +/// 24-bit in-place addition +pub const R_LARCH_ADD24: u32 = 49; +/// 32-bit in-place addition +pub const R_LARCH_ADD32: u32 = 50; +/// 64-bit in-place addition +pub const R_LARCH_ADD64: u32 = 51; +/// 8-bit in-place subtraction +pub const R_LARCH_SUB8: u32 = 52; +/// 16-bit in-place subtraction +pub const R_LARCH_SUB16: u32 = 53; +/// 24-bit in-place subtraction +pub const R_LARCH_SUB24: u32 = 54; +/// 32-bit in-place subtraction +pub const R_LARCH_SUB32: u32 = 55; +/// 64-bit in-place subtraction +pub const R_LARCH_SUB64: u32 = 56; +/// GNU C++ vtable hierarchy +pub const R_LARCH_GNU_VTINHERIT: u32 = 57; +/// GNU C++ vtable member usage +pub const R_LARCH_GNU_VTENTRY: u32 = 58; + unsafe_impl_endian_pod!( FileHeader32, FileHeader64, diff --git a/src/read/elf/file.rs b/src/read/elf/file.rs index 7df4ab2c..d5a2647b 100644 --- a/src/read/elf/file.rs +++ b/src/read/elf/file.rs @@ -164,6 +164,7 @@ where (elf::EM_X86_64, false) => Architecture::X86_64_X32, (elf::EM_X86_64, true) => Architecture::X86_64, (elf::EM_HEXAGON, _) => Architecture::Hexagon, + (elf::EM_LOONGARCH, true) => Architecture::LoongArch64, (elf::EM_MIPS, false) => Architecture::Mips, (elf::EM_MIPS, true) => Architecture::Mips64, (elf::EM_MSP430, _) => Architecture::Msp430, diff --git a/src/write/elf/object.rs b/src/write/elf/object.rs index 834c6a19..59ebdd3e 100644 --- a/src/write/elf/object.rs +++ b/src/write/elf/object.rs @@ -74,6 +74,7 @@ impl<'a> Object<'a> { Architecture::X86_64 => true, Architecture::X86_64_X32 => true, Architecture::Hexagon => true, + Architecture::LoongArch64 => true, Architecture::Mips => false, Architecture::Mips64 => true, Architecture::Msp430 => true, @@ -270,6 +271,7 @@ impl<'a> Object<'a> { Architecture::X86_64 => elf::EM_X86_64, Architecture::X86_64_X32 => elf::EM_X86_64, Architecture::Hexagon => elf::EM_HEXAGON, + Architecture::LoongArch64 => elf::EM_LOONGARCH, Architecture::Mips => elf::EM_MIPS, Architecture::Mips64 => elf::EM_MIPS, Architecture::Msp430 => elf::EM_MSP430, From 4f286da541a95dfef18600d54fee4a7421015ec1 Mon Sep 17 00:00:00 2001 From: Xi Ruoyao Date: Thu, 31 Mar 2022 17:54:17 +0800 Subject: [PATCH 2/2] add LoongArch64 ELF absolute relocation support --- src/read/elf/relocation.rs | 5 +++++ src/write/elf/object.rs | 9 +++++++++ tests/round_trip/mod.rs | 1 + 3 files changed, 15 insertions(+) diff --git a/src/read/elf/relocation.rs b/src/read/elf/relocation.rs index 5930613a..557b80ef 100644 --- a/src/read/elf/relocation.rs +++ b/src/read/elf/relocation.rs @@ -301,6 +301,11 @@ fn parse_relocation( elf::R_HEX_32 => (RelocationKind::Absolute, 32), r_type => (RelocationKind::Elf(r_type), 0), }, + elf::EM_LOONGARCH => match reloc.r_type(endian, false) { + elf::R_LARCH_32 => (RelocationKind::Absolute, 32), + elf::R_LARCH_64 => (RelocationKind::Absolute, 64), + r_type => (RelocationKind::Elf(r_type), 0), + }, elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) { elf::R_MIPS_16 => (RelocationKind::Absolute, 16), elf::R_MIPS_32 => (RelocationKind::Absolute, 32), diff --git a/src/write/elf/object.rs b/src/write/elf/object.rs index 59ebdd3e..b4b5f400 100644 --- a/src/write/elf/object.rs +++ b/src/write/elf/object.rs @@ -519,6 +519,15 @@ impl<'a> Object<'a> { return Err(Error(format!("unimplemented relocation {:?}", reloc))); } }, + Architecture::LoongArch64 => match (reloc.kind, reloc.encoding, reloc.size) + { + (RelocationKind::Absolute, _, 32) => elf::R_LARCH_32, + (RelocationKind::Absolute, _, 64) => elf::R_LARCH_64, + (RelocationKind::Elf(x), _, _) => x, + _ => { + return Err(Error(format!("unimplemented relocation {:?}", reloc))); + } + }, Architecture::Mips | Architecture::Mips64 => { match (reloc.kind, reloc.encoding, reloc.size) { (RelocationKind::Absolute, _, 16) => elf::R_MIPS_16, diff --git a/tests/round_trip/mod.rs b/tests/round_trip/mod.rs index e83b2c22..120092ee 100644 --- a/tests/round_trip/mod.rs +++ b/tests/round_trip/mod.rs @@ -238,6 +238,7 @@ fn elf_any() { (Architecture::X86_64, Endianness::Little), (Architecture::X86_64_X32, Endianness::Little), (Architecture::Hexagon, Endianness::Little), + (Architecture::LoongArch64, Endianness::Little), (Architecture::Mips, Endianness::Little), (Architecture::Mips64, Endianness::Little), (Architecture::Msp430, Endianness::Little),