forked from M-Labs/artiq
libdyld: add riscv support
This commit is contained in:
parent
ad3037d0f6
commit
bfddd8a30f
|
@ -131,6 +131,7 @@ pub const EM_TILEPRO: u16 = 188;
|
||||||
pub const EM_MICROBLAZE: u16 = 189;
|
pub const EM_MICROBLAZE: u16 = 189;
|
||||||
pub const EM_TILEGX: u16 = 191;
|
pub const EM_TILEGX: u16 = 191;
|
||||||
pub const EM_NUM: u16 = 192;
|
pub const EM_NUM: u16 = 192;
|
||||||
|
pub const EM_RISCV: u16 = 243;
|
||||||
pub const EM_ALPHA: u16 = 36902;
|
pub const EM_ALPHA: u16 = 36902;
|
||||||
pub const EV_NONE: u8 = 0;
|
pub const EV_NONE: u8 = 0;
|
||||||
pub const EV_CURRENT: u8 = 1;
|
pub const EV_CURRENT: u8 = 1;
|
||||||
|
@ -2229,6 +2230,61 @@ pub const R_OR1K_TLS_TPOFF: u8 = 32;
|
||||||
pub const R_OR1K_TLS_DTPOFF: u8 = 33;
|
pub const R_OR1K_TLS_DTPOFF: u8 = 33;
|
||||||
pub const R_OR1K_TLS_DTPMOD: u8 = 34;
|
pub const R_OR1K_TLS_DTPMOD: u8 = 34;
|
||||||
pub const R_OR1K_NUM: u8 = 35;
|
pub const R_OR1K_NUM: u8 = 35;
|
||||||
|
pub const R_RISCV_NONE: u8 = 0;
|
||||||
|
pub const R_RISCV_32: u8 = 1;
|
||||||
|
pub const R_RISCV_64: u8 = 2;
|
||||||
|
pub const R_RISCV_RELATIVE: u8 = 3;
|
||||||
|
pub const R_RISCV_COPY: u8 = 4;
|
||||||
|
pub const R_RISCV_JUMP_SLOT: u8 = 5;
|
||||||
|
pub const R_RISCV_TLS_DTPMOD32: u8 = 6;
|
||||||
|
pub const R_RISCV_TLS_DTPMOD64: u8 = 7;
|
||||||
|
pub const R_RISCV_TLS_DTPREL32: u8 = 8;
|
||||||
|
pub const R_RISCV_TLS_DTPREL64: u8 = 9;
|
||||||
|
pub const R_RISCV_TLS_TPREL32: u8 = 10;
|
||||||
|
pub const R_RISCV_TLS_TPREL64: u8 = 11;
|
||||||
|
pub const R_RISCV_BRANCH: u8 = 16;
|
||||||
|
pub const R_RISCV_JAL: u8 = 17;
|
||||||
|
pub const R_RISCV_CALL: u8 = 18;
|
||||||
|
pub const R_RISCV_CALL_PLT: u8 = 19;
|
||||||
|
pub const R_RISCV_GOT_HI20: u8 = 20;
|
||||||
|
pub const R_RISCV_TLS_GOT_HI20: u8 = 21;
|
||||||
|
pub const R_RISCV_TLS_GD_HI20: u8 = 22;
|
||||||
|
pub const R_RISCV_PCREL_HI20: u8 = 23;
|
||||||
|
pub const R_RISCV_PCREL_LO12_I: u8 = 24;
|
||||||
|
pub const R_RISCV_PCREL_LO12_S: u8 = 25;
|
||||||
|
pub const R_RISCV_HI20: u8 = 26;
|
||||||
|
pub const R_RISCV_LO12_I: u8 = 27;
|
||||||
|
pub const R_RISCV_LO12_S: u8 = 28;
|
||||||
|
pub const R_RISCV_TPREL_HI20: u8 = 29;
|
||||||
|
pub const R_RISCV_TPREL_LO12_I: u8 = 30;
|
||||||
|
pub const R_RISCV_TPREL_LO12_S: u8 = 31;
|
||||||
|
pub const R_RISCV_TPREL_ADD: u8 = 32;
|
||||||
|
pub const R_RISCV_ADD8: u8 = 33;
|
||||||
|
pub const R_RISCV_ADD16: u8 = 34;
|
||||||
|
pub const R_RISCV_ADD32: u8 = 35;
|
||||||
|
pub const R_RISCV_ADD64: u8 = 36;
|
||||||
|
pub const R_RISCV_SUB8: u8 = 37;
|
||||||
|
pub const R_RISCV_SUB16: u8 = 38;
|
||||||
|
pub const R_RISCV_SUB32: u8 = 39;
|
||||||
|
pub const R_RISCV_SUB64: u8 = 40;
|
||||||
|
pub const R_RISCV_GNU_VTINHERIT: u8 = 41;
|
||||||
|
pub const R_RISCV_GNU_VTENTRY: u8 = 42;
|
||||||
|
pub const R_RISCV_ALIGN: u8 = 43;
|
||||||
|
pub const R_RISCV_RVC_BRANCH: u8 = 44;
|
||||||
|
pub const R_RISCV_RVC_JUMP: u8 = 45;
|
||||||
|
pub const R_RISCV_RVC_LUI: u8 = 46;
|
||||||
|
pub const R_RISCV_GPREL_I: u8 = 47;
|
||||||
|
pub const R_RISCV_GPREL_S: u8 = 48;
|
||||||
|
pub const R_RISCV_TPREL_I: u8 = 49;
|
||||||
|
pub const R_RISCV_TPREL_S: u8 = 50;
|
||||||
|
pub const R_RISCV_RELAX: u8 = 51;
|
||||||
|
pub const R_RISCV_SUB6: u8 = 52;
|
||||||
|
pub const R_RISCV_SET6: u8 = 53;
|
||||||
|
pub const R_RISCV_SET8: u8 = 54;
|
||||||
|
pub const R_RISCV_SET16: u8 = 55;
|
||||||
|
pub const R_RISCV_SET32: u8 = 56;
|
||||||
|
pub const R_RISCV_32_PCREL: u8 = 57;
|
||||||
|
pub const R_RISCV_NUM: u8 = 58;
|
||||||
|
|
||||||
pub type Elf32_Half = u16;
|
pub type Elf32_Half = u16;
|
||||||
pub type Elf64_Half = u16;
|
pub type Elf64_Half = u16;
|
||||||
|
|
|
@ -75,9 +75,16 @@ impl<'a> fmt::Display for Error<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum Arch {
|
||||||
|
RiscV,
|
||||||
|
OpenRisc,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Library<'a> {
|
pub struct Library<'a> {
|
||||||
image_off: Elf32_Addr,
|
image_off: Elf32_Addr,
|
||||||
image_sz: usize,
|
image_sz: usize,
|
||||||
|
arch: Arch,
|
||||||
strtab: &'a [u8],
|
strtab: &'a [u8],
|
||||||
symtab: &'a [Elf32_Sym],
|
symtab: &'a [Elf32_Sym],
|
||||||
pltrel: &'a [Elf32_Rela],
|
pltrel: &'a [Elf32_Rela],
|
||||||
|
@ -133,8 +140,12 @@ impl<'a> Library<'a> {
|
||||||
// This is unsafe because it mutates global data (the PLT).
|
// This is unsafe because it mutates global data (the PLT).
|
||||||
pub unsafe fn rebind(&self, name: &[u8], addr: Elf32_Word) -> Result<(), Error<'a>> {
|
pub unsafe fn rebind(&self, name: &[u8], addr: Elf32_Word) -> Result<(), Error<'a>> {
|
||||||
for rela in self.pltrel.iter() {
|
for rela in self.pltrel.iter() {
|
||||||
match ELF32_R_TYPE(rela.r_info) {
|
match (ELF32_R_TYPE(rela.r_info), self.arch) {
|
||||||
R_OR1K_32 | R_OR1K_GLOB_DAT | R_OR1K_JMP_SLOT => {
|
(R_OR1K_32, Arch::OpenRisc) |
|
||||||
|
(R_OR1K_GLOB_DAT, Arch::OpenRisc) |
|
||||||
|
(R_OR1K_JMP_SLOT, Arch::OpenRisc) |
|
||||||
|
(R_RISCV_32, Arch::RiscV) |
|
||||||
|
(R_RISCV_JUMP_SLOT, Arch::RiscV) => {
|
||||||
let sym = self.symtab.get(ELF32_R_SYM(rela.r_info) as usize)
|
let sym = self.symtab.get(ELF32_R_SYM(rela.r_info) as usize)
|
||||||
.ok_or("symbol out of bounds of symbol table")?;
|
.ok_or("symbol out of bounds of symbol table")?;
|
||||||
let sym_name = self.name_starting_at(sym.st_name as usize)?;
|
let sym_name = self.name_starting_at(sym.st_name as usize)?;
|
||||||
|
@ -162,14 +173,18 @@ impl<'a> Library<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let value;
|
let value;
|
||||||
match ELF32_R_TYPE(rela.r_info) {
|
match (ELF32_R_TYPE(rela.r_info), self.arch) {
|
||||||
R_OR1K_NONE =>
|
(R_OR1K_NONE, Arch::OpenRisc) | (R_RISCV_NONE, Arch::RiscV) =>
|
||||||
return Ok(()),
|
return Ok(()),
|
||||||
|
|
||||||
R_OR1K_RELATIVE =>
|
(R_OR1K_RELATIVE, Arch::OpenRisc) | (R_RISCV_RELATIVE, Arch::RiscV) =>
|
||||||
value = self.image_off + rela.r_addend as Elf32_Word,
|
value = self.image_off + rela.r_addend as Elf32_Word,
|
||||||
|
|
||||||
R_OR1K_32 | R_OR1K_GLOB_DAT | R_OR1K_JMP_SLOT => {
|
(R_OR1K_32, Arch::OpenRisc) |
|
||||||
|
(R_OR1K_GLOB_DAT, Arch::OpenRisc) |
|
||||||
|
(R_OR1K_JMP_SLOT, Arch::OpenRisc) |
|
||||||
|
(R_RISCV_32, Arch::RiscV) |
|
||||||
|
(R_RISCV_JUMP_SLOT, Arch::RiscV) => {
|
||||||
let sym = sym.ok_or("relocation requires an associated symbol")?;
|
let sym = sym.ok_or("relocation requires an associated symbol")?;
|
||||||
let sym_name = self.name_starting_at(sym.st_name as usize)?;
|
let sym_name = self.name_starting_at(sym.st_name as usize)?;
|
||||||
|
|
||||||
|
@ -202,20 +217,7 @@ impl<'a> Library<'a> {
|
||||||
let ehdr = read_unaligned::<Elf32_Ehdr>(data, 0)
|
let ehdr = read_unaligned::<Elf32_Ehdr>(data, 0)
|
||||||
.map_err(|()| "cannot read ELF header")?;
|
.map_err(|()| "cannot read ELF header")?;
|
||||||
|
|
||||||
const IDENT: [u8; EI_NIDENT] = [
|
let arch = arch(&ehdr).ok_or("not a shared library for current architecture")?;
|
||||||
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
|
|
||||||
ELFCLASS32, ELFDATA2MSB, EV_CURRENT, ELFOSABI_NONE,
|
|
||||||
/* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0
|
|
||||||
];
|
|
||||||
|
|
||||||
#[cfg(target_arch = "or1k")]
|
|
||||||
const ARCH: u16 = EM_OPENRISC;
|
|
||||||
#[cfg(not(target_arch = "or1k"))]
|
|
||||||
const ARCH: u16 = EM_NONE;
|
|
||||||
|
|
||||||
if ehdr.e_ident != IDENT || ehdr.e_type != ET_DYN || ehdr.e_machine != ARCH {
|
|
||||||
return Err("not a shared library for current architecture")?
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut dyn_off = None;
|
let mut dyn_off = None;
|
||||||
for i in 0..ehdr.e_phnum {
|
for i in 0..ehdr.e_phnum {
|
||||||
|
@ -314,6 +316,7 @@ impl<'a> Library<'a> {
|
||||||
let library = Library {
|
let library = Library {
|
||||||
image_off: image.as_ptr() as Elf32_Word,
|
image_off: image.as_ptr() as Elf32_Word,
|
||||||
image_sz: image.len(),
|
image_sz: image.len(),
|
||||||
|
arch: arch,
|
||||||
strtab: strtab,
|
strtab: strtab,
|
||||||
symtab: symtab,
|
symtab: symtab,
|
||||||
pltrel: pltrel,
|
pltrel: pltrel,
|
||||||
|
@ -337,3 +340,25 @@ impl<'a> Library<'a> {
|
||||||
Ok(library)
|
Ok(library)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn arch(ehdr: &Elf32_Ehdr) -> Option<Arch> {
|
||||||
|
const IDENT_OPENRISC: [u8; EI_NIDENT] = [
|
||||||
|
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
|
||||||
|
ELFCLASS32, ELFDATA2MSB, EV_CURRENT, ELFOSABI_NONE,
|
||||||
|
/* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0
|
||||||
|
];
|
||||||
|
const IDENT_RISCV: [u8; EI_NIDENT] = [
|
||||||
|
ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3,
|
||||||
|
ELFCLASS32, ELFDATA2LSB, EV_CURRENT, ELFOSABI_NONE,
|
||||||
|
/* ABI version */ 0, /* padding */ 0, 0, 0, 0, 0, 0, 0
|
||||||
|
];
|
||||||
|
match (ehdr.e_ident, ehdr.e_machine) {
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
(IDENT_RISCV, EM_RISCV) => Some(Arch::RiscV),
|
||||||
|
|
||||||
|
#[cfg(target_arch = "or1k")]
|
||||||
|
(IDENT_OPENRISC, EM_OPENRISC) => Some(Arch::OpenRisc),
|
||||||
|
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue