Make use of the kernel's elf loader code instead of duplicating it.
Add placeholder for m68k. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22748 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
0743882d32
commit
7986b7e36d
18
src/system/boot/arch/m68k/Jamfile
Normal file
18
src/system/boot/arch/m68k/Jamfile
Normal file
@ -0,0 +1,18 @@
|
||||
SubDir HAIKU_TOP src system boot arch m68k ;
|
||||
|
||||
{
|
||||
local defines =
|
||||
_BOOT_MODE
|
||||
;
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) -Wall -Wno-multichar ;
|
||||
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
|
||||
}
|
||||
|
||||
KernelMergeObject boot_arch_m68k.o :
|
||||
arch_elf.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles arch_elf.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ;
|
@ -1,7 +1,18 @@
|
||||
SubDir HAIKU_TOP src system boot arch ppc ;
|
||||
|
||||
SubDirC++Flags -fno-rtti ;
|
||||
{
|
||||
local defines =
|
||||
_BOOT_MODE
|
||||
;
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) -Wall -Wno-multichar ;
|
||||
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
|
||||
}
|
||||
|
||||
KernelMergeObject boot_arch_ppc.o :
|
||||
elf.cpp
|
||||
arch_elf.cpp
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles arch_elf.cpp ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ;
|
||||
|
@ -1,385 +0,0 @@
|
||||
/*
|
||||
* Copyright 2005, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
|
||||
* All rights reserved. Distributed under the terms of the MIT License.
|
||||
*/
|
||||
/*
|
||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <boot/arch.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <elf_priv.h>
|
||||
#include <arch/elf.h>
|
||||
|
||||
|
||||
#define CHATTY 0
|
||||
|
||||
|
||||
status_t
|
||||
boot_arch_elf_relocate_rel(struct preloaded_image *image,
|
||||
struct Elf32_Rel *rel, int rel_len)
|
||||
{
|
||||
// there are no rel entries in PPC elf
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write_word32(addr_t P, Elf32_Word value)
|
||||
{
|
||||
*(Elf32_Word*)P = value;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write_word30(addr_t P, Elf32_Word value)
|
||||
{
|
||||
// bits 0:29
|
||||
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0x3) | (value << 2);
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_low24_check(addr_t P, Elf32_Word value)
|
||||
{
|
||||
// bits 6:29
|
||||
if ((value & 0x3f000000) && (~value & 0x3f800000))
|
||||
return false;
|
||||
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0xfc000003)
|
||||
| ((value & 0x00ffffff) << 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_low14_check(addr_t P, Elf32_Word value)
|
||||
{
|
||||
// bits 16:29
|
||||
if ((value & 0x3fffc000) && (~value & 0x3fffe000))
|
||||
return false;
|
||||
*(Elf32_Word*)P = (*(Elf32_Word*)P & 0xffff0003)
|
||||
| ((value & 0x00003fff) << 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
write_half16(addr_t P, Elf32_Word value)
|
||||
{
|
||||
// bits 16:29
|
||||
*(Elf32_Half*)P = (Elf32_Half)value;
|
||||
}
|
||||
|
||||
|
||||
static inline bool
|
||||
write_half16_check(addr_t P, Elf32_Word value)
|
||||
{
|
||||
// bits 16:29
|
||||
if ((value & 0xffff0000) && (~value & 0xffff8000))
|
||||
return false;
|
||||
*(Elf32_Half*)P = (Elf32_Half)value;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline Elf32_Word
|
||||
lo(Elf32_Word value)
|
||||
{
|
||||
return (value & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
static inline Elf32_Word
|
||||
hi(Elf32_Word value)
|
||||
{
|
||||
return ((value >> 16) & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
static inline Elf32_Word
|
||||
ha(Elf32_Word value)
|
||||
{
|
||||
return (((value >> 16) + (value & 0x8000 ? 1 : 0)) & 0xffff);
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
boot_arch_elf_relocate_rela(struct preloaded_image *image,
|
||||
struct Elf32_Rela *rel, int rel_len)
|
||||
{
|
||||
int i;
|
||||
struct Elf32_Sym *sym;
|
||||
int vlErr;
|
||||
addr_t 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(struct Elf32_Rela) < rel_len; i++) {
|
||||
#if CHATTY
|
||||
dprintf("looking at rel type %d, offset 0x%lx, sym 0x%lx, addend 0x%lx\n",
|
||||
ELF32_R_TYPE(rel[i].r_info), rel[i].r_offset, ELF32_R_SYM(rel[i].r_info), rel[i].r_addend);
|
||||
#endif
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_PPC_SECTOFF:
|
||||
case R_PPC_SECTOFF_LO:
|
||||
case R_PPC_SECTOFF_HI:
|
||||
case R_PPC_SECTOFF_HA:
|
||||
dprintf("arch_elf_relocate_rela(): Getting section relative "
|
||||
"symbol addresses not yet supported!\n");
|
||||
return B_ERROR;
|
||||
|
||||
case R_PPC_ADDR32:
|
||||
case R_PPC_ADDR24:
|
||||
case R_PPC_ADDR16:
|
||||
case R_PPC_ADDR16_LO:
|
||||
case R_PPC_ADDR16_HI:
|
||||
case R_PPC_ADDR16_HA:
|
||||
case R_PPC_ADDR14:
|
||||
case R_PPC_ADDR14_BRTAKEN:
|
||||
case R_PPC_ADDR14_BRNTAKEN:
|
||||
case R_PPC_REL24:
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
case R_PPC_GLOB_DAT:
|
||||
case R_PPC_UADDR32:
|
||||
case R_PPC_UADDR16:
|
||||
case R_PPC_REL32:
|
||||
case R_PPC_SDAREL16:
|
||||
case R_PPC_ADDR30:
|
||||
case R_PPC_JMP_SLOT:
|
||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
||||
|
||||
vlErr = boot_elf_resolve_symbol(image, sym, &S);
|
||||
if (vlErr < 0) {
|
||||
dprintf("boot_arch_elf_relocate_rela(): Failed to relocate "
|
||||
"entry index %d, rel type %d, offset 0x%lx, sym 0x%lx, "
|
||||
"addend 0x%lx\n", i, ELF32_R_TYPE(rel[i].r_info),
|
||||
rel[i].r_offset, ELF32_R_SYM(rel[i].r_info),
|
||||
rel[i].r_addend);
|
||||
return vlErr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_PPC_NONE:
|
||||
break;
|
||||
|
||||
case R_PPC_COPY:
|
||||
// TODO: Implement!
|
||||
dprintf("arch_elf_relocate_rela(): R_PPC_COPY not yet "
|
||||
"supported!\n");
|
||||
return B_ERROR;
|
||||
|
||||
case R_PPC_ADDR32:
|
||||
case R_PPC_GLOB_DAT:
|
||||
case R_PPC_UADDR32:
|
||||
write_word32(P, S + A);
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR24:
|
||||
if (write_low24_check(P, (S + A) >> 2))
|
||||
break;
|
||||
dprintf("R_PPC_ADDR24 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_ADDR16:
|
||||
case R_PPC_UADDR16:
|
||||
if (write_half16_check(P, S + A))
|
||||
break;
|
||||
dprintf("R_PPC_ADDR16 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_ADDR16_LO:
|
||||
write_half16(P, lo(S + A));
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16_HI:
|
||||
write_half16(P, hi(S + A));
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR16_HA:
|
||||
write_half16(P, ha(S + A));
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR14:
|
||||
case R_PPC_ADDR14_BRTAKEN:
|
||||
case R_PPC_ADDR14_BRNTAKEN:
|
||||
if (write_low14_check(P, (S + A) >> 2))
|
||||
break;
|
||||
dprintf("R_PPC_ADDR14 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_REL24:
|
||||
if (write_low24_check(P, (S + A - P) >> 2))
|
||||
break;
|
||||
dprintf("R_PPC_REL24 overflow: 0x%lx\n", (S + A - P) >> 2);
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_REL14:
|
||||
case R_PPC_REL14_BRTAKEN:
|
||||
case R_PPC_REL14_BRNTAKEN:
|
||||
if (write_low14_check(P, (S + A - P) >> 2))
|
||||
break;
|
||||
dprintf("R_PPC_REL14 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_GOT16:
|
||||
REQUIRE_GOT;
|
||||
if (write_half16_check(P, G + A))
|
||||
break;
|
||||
dprintf("R_PPC_GOT16 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_GOT16_LO:
|
||||
REQUIRE_GOT;
|
||||
write_half16(P, lo(G + A));
|
||||
break;
|
||||
|
||||
case R_PPC_GOT16_HI:
|
||||
REQUIRE_GOT;
|
||||
write_half16(P, hi(G + A));
|
||||
break;
|
||||
|
||||
case R_PPC_GOT16_HA:
|
||||
REQUIRE_GOT;
|
||||
write_half16(P, ha(G + A));
|
||||
break;
|
||||
|
||||
case R_PPC_JMP_SLOT:
|
||||
{
|
||||
// If the relative offset is small enough, we fabricate a
|
||||
// relative branch instruction ("b <addr>").
|
||||
addr_t jumpOffset = S - P;
|
||||
if ((jumpOffset & 0xfc000000) != 0
|
||||
&& (~jumpOffset & 0xfe000000) != 0) {
|
||||
// Offset > 24 bit.
|
||||
// TODO: Implement!
|
||||
// See System V PPC ABI supplement, p. 5-6!
|
||||
dprintf("arch_elf_relocate_rela(): R_PPC_JMP_SLOT: "
|
||||
"Offsets > 24 bit currently not supported!\n");
|
||||
dprintf("jumpOffset: %p\n", (void*)jumpOffset);
|
||||
return B_ERROR;
|
||||
} else {
|
||||
// Offset <= 24 bit
|
||||
// 0:5 opcode (= 18), 6:29 address, 30 AA, 31 LK
|
||||
// "b" instruction: opcode = 18, AA = 0, LK = 0
|
||||
// address: 24 high-order bits of 26 bit offset
|
||||
*(uint32*)P = 0x48000000 | ((jumpOffset) & 0x03fffffc);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case R_PPC_RELATIVE:
|
||||
write_word32(P, B + A);
|
||||
break;
|
||||
|
||||
case R_PPC_LOCAL24PC:
|
||||
// TODO: Implement!
|
||||
// low24*
|
||||
// if (write_low24_check(P, ?)
|
||||
// break;
|
||||
// return B_BAD_DATA;
|
||||
dprintf("arch_elf_relocate_rela(): R_PPC_LOCAL24PC not yet "
|
||||
"supported!\n");
|
||||
return B_ERROR;
|
||||
|
||||
case R_PPC_REL32:
|
||||
write_word32(P, S + A - P);
|
||||
break;
|
||||
|
||||
case R_PPC_PLTREL24:
|
||||
REQUIRE_PLT;
|
||||
if (write_low24_check(P, (L + A - P) >> 2))
|
||||
break;
|
||||
dprintf("R_PPC_PLTREL24 overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_PLT32:
|
||||
REQUIRE_PLT;
|
||||
write_word32(P, L + A);
|
||||
break;
|
||||
|
||||
case R_PPC_PLTREL32:
|
||||
REQUIRE_PLT;
|
||||
write_word32(P, L + A - P);
|
||||
break;
|
||||
|
||||
case R_PPC_PLT16_LO:
|
||||
REQUIRE_PLT;
|
||||
write_half16(P, lo(L + A));
|
||||
break;
|
||||
|
||||
case R_PPC_PLT16_HI:
|
||||
REQUIRE_PLT;
|
||||
write_half16(P, hi(L + A));
|
||||
break;
|
||||
|
||||
case R_PPC_PLT16_HA:
|
||||
write_half16(P, ha(L + A));
|
||||
break;
|
||||
|
||||
case R_PPC_SDAREL16:
|
||||
// TODO: Implement!
|
||||
// if (write_half16_check(P, S + A - _SDA_BASE_))
|
||||
// break;
|
||||
// return B_BAD_DATA;
|
||||
dprintf("arch_elf_relocate_rela(): R_PPC_SDAREL16 not yet "
|
||||
"supported!\n");
|
||||
return B_ERROR;
|
||||
|
||||
case R_PPC_SECTOFF:
|
||||
if (write_half16_check(P, R + A))
|
||||
break;
|
||||
dprintf("R_PPC_SECTOFF overflow\n");
|
||||
return B_BAD_DATA;
|
||||
|
||||
case R_PPC_SECTOFF_LO:
|
||||
write_half16(P, lo(R + A));
|
||||
break;
|
||||
|
||||
case R_PPC_SECTOFF_HI:
|
||||
write_half16(P, hi(R + A));
|
||||
break;
|
||||
|
||||
case R_PPC_SECTOFF_HA:
|
||||
write_half16(P, ha(R + A));
|
||||
break;
|
||||
|
||||
case R_PPC_ADDR30:
|
||||
write_word30(P, (S + A - P) >> 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintf("arch_elf_relocate_rela: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
@ -1,7 +1,18 @@
|
||||
SubDir HAIKU_TOP src system boot arch x86 ;
|
||||
|
||||
SubDirC++Flags -fno-rtti ;
|
||||
{
|
||||
local defines =
|
||||
_BOOT_MODE
|
||||
;
|
||||
|
||||
defines = [ FDefines $(defines) ] ;
|
||||
SubDirCcFlags $(defines) -Wall -Wno-multichar ;
|
||||
SubDirC++Flags $(defines) -Wall -Wno-multichar -fno-rtti ;
|
||||
}
|
||||
|
||||
KernelMergeObject boot_arch_x86.o :
|
||||
elf.cpp
|
||||
arch_elf.c
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles arch_elf.c ]
|
||||
= [ FDirName $(HAIKU_TOP) src system kernel arch $(TARGET_ARCH) ] ;
|
||||
|
@ -1,135 +0,0 @@
|
||||
/*
|
||||
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
|
||||
#include <boot/arch.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <elf_priv.h>
|
||||
#include <arch/elf.h>
|
||||
|
||||
|
||||
//#define TRACE_ARCH_ELF
|
||||
#ifdef TRACE_ARCH_ELF
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef TRACE_ARCH_ELF
|
||||
static const char *kRelocations[] = {
|
||||
"R_386_NONE",
|
||||
"R_386_32", /* add symbol value */
|
||||
"R_386_PC32", /* add PC relative symbol value */
|
||||
"R_386_GOT32", /* add PC relative GOT offset */
|
||||
"R_386_PLT32", /* add PC relative PLT offset */
|
||||
"R_386_COPY", /* copy data from shared object */
|
||||
"R_386_GLOB_DAT", /* set GOT entry to data address */
|
||||
"R_386_JMP_SLOT", /* set GOT entry to code address */
|
||||
"R_386_RELATIVE", /* add load address of shared object */
|
||||
"R_386_GOTOFF", /* add GOT relative symbol address */
|
||||
"R_386_GOTPC", /* add PC relative GOT table address */
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
status_t
|
||||
boot_arch_elf_relocate_rel(struct preloaded_image *image,
|
||||
struct Elf32_Rel *rel, int rel_len)
|
||||
{
|
||||
struct Elf32_Sym *sym;
|
||||
addr_t S;
|
||||
addr_t A;
|
||||
addr_t P;
|
||||
addr_t final_val;
|
||||
int i;
|
||||
|
||||
S = A = P = 0;
|
||||
|
||||
for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
|
||||
TRACE(("looking at rel type %s, offset 0x%lx\n", kRelocations[ELF32_R_TYPE(rel[i].r_info)], rel[i].r_offset));
|
||||
|
||||
// calc S
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_386_32:
|
||||
case R_386_PC32:
|
||||
case R_386_GLOB_DAT:
|
||||
case R_386_JMP_SLOT:
|
||||
case R_386_GOTOFF:
|
||||
{
|
||||
int vlErr;
|
||||
|
||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
||||
|
||||
vlErr = boot_elf_resolve_symbol(image, sym, &S);
|
||||
if (vlErr < 0)
|
||||
return vlErr;
|
||||
TRACE(("S %p (%s)\n", (void *)S, SYMNAME(image, sym)));
|
||||
}
|
||||
}
|
||||
// calc A
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_386_32:
|
||||
case R_386_PC32:
|
||||
case R_386_GOT32:
|
||||
case R_386_PLT32:
|
||||
case R_386_RELATIVE:
|
||||
case R_386_GOTOFF:
|
||||
case R_386_GOTPC:
|
||||
A = *(addr_t *)(image->text_region.delta + rel[i].r_offset);
|
||||
TRACE(("A %p\n", (void *)A));
|
||||
break;
|
||||
}
|
||||
// calc P
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_386_PC32:
|
||||
case R_386_GOT32:
|
||||
case R_386_PLT32:
|
||||
case R_386_GOTPC:
|
||||
P = image->text_region.delta + rel[i].r_offset;
|
||||
TRACE(("P %p\n", (void *)P));
|
||||
break;
|
||||
}
|
||||
|
||||
switch (ELF32_R_TYPE(rel[i].r_info)) {
|
||||
case R_386_NONE:
|
||||
continue;
|
||||
case R_386_32:
|
||||
final_val = S + A;
|
||||
break;
|
||||
case R_386_PC32:
|
||||
final_val = S + A - P;
|
||||
break;
|
||||
case R_386_RELATIVE:
|
||||
// B + A;
|
||||
final_val = image->text_region.delta + A;
|
||||
break;
|
||||
case R_386_JMP_SLOT:
|
||||
case R_386_GLOB_DAT:
|
||||
final_val = S;
|
||||
break;
|
||||
|
||||
default:
|
||||
dprintf("arch_elf_relocate_rel: unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
|
||||
return EPERM;
|
||||
}
|
||||
*(addr_t *)(image->text_region.delta + rel[i].r_offset) = final_val;
|
||||
TRACE(("-> offset %p = %p\n", (void *)(image->text_region.delta + rel[i].r_offset), (void *)final_val));
|
||||
}
|
||||
|
||||
return B_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
boot_arch_elf_relocate_rela(struct preloaded_image *image,
|
||||
struct Elf32_Rela *rel, int rel_len)
|
||||
{
|
||||
dprintf("arch_elf_relocate_rela: not supported on x86\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user