Skip to content

Commit

Permalink
add LoongArch64 ELF basic support (#430)
Browse files Browse the repository at this point in the history
  • Loading branch information
xry111 authored Apr 1, 2022
1 parent 389c43a commit c476071
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub enum Architecture {
#[allow(non_camel_case_types)]
X86_64_X32,
Hexagon,
LoongArch64,
Mips,
Mips64,
Msp430,
Expand Down Expand Up @@ -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),
Expand Down
125 changes: 125 additions & 0 deletions src/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/read/elf/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
5 changes: 5 additions & 0 deletions src/read/elf/relocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,11 @@ fn parse_relocation<Elf: FileHeader>(
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),
Expand Down
11 changes: 11 additions & 0 deletions src/write/elf/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -517,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,
Expand Down
1 change: 1 addition & 0 deletions tests/round_trip/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down

0 comments on commit c476071

Please sign in to comment.