sparc: implement elf relocation
Needed to load the kernel properly. Change-Id: Iab520398271be2ee3a740af4104960367c3b4ea9 Reviewed-on: https://review.haiku-os.org/c/haiku/+/3585 Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
parent
b992c828cf
commit
76fed28ab1
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2020, Haiku, inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_ARCH_SPARC_ELF_H
|
||||
#define _KERNEL_ARCH_SPARC_ELF_H
|
||||
|
||||
#define R_SPARC_NONE 0
|
||||
#define R_SPARC_8 1
|
||||
#define R_SPARC_16 2
|
||||
#define R_SPARC_32 3
|
||||
#define R_SPARC_DISP8 4
|
||||
#define R_SPARC_DISP16 5
|
||||
#define R_SPARC_DISP32 6
|
||||
#define R_SPARC_WDISP30 7
|
||||
#define R_SPARC_WDISP22 8
|
||||
#define R_SPARC_HI22 9
|
||||
#define R_SPARC_22 10
|
||||
#define R_SPARC_13 11
|
||||
#define R_SPARC_LO10 12
|
||||
#define R_SPARC_GOT10 13
|
||||
#define R_SPARC_GOT13 14
|
||||
#define R_SPARC_GOT22 15
|
||||
#define R_SPARC_PC10 16
|
||||
#define R_SPARC_PC22 17
|
||||
#define R_SPARC_WPLT30 18
|
||||
#define R_SPARC_COPY 19
|
||||
#define R_SPARC_GLOB_DAT 20
|
||||
#define R_SPARC_JMP_SLOT 21
|
||||
#define R_SPARC_RELATIVE 22
|
||||
#define R_SPARC_UA32 23
|
||||
#define R_SPARC_PLT32 24
|
||||
#define R_SPARC_HIPLT22 25
|
||||
#define R_SPARC_LOPLT10 26
|
||||
#define R_SPARC_PCPLT32 27
|
||||
#define R_SPARC_PCPLT22 28
|
||||
#define R_SPARC_PCPLT10 29
|
||||
#define R_SPARC_10 30
|
||||
#define R_SPARC_11 31
|
||||
#define R_SPARC_64 32
|
||||
#define R_SPARC_OLO10 33
|
||||
#define R_SPARC_HH22 34
|
||||
#define R_SPARC_HM10 35
|
||||
#define R_SPARC_LM22 36
|
||||
#define R_SPARC_PC_HH22 37
|
||||
#define R_SPARC_PC_HM10 38
|
||||
#define R_SPARC_PC_LM22 39
|
||||
#define R_SPARC_WDISP16 40
|
||||
#define R_SPARC_WDISP19 41
|
||||
#define R_SPARC_7 43
|
||||
#define R_SPARC_5 44
|
||||
#define R_SPARC_6 45
|
||||
#define R_SPARC_DISP64 46
|
||||
#define R_SPARC_PLT64 47
|
||||
#define R_SPARC_HIX22 48
|
||||
#define R_SPARC_LOX10 49
|
||||
#define R_SPARC_H44 50
|
||||
#define R_SPARC_M44 51
|
||||
#define R_SPARC_L44 52
|
||||
#define R_SPARC_REGISTER 53
|
||||
#define R_SPARC_UA64 54
|
||||
#define R_SPARC_UA16 55
|
||||
#define R_SPARC_GOTDATA_HIX22 80
|
||||
#define R_SPARC_GOTDATA_LOX10 81
|
||||
#define R_SPARC_GOTDATA_OP_HIX22 82
|
||||
#define R_SPARC_GOTDATA_OP_LOX10 83
|
||||
#define R_SPARC_GOTDATA_OP 84
|
||||
#define R_SPARC_H34 85
|
||||
#define R_SPARC_SIZE32 86
|
||||
#define R_SPARC_SIZE64 87
|
||||
|
||||
#endif /* _KERNEL_ARCH_SPARC_ELF_H */
|
@ -1,5 +1,7 @@
|
||||
SubDir HAIKU_TOP src system kernel arch sparc ;
|
||||
|
||||
UsePrivateKernelHeaders ;
|
||||
|
||||
KernelMergeObject kernel_arch_sparc.o :
|
||||
arch_asm.S
|
||||
arch_commpage.cpp
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2019, Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Copyright 2019-2020, Adrien Destugues <pulkomandy@pulkomandy.tk>
|
||||
* Copyright 2010, Ithamar R. Adema <ithamar.adema@team-embedded.nl>
|
||||
* Copyright 2009, Johannes Wischert, johanneswi@gmail.com.
|
||||
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
|
||||
@ -11,6 +11,7 @@
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <elf_priv.h>
|
||||
#include <boot/elf.h>
|
||||
#include <arch/elf.h>
|
||||
|
||||
|
||||
@ -52,48 +53,37 @@ arch_elf_relocate_rel(struct elf_image_info *image,
|
||||
|
||||
|
||||
static inline void
|
||||
write_32(addr_t P, Elf32_Word value)
|
||||
write_word32(addr_t P, Elf64_Word value)
|
||||
{
|
||||
*(Elf32_Word*)P = value;
|
||||
*(Elf64_Word*)P = value;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write_16(addr_t P, Elf32_Word value)
|
||||
write_word64(addr_t P, Elf64_Xword value)
|
||||
{
|
||||
// bits 16:29
|
||||
*(Elf32_Half*)P = (Elf32_Half)value;
|
||||
*(Elf64_Xword*)P = value;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_16_check(addr_t P, Elf32_Word value)
|
||||
static inline void
|
||||
write_hi30(addr_t P, Elf64_Word value)
|
||||
{
|
||||
// bits 15:0
|
||||
if ((value & 0xffff0000) && (~value & 0xffff8000))
|
||||
return false;
|
||||
*(Elf32_Half*)P = (Elf32_Half)value;
|
||||
return true;
|
||||
*(Elf64_Word*)P |= value >> 2;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_8(addr_t P, Elf32_Word value)
|
||||
static inline void
|
||||
write_hi22(addr_t P, Elf64_Word value)
|
||||
{
|
||||
// bits 7:0
|
||||
*(uint8 *)P = (uint8)value;
|
||||
return true;
|
||||
*(Elf64_Word*)P |= value >> 10;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_8_check(addr_t P, Elf32_Word value)
|
||||
static inline void
|
||||
write_lo10(addr_t P, Elf64_Word value)
|
||||
{
|
||||
// bits 7:0
|
||||
if ((value & 0xffffff00) && (~value & 0xffffff80))
|
||||
return false;
|
||||
*(uint8 *)P = (uint8)value;
|
||||
return true;
|
||||
*(Elf64_Word*)P |= value & 0x3ff;
|
||||
}
|
||||
|
||||
|
||||
@ -107,5 +97,140 @@ arch_elf_relocate_rela(struct elf_image_info *image,
|
||||
struct elf_image_info *resolve_image, Elf64_Rela *rel, int rel_len)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
Elf64_Sym *sym;
|
||||
int vlErr;
|
||||
|
||||
Elf64_Addr S = 0; // symbol address
|
||||
//addr_t R = 0; // section relative symbol address
|
||||
|
||||
//addr_t G = 0; // GOT address
|
||||
//addr_t L = 0; // PLT address
|
||||
|
||||
#define P ((addr_t)(image->text_region.delta + rel[i].r_offset))
|
||||
#define A ((addr_t)rel[i].r_addend)
|
||||
#define B (image->text_region.delta)
|
||||
|
||||
// TODO: Get the GOT address!
|
||||
#define REQUIRE_GOT \
|
||||
if (G == 0) { \
|
||||
dprintf("arch_elf_relocate_rela(): Failed to get GOT address!\n"); \
|
||||
return B_ERROR; \
|
||||
}
|
||||
|
||||
// TODO: Get the PLT address!
|
||||
#define REQUIRE_PLT \
|
||||
if (L == 0) { \
|
||||
dprintf("arch_elf_relocate_rela(): Failed to get PLT address!\n"); \
|
||||
return B_ERROR; \
|
||||
}
|
||||
|
||||
for (i = 0; i * (int)sizeof(Elf64_Rela) < rel_len; i++) {
|
||||
#if CHATTY
|
||||
dprintf("looking at rel type %" PRIu64 ", offset 0x%lx, sym 0x%lx, "
|
||||
"addend 0x%lx\n", ELF64_R_TYPE(rel[i].r_info), rel[i].r_offset,
|
||||
ELF64_R_SYM(rel[i].r_info), rel[i].r_addend);
|
||||
#endif
|
||||
// Relocation types and what to do with them are defined in Oracle docs
|
||||
// Documentation Home > Linker and Libraries Guide
|
||||
// > Chapter 7 Object File Format > File Format > Relocation Sections
|
||||
// > Relocation Types (Processor-Specific) > SPARC: Relocation Types
|
||||
// https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-24/index.html
|
||||
// https://docs.oracle.com/cd/E19120-01/open.solaris/819-0690/chapter6-24-1/index.html
|
||||
switch (ELF64_R_TYPE(rel[i].r_info)) {
|
||||
case R_SPARC_WDISP30:
|
||||
case R_SPARC_HI22:
|
||||
case R_SPARC_LO10:
|
||||
case R_SPARC_GLOB_DAT:
|
||||
case R_SPARC_JMP_SLOT:
|
||||
case R_SPARC_64:
|
||||
sym = SYMBOL(image, ELF64_R_SYM(rel[i].r_info));
|
||||
#ifdef _BOOT_MODE
|
||||
vlErr = boot_elf_resolve_symbol(image, sym, &S);
|
||||
#else
|
||||
vlErr = elf_resolve_symbol(image, sym, resolve_image, &S);
|
||||
#endif
|
||||
if (vlErr < 0) {
|
||||
dprintf("%s(): Failed to relocate "
|
||||
"entry index %d, rel type %" PRIu64 ", offset 0x%lx, "
|
||||
"sym 0x%lx, addend 0x%lx\n", __FUNCTION__, i,
|
||||
ELF64_R_TYPE(rel[i].r_info),
|
||||
rel[i].r_offset, ELF64_R_SYM(rel[i].r_info),
|
||||
rel[i].r_addend);
|
||||
return vlErr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ELF64_R_TYPE(rel[i].r_info)) {
|
||||
case R_SPARC_WDISP30:
|
||||
{
|
||||
write_hi30(P, S + A - P);
|
||||
}
|
||||
case R_SPARC_HI22:
|
||||
{
|
||||
write_hi22(P, S + A);
|
||||
break;
|
||||
}
|
||||
case R_SPARC_LO10:
|
||||
{
|
||||
write_lo10(P, S + A);
|
||||
break;
|
||||
}
|
||||
case R_SPARC_GLOB_DAT:
|
||||
{
|
||||
write_word64(P, S + A);
|
||||
break;
|
||||
}
|
||||
case R_SPARC_JMP_SLOT:
|
||||
{
|
||||
// Created by the link-editor for dynamic objects to provide
|
||||
// lazy binding. The relocation offset member gives the
|
||||
// location of a procedure linkage table entry. The runtime
|
||||
// linker modifies the procedure linkage table entry to
|
||||
// transfer control to the designated symbol address.
|
||||
addr_t jumpOffset = S - (P + 8);
|
||||
if ((jumpOffset & 0xc0000000) != 0
|
||||
&& (~jumpOffset & 0xc0000000) != 0) {
|
||||
// Offset > 30 bit.
|
||||
// TODO: Implement!
|
||||
// See https://docs.oracle.com/cd/E26502_01/html/E26507/chapter6-1235.html
|
||||
// examples .PLT102 and .PLT103
|
||||
dprintf("arch_elf_relocate_rela(): R_SPARC_JMP_SLOT: "
|
||||
"Offsets > 30 bit currently not supported!\n");
|
||||
dprintf("jumpOffset: %p\n", (void*)jumpOffset);
|
||||
return B_ERROR;
|
||||
} else {
|
||||
uint32* instructions = (uint32*)P;
|
||||
// We need to use a call instruction because it has a lot
|
||||
// of space for the destination (30 bits). However, it
|
||||
// erases o7, which we don't want.
|
||||
// We could avoid this with a JMPL if the displacement was
|
||||
// small enough, but it probably isn't.
|
||||
// So, we store o7 in g1 before the call, and restore it
|
||||
// in the branch delay slot. Crazy, but it works!
|
||||
instructions[0] = 0x01000000; // NOP to preserve the alignment?
|
||||
instructions[1] = 0x8210000f; // MOV %o7, %g1
|
||||
instructions[2] = 0x40000000 | ((jumpOffset >> 2) & 0x3fffffff);
|
||||
instructions[3] = 0x9e100001; // MOV %g1, %o7
|
||||
}
|
||||
break;
|
||||
}
|
||||
case R_SPARC_RELATIVE:
|
||||
{
|
||||
write_word32(P, B + A);
|
||||
break;
|
||||
}
|
||||
case R_SPARC_64:
|
||||
{
|
||||
write_word64(P, S + A);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dprintf("arch_elf_relocate_rela: unhandled relocation type %"
|
||||
PRIu64 "\n", ELF64_R_TYPE(rel[i].r_info));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user