Included NewOS change 1674 - moved architecture dependent part of elf.c
to the correct location. git-svn-id: file:///srv/svn/repos/haiku/trunk/current@2319 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -4,6 +4,7 @@ KernelStaticLibrary libx86 :
|
|||||||
<$(SOURCE_GRIST)>arch_cpu.c
|
<$(SOURCE_GRIST)>arch_cpu.c
|
||||||
<$(SOURCE_GRIST)>arch_dbg_console.c
|
<$(SOURCE_GRIST)>arch_dbg_console.c
|
||||||
<$(SOURCE_GRIST)>arch_debug.c
|
<$(SOURCE_GRIST)>arch_debug.c
|
||||||
|
<$(SOURCE_GRIST)>arch_elf.c
|
||||||
<$(SOURCE_GRIST)>arch_faults.c
|
<$(SOURCE_GRIST)>arch_faults.c
|
||||||
<$(SOURCE_GRIST)>arch_int.c
|
<$(SOURCE_GRIST)>arch_int.c
|
||||||
<$(SOURCE_GRIST)>arch_selector.c
|
<$(SOURCE_GRIST)>arch_selector.c
|
||||||
|
|||||||
@@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
** Copyright 2002, Travis Geiselbrecht. All rights reserved.
|
||||||
|
** Distributed under the terms of the NewOS License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <KernelExport.h>
|
||||||
|
|
||||||
|
#include <elf_priv.h>
|
||||||
|
#include <arch/elf.h>
|
||||||
|
|
||||||
|
#define ELF_TRACE 0
|
||||||
|
#if ELF_TRACE
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
|
#else
|
||||||
|
# define TRACE(x) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
arch_elf_relocate_rel(struct elf_image_info *image, const char *sym_prepend,
|
||||||
|
struct elf_image_info *resolve_image, struct Elf32_Rel *rel, int rel_len)
|
||||||
|
{
|
||||||
|
struct Elf32_Sym *sym;
|
||||||
|
addr S;
|
||||||
|
addr A;
|
||||||
|
addr P;
|
||||||
|
addr 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 %d, offset 0x%x\n", 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 = elf_resolve_symbol(image, sym, resolve_image, sym_prepend, &S);
|
||||||
|
if (vlErr < 0)
|
||||||
|
return vlErr;
|
||||||
|
TRACE(("S %p\n", (void *)S));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 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 *)(image->regions[0].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->regions[0].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->regions[0].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 *)(image->regions[0].delta + rel[i].r_offset) = final_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_NO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
arch_elf_relocate_rela(struct elf_image_info *image, const char *sym_prepend,
|
||||||
|
struct elf_image_info *resolve_image, struct Elf32_Rela *rel, int rel_len)
|
||||||
|
{
|
||||||
|
dprintf("arch_elf_relocate_rela: not supported on x86\n");
|
||||||
|
return B_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
+31
-145
@@ -18,8 +18,8 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <arch/cpu.h>
|
#include <arch/cpu.h>
|
||||||
|
#include <arch/elf.h>
|
||||||
#include <elf32.h>
|
#include <elf_priv.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -27,41 +27,12 @@
|
|||||||
#define ELF_TRACE 0
|
#define ELF_TRACE 0
|
||||||
#if ELF_TRACE
|
#if ELF_TRACE
|
||||||
# define PRINT(x) dprintf x
|
# define PRINT(x) dprintf x
|
||||||
|
# define TRACE(x) dprintf x
|
||||||
#else
|
#else
|
||||||
# define PRINT(x)
|
# define PRINT(x) ;
|
||||||
|
# define TRACE(x) ;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct elf_region {
|
|
||||||
region_id id;
|
|
||||||
addr start;
|
|
||||||
addr size;
|
|
||||||
long delta;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct elf_image_info {
|
|
||||||
struct elf_image_info *next;
|
|
||||||
char *name;
|
|
||||||
image_id id;
|
|
||||||
int32 ref_count;
|
|
||||||
void *vnode;
|
|
||||||
struct elf_region regions[2]; // describes the text and data regions
|
|
||||||
addr dynamic_ptr; // pointer to the dynamic section
|
|
||||||
struct elf_linked_image *linked_images;
|
|
||||||
|
|
||||||
struct Elf32_Ehdr *eheader;
|
|
||||||
|
|
||||||
// pointer to symbol participation data structures
|
|
||||||
char *needed;
|
|
||||||
unsigned int *symhash;
|
|
||||||
struct Elf32_Sym *syms;
|
|
||||||
char *strtab;
|
|
||||||
struct Elf32_Rel *rel;
|
|
||||||
int rel_len;
|
|
||||||
struct Elf32_Rela *rela;
|
|
||||||
int rela_len;
|
|
||||||
struct Elf32_Rel *pltrel;
|
|
||||||
int pltrel_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
// XXX TK this shall contain a list of linked images
|
// XXX TK this shall contain a list of linked images
|
||||||
// (don't know enough about ELF how to get this list)
|
// (don't know enough about ELF how to get this list)
|
||||||
@@ -76,13 +47,6 @@ static mutex image_lock;
|
|||||||
static mutex image_load_lock;
|
static mutex image_load_lock;
|
||||||
static image_id next_image_id = 0;
|
static image_id next_image_id = 0;
|
||||||
|
|
||||||
#define STRING(image, offset) ((char *)(&(image)->strtab[(offset)]))
|
|
||||||
#define SYMNAME(image, sym) STRING(image, (sym)->st_name)
|
|
||||||
#define SYMBOL(image, num) ((struct Elf32_Sym *)&(image)->syms[num])
|
|
||||||
#define HASHTABSIZE(image) ((image)->symhash[0])
|
|
||||||
#define HASHBUCKETS(image) ((unsigned int *)&(image)->symhash[2])
|
|
||||||
#define HASHCHAINS(image) ((unsigned int *)&(image)->symhash[2+HASHTABSIZE(image)])
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
|
elf_lookup_symbol_address(addr address, addr *baseAddress, char *text, size_t length)
|
||||||
@@ -296,6 +260,8 @@ dump_image_info(struct elf_image_info *image)
|
|||||||
dprintf(" rel_len 0x%x\n", image->rel_len);
|
dprintf(" rel_len 0x%x\n", image->rel_len);
|
||||||
dprintf(" rela %p\n", image->rela);
|
dprintf(" rela %p\n", image->rela);
|
||||||
dprintf(" rela_len 0x%x\n", image->rela_len);
|
dprintf(" rela_len 0x%x\n", image->rela_len);
|
||||||
|
dprintf(" pltrel %p\n", image->pltrel);
|
||||||
|
dprintf(" pltrel_len 0x%x\n", image->pltrel_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX - Currently unused
|
/* XXX - Currently unused
|
||||||
@@ -401,13 +367,16 @@ elf_parse_dynamic_section(struct elf_image_info *image)
|
|||||||
case DT_RELASZ:
|
case DT_RELASZ:
|
||||||
image->rela_len = d[i].d_un.d_val;
|
image->rela_len = d[i].d_un.d_val;
|
||||||
break;
|
break;
|
||||||
// TK: procedure linkage table
|
|
||||||
case DT_JMPREL:
|
case DT_JMPREL:
|
||||||
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
||||||
break;
|
break;
|
||||||
case DT_PLTRELSZ:
|
case DT_PLTRELSZ:
|
||||||
image->pltrel_len = d[i].d_un.d_val;
|
image->pltrel_len = d[i].d_un.d_val;
|
||||||
break;
|
break;
|
||||||
|
case DT_PLTREL:
|
||||||
|
image->pltrel_type = d[i].d_un.d_val;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -426,12 +395,12 @@ elf_parse_dynamic_section(struct elf_image_info *image)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* this function first tries to see if the first image and it's already resolved symbol is okay, otherwise
|
/** this function first tries to see if the first image and it's already resolved symbol is okay, otherwise
|
||||||
* it tries to link against the shared_image
|
* it tries to link against the shared_image
|
||||||
* XXX gross hack and needs to be done better
|
* XXX gross hack and needs to be done better
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
int
|
||||||
elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct elf_image_info *shared_image, const char *sym_prepend,addr *sym_addr)
|
elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct elf_image_info *shared_image, const char *sym_prepend,addr *sym_addr)
|
||||||
{
|
{
|
||||||
struct Elf32_Sym *sym2;
|
struct Elf32_Sym *sym2;
|
||||||
@@ -478,125 +447,42 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct e
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
elf_relocate_rel(struct elf_image_info *image, const char *sym_prepend,
|
|
||||||
struct Elf32_Rel *rel, int rel_len )
|
|
||||||
{
|
|
||||||
struct Elf32_Sym *sym;
|
|
||||||
int vlErr;
|
|
||||||
addr S;
|
|
||||||
addr A;
|
|
||||||
addr P;
|
|
||||||
addr final_val;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
S = A = P = 0;
|
|
||||||
|
|
||||||
for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
|
|
||||||
PRINT(("looking at rel type %d, offset 0x%x\n", 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:
|
|
||||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
|
||||||
|
|
||||||
vlErr = elf_resolve_symbol(image, sym, kernel_image, sym_prepend, &S);
|
|
||||||
if (vlErr < 0)
|
|
||||||
return vlErr;
|
|
||||||
PRINT(("S %p\n", (void *)S));
|
|
||||||
}
|
|
||||||
// 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 *)(image->regions[0].delta + rel[i].r_offset);
|
|
||||||
PRINT(("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->regions[0].delta + rel[i].r_offset;
|
|
||||||
PRINT(("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->regions[0].delta + A;
|
|
||||||
break;
|
|
||||||
case R_386_JMP_SLOT:
|
|
||||||
case R_386_GLOB_DAT:
|
|
||||||
final_val = S;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dprintf("unhandled relocation type %d\n", ELF32_R_TYPE(rel[i].r_info));
|
|
||||||
return EPERM;
|
|
||||||
}
|
|
||||||
*(addr *)(image->regions[0].delta + rel[i].r_offset) = final_val;
|
|
||||||
}
|
|
||||||
|
|
||||||
return B_NO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// XXX for now just link against the kernel
|
// XXX for now just link against the kernel
|
||||||
|
|
||||||
static int
|
static int
|
||||||
elf_relocate(struct elf_image_info *image, const char *sym_prepend)
|
elf_relocate(struct elf_image_info *image, const char *sym_prepend)
|
||||||
{
|
{
|
||||||
int res = B_NO_ERROR;
|
int status = B_NO_ERROR;
|
||||||
|
|
||||||
PRINT(("top of elf_relocate\n"));
|
PRINT(("top of elf_relocate\n"));
|
||||||
|
|
||||||
// deal with the rels first
|
// deal with the rels first
|
||||||
if (image->rel) {
|
if (image->rel) {
|
||||||
dprintf("total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel));
|
TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel)));
|
||||||
res = elf_relocate_rel(image, sym_prepend, image->rel, image->rel_len);
|
|
||||||
|
|
||||||
if (res)
|
status = arch_elf_relocate_rel(image, sym_prepend, kernel_image, image->rel, image->rel_len);
|
||||||
return res;
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->pltrel) {
|
if (image->pltrel) {
|
||||||
dprintf("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel));
|
TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
|
||||||
res = elf_relocate_rel(image, sym_prepend, image->pltrel, image->pltrel_len);
|
|
||||||
|
|
||||||
if (res)
|
if (image->pltrel_type == DT_REL)
|
||||||
return res;
|
status = arch_elf_relocate_rel(image, sym_prepend, kernel_image, image->pltrel, image->pltrel_len);
|
||||||
|
else
|
||||||
|
status = arch_elf_relocate_rela(image, sym_prepend, kernel_image, (struct Elf32_Rela *)image->pltrel, image->pltrel_len);
|
||||||
|
if (status < B_OK)
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (image->rela) {
|
if (image->rela) {
|
||||||
#if ELF_TRACE
|
status = arch_elf_relocate_rela(image, sym_prepend, kernel_image, image->rela, image->rela_len);
|
||||||
int i;
|
if (status < B_OK)
|
||||||
for(i = 1; i * (int)sizeof(struct Elf32_Rela) < image->rela_len; i++) {
|
return status;
|
||||||
dprintf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info));
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
dprintf("RELA relocations not supported\n");
|
return status;
|
||||||
return EPERM;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user