From 727a50c4fc849f46296fef3358ea828d106f9b14 Mon Sep 17 00:00:00 2001 From: Josh Channings Date: Fri, 6 Oct 2023 22:06:38 +0100 Subject: [PATCH] elf: Add support for SHARC+ relocations --- src/common.rs | 48 ++++++++++++++++++ src/elf.rs | 100 +++++++++++++++++++++++++++++++++++++ src/read/elf/relocation.rs | 51 +++++++++++++++++++ src/write/elf/object.rs | 21 ++++++++ 4 files changed, 220 insertions(+) diff --git a/src/common.rs b/src/common.rs index 158ff8a8..b1eddd61 100644 --- a/src/common.rs +++ b/src/common.rs @@ -369,6 +369,54 @@ pub enum RelocationEncoding { /// /// The `RelocationKind` must be PC relative. LoongArchBranch, + + /// SHARC+ 24-bit absolute address in a Type A instruction + /// + /// Used with `RelocationKind::Absolute`. + /// See [elf::R_SHARC_ADDR24_v3] + SharcAbs24TypeA, + + /// SHARC+ 32-bit absolute address in a Type A instruction + /// + /// Used with `RelocationKind::Absolute`. + /// See [elf::R_SHARC_ADDR32_v3] + SharcAbs32TypeA, + + /// SHARC+ 32-bit absolute address in a 32-bit STT_OBJECT location + /// + /// See [elf::R_SHARC_ADDRVAR_V3] + SharcAbs32Data, + + /// SHARC+ 6-bit relative address in a Type A instruction + /// + /// The `RelocationKind` must be PC relative. + SharcPcr6TypeA, + + /// SHARC+ 24-bit relative address in a Type A instruction + /// + /// The `RelocationKind` must be PC relative. + SharcPcr24TypeA, + + /// SHARC+ 6-bit absolute address in the immediate value field of a Type A instruction + SharcAbs6TypeA, + + /// SHARC+ 16-bit absolute address in the immediate value field of a Type A instruction + SharcAbs16TypeA, + + /// SHARC+ 6-bit absolute address in the immediate value field of a Type B instruction + SharcAbs6TypeB, + + /// SHARC+ 7-bit absolute address in the immediate value field of a Type B instruction + SharcAbs7TypeB, + + /// SHARC+ 16-bit absolute address in a Type B instruction + SharcAbs16TypeB, + + /// SHARC+ 6-bit relative address in a Type B instruction + SharcPcr6TypeB, + + /// SHARC+ 16-bit absolute address in a 16-bit STT_OBJECT location + SharcAbs16Data, } /// File flags that are specific to each file format. diff --git a/src/elf.rs b/src/elf.rs index f202c598..14f4b67b 100644 --- a/src/elf.rs +++ b/src/elf.rs @@ -2207,6 +2207,106 @@ pub const R_386_IRELATIVE: u32 = 42; /// Load from 32 bit GOT entry, relaxable. pub const R_386_GOT32X: u32 = 43; +// ADI SHARC specific definitions + +// SHARC values for `Rel*::r_type` + +/// 24-bit absolute address in bits 23:0 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 25a (PC_DIRECT) +pub const R_SHARC_ADDR24_V3: u32 = 0x0b; + +/// 32-bit absolute address in bits 31:0 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 14a +/// * Type 14d +/// * Type 15a +/// * Type 16a +/// * Type 17a +/// * Type 18a +/// * Type 19a +pub const R_SHARC_ADDR32_V3: u32 = 0x0c; + +/// 32-bit absolute address in bits 31:0 of a 32-bit data location +pub const R_SHARC_ADDR_VAR_V3: u32 = 0x0d; + +/// 6-bit PC-relative address in bits 32:27 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 9a +/// * Type 10a +pub const R_SHARC_PCRSHORT_V3: u32 = 0x0e; + +/// 24-bit PC-relative address in bits 23:0 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 8a +/// * Type 12a (truncated to 23 bits after relocation) +/// * Type 13a (truncated to 23 bits after relocation) +/// * Type 25a (PC Relative) +pub const R_SHARC_PCRLONG_V3: u32 = 0x0f; + +/// 6-bit absolute address in bits 32:27 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 4a +/// * Type 4b +/// * Type 4d +pub const R_SHARC_DATA6_V3: u32 = 0x10; + +/// 16-bit absolute address in bits 39:24 of a 48-bit instr +/// +/// Targets: +/// +/// * Type 12a +pub const R_SHARC_DATA16_V3: u32 = 0x11; + +/// 6-bit absolute address into bits 16:11 of a 32-bit instr +/// +/// Targets: +/// +/// * Type 4b +pub const R_SHARC_DATA6_VISA_V3: u32 = 0x12; + +/// 7-bit absolute address into bits 6:0 of a 32-bit instr +pub const R_SHARC_DATA7_VISA_V3: u32 = 0x13; + +/// 16-bit absolute address into bits 15:0 of a 32-bit instr +pub const R_SHARC_DATA16_VISA_V3: u32 = 0x14; + +/// 6-bit PC-relative address into bits 16:11 of a Type B +/// +/// Targets: +/// +/// * Type 9b +pub const R_SHARC_PCR6_VISA_V3: u32 = 0x17; + +/// 16-bit absolute address into bits 15:0 of a 16-bit location. +pub const R_SHARC_ADDR_VAR16_V3: u32 = 0x19; + +pub const R_SHARC_CALC_PUSH_ADDR: u32 = 0xe0; +pub const R_SHARC_CALC_PUSH_ADDEND: u32 = 0xe1; +pub const R_SHARC_CALC_ADD: u32 = 0xe2; +pub const R_SHARC_CALC_SUB: u32 = 0xe3; +pub const R_SHARC_CALC_MUL: u32 = 0xe4; +pub const R_SHARC_CALC_DIV: u32 = 0xe5; +pub const R_SHARC_CALC_MOD: u32 = 0xe6; +pub const R_SHARC_CALC_LSHIFT: u32 = 0xe7; +pub const R_SHARC_CALC_RSHIFT: u32 = 0xe8; +pub const R_SHARC_CALC_AND: u32 = 0xe9; +pub const R_SHARC_CALC_OR: u32 = 0xea; +pub const R_SHARC_CALC_XOR: u32 = 0xeb; +pub const R_SHARC_CALC_PUSH_LEN: u32 = 0xec; +pub const R_SHARC_CALC_NOT: u32 = 0xf6; + + // SUN SPARC specific definitions. // SPARC values for `st_type` component of `Sym*::st_info`. diff --git a/src/read/elf/relocation.rs b/src/read/elf/relocation.rs index 78032dfd..2f9a1568 100644 --- a/src/read/elf/relocation.rs +++ b/src/read/elf/relocation.rs @@ -404,6 +404,57 @@ fn parse_relocation( elf::R_SBF_64_32 => (RelocationKind::Absolute, 32), r_type => (RelocationKind::Elf(r_type), 0), }, + elf::EM_SHARC => match reloc.r_type(endian, false) { + elf::R_SHARC_ADDR24_V3 => { + encoding = RelocationEncoding::SharcAbs24TypeA; + (RelocationKind::Absolute, 48) + } + elf::R_SHARC_ADDR32_V3 => { + encoding = RelocationEncoding::SharcAbs32TypeA; + (RelocationKind::Absolute, 48) + } + elf::R_SHARC_ADDR_VAR_V3 => { + encoding = RelocationEncoding::SharcAbs32Data; + (RelocationKind::Absolute, 32) + } + elf::R_SHARC_PCRSHORT_V3 => { + encoding = RelocationEncoding::SharcPcr6TypeA; + (RelocationKind::Relative, 48) + } + elf::R_SHARC_PCRLONG_V3 => { + encoding = RelocationEncoding::SharcPcr24TypeA; + (RelocationKind::Relative, 48) + } + elf::R_SHARC_DATA6_V3 => { + encoding = RelocationEncoding::SharcAbs6TypeA; + (RelocationKind::Absolute, 48) + } + elf::R_SHARC_DATA16_V3 => { + encoding = RelocationEncoding::SharcAbs16TypeA; + (RelocationKind::Absolute, 48) + } + elf::R_SHARC_DATA6_VISA_V3 => { + encoding = RelocationEncoding::SharcAbs6TypeB; + (RelocationKind::Absolute, 32) + } + elf::R_SHARC_DATA7_VISA_V3 => { + encoding = RelocationEncoding::SharcAbs7TypeB; + (RelocationKind::Absolute, 32) + } + elf::R_SHARC_DATA16_VISA_V3 => { + encoding = RelocationEncoding::SharcAbs16TypeB; + (RelocationKind::Absolute, 32) + } + elf::R_SHARC_PCR6_VISA_V3 => { + encoding = RelocationEncoding::SharcPcr6TypeB; + (RelocationKind::Relative, 32) + } + elf::R_SHARC_ADDR_VAR16_V3 => { + encoding = RelocationEncoding::SharcAbs16Data; + (RelocationKind::Absolute, 16) + } + r_type => (RelocationKind::Elf(r_type), 0) + }, elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => { match reloc.r_type(endian, false) { elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32), diff --git a/src/write/elf/object.rs b/src/write/elf/object.rs index d62df560..fa80df33 100644 --- a/src/write/elf/object.rs +++ b/src/write/elf/object.rs @@ -768,6 +768,27 @@ impl<'a> Object<'a> { return Err(Error(format!("unimplemented relocation {:?}", reloc))); } }, + Architecture::Sharc => match (reloc.kind, reloc.encoding, reloc.size) { + (RelocationKind::Absolute, RelocationEncoding::SharcAbs32TypeA, 48) => elf::R_SHARC_ADDR32_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs32Data, 32) => elf::R_SHARC_ADDR_VAR_V3, + (RelocationKind::Relative, RelocationEncoding::SharcPcr24TypeA, 48) => elf::R_SHARC_PCRLONG_V3, + (RelocationKind::Relative, RelocationEncoding::SharcPcr6TypeA, 48) => elf::R_SHARC_PCRSHORT_V3, + (RelocationKind::Relative, RelocationEncoding::SharcPcr6TypeB, 32) => elf::R_SHARC_PCRSHORT_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs16Data, 16) => elf::R_SHARC_ADDR_VAR16_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs16TypeA, 48) => elf::R_SHARC_DATA16_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs16TypeB, 32) => elf::R_SHARC_DATA16_VISA_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs24TypeA, 48) => elf::R_SHARC_ADDR24_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs6TypeA, 48) => elf::R_SHARC_DATA6_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs6TypeB, 32) => elf::R_SHARC_DATA6_VISA_V3, + (RelocationKind::Absolute, RelocationEncoding::SharcAbs7TypeB, 32) => elf::R_SHARC_DATA7_VISA_V3, + (_, RelocationEncoding::Generic, _) => { + return Err(Error(format!("SHARC+ ISA does not have a generic relocation encoding"))); + }, + (RelocationKind::Elf(x), _, _) => x, + _ => { + return Err(Error(format!("unimplemented relocation {:?}", reloc))); + } + } Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) { // TODO: use R_SPARC_32/R_SPARC_64 if aligned. (RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32,