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:
parent
7747cd8133
commit
ed5c11d75a
@ -4,6 +4,7 @@ KernelStaticLibrary libx86 :
|
||||
<$(SOURCE_GRIST)>arch_cpu.c
|
||||
<$(SOURCE_GRIST)>arch_dbg_console.c
|
||||
<$(SOURCE_GRIST)>arch_debug.c
|
||||
<$(SOURCE_GRIST)>arch_elf.c
|
||||
<$(SOURCE_GRIST)>arch_faults.c
|
||||
<$(SOURCE_GRIST)>arch_int.c
|
||||
<$(SOURCE_GRIST)>arch_selector.c
|
||||
|
114
src/kernel/core/arch/x86/arch_elf.c
Normal file
114
src/kernel/core/arch/x86/arch_elf.c
Normal file
@ -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;
|
||||
}
|
||||
|
@ -18,8 +18,8 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <arch/cpu.h>
|
||||
|
||||
#include <elf32.h>
|
||||
#include <arch/elf.h>
|
||||
#include <elf_priv.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@ -27,41 +27,12 @@
|
||||
#define ELF_TRACE 0
|
||||
#if ELF_TRACE
|
||||
# define PRINT(x) dprintf x
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define PRINT(x)
|
||||
# define PRINT(x) ;
|
||||
# define TRACE(x) ;
|
||||
#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
|
||||
// (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 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
|
||||
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(" rela %p\n", image->rela);
|
||||
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
|
||||
@ -401,13 +367,16 @@ elf_parse_dynamic_section(struct elf_image_info *image)
|
||||
case DT_RELASZ:
|
||||
image->rela_len = d[i].d_un.d_val;
|
||||
break;
|
||||
// TK: procedure linkage table
|
||||
case DT_JMPREL:
|
||||
image->pltrel = (struct Elf32_Rel *)(d[i].d_un.d_ptr + image->regions[0].delta);
|
||||
break;
|
||||
case DT_PLTRELSZ:
|
||||
image->pltrel_len = d[i].d_un.d_val;
|
||||
break;
|
||||
case DT_PLTREL:
|
||||
image->pltrel_type = d[i].d_un.d_val;
|
||||
break;
|
||||
|
||||
default:
|
||||
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
|
||||
* it tries to link against the shared_image
|
||||
* XXX gross hack and needs to be done better
|
||||
/** 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
|
||||
* 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)
|
||||
{
|
||||
struct Elf32_Sym *sym2;
|
||||
@ -462,10 +431,10 @@ elf_resolve_symbol(struct elf_image_info *image, struct Elf32_Sym *sym, struct e
|
||||
}
|
||||
|
||||
*sym_addr = sym2->st_value + shared_image->regions[0].delta;
|
||||
return B_NO_ERROR;
|
||||
return B_NO_ERROR;
|
||||
case SHN_ABS:
|
||||
*sym_addr = sym->st_value;
|
||||
return B_NO_ERROR;
|
||||
return B_NO_ERROR;
|
||||
case SHN_COMMON:
|
||||
// XXX finish this
|
||||
PRINT(("elf_resolve_symbol: COMMON symbol, finish me!\n"));
|
||||
@ -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
|
||||
|
||||
static int
|
||||
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"));
|
||||
|
||||
// deal with the rels first
|
||||
if (image->rel) {
|
||||
dprintf("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)
|
||||
return res;
|
||||
TRACE(("total %i relocs\n", image->rel_len / (int)sizeof(struct Elf32_Rel)));
|
||||
|
||||
status = arch_elf_relocate_rel(image, sym_prepend, kernel_image, image->rel, image->rel_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
|
||||
if (image->pltrel) {
|
||||
dprintf("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);
|
||||
TRACE(("total %i plt-relocs\n", image->pltrel_len / (int)sizeof(struct Elf32_Rel)));
|
||||
|
||||
if (res)
|
||||
return res;
|
||||
if (image->pltrel_type == DT_REL)
|
||||
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 ELF_TRACE
|
||||
int i;
|
||||
for(i = 1; i * (int)sizeof(struct Elf32_Rela) < image->rela_len; i++) {
|
||||
dprintf("rela: type %d\n", ELF32_R_TYPE(image->rela[i].r_info));
|
||||
}
|
||||
#endif
|
||||
dprintf("RELA relocations not supported\n");
|
||||
return EPERM;
|
||||
status = arch_elf_relocate_rela(image, sym_prepend, kernel_image, image->rela, image->rela_len);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
}
|
||||
return res;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user