diff options
author | Artur Grabowski <art@cvs.openbsd.org> | 2001-05-31 13:26:52 +0000 |
---|---|---|
committer | Artur Grabowski <art@cvs.openbsd.org> | 2001-05-31 13:26:52 +0000 |
commit | 670a54c0a370c42e737347f4db1c42188048b584 (patch) | |
tree | 73c2c58f2601362cbf2475a84c130b258e96c3ff /libexec/ld.so | |
parent | 19edfb207949d42d36a91376924d9319bfc7473f (diff) |
Correctly implement most linking for alpha.
Remove a lot of code copied from powerpc.
Diffstat (limited to 'libexec/ld.so')
-rw-r--r-- | libexec/ld.so/alpha/archdep.h | 50 | ||||
-rw-r--r-- | libexec/ld.so/alpha/rtld_machine.c | 266 |
2 files changed, 53 insertions, 263 deletions
diff --git a/libexec/ld.so/alpha/archdep.h b/libexec/ld.so/alpha/archdep.h index 49846926455..365d4c38260 100644 --- a/libexec/ld.so/alpha/archdep.h +++ b/libexec/ld.so/alpha/archdep.h @@ -1,4 +1,4 @@ -/* $OpenBSD: archdep.h,v 1.1 2001/05/14 22:18:20 niklas Exp $ */ +/* $OpenBSD: archdep.h,v 1.2 2001/05/31 13:26:09 art Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -52,11 +52,6 @@ int _dl_write __P((int, const char *, int)); * be used before bootstrap linking has been finished. */ static inline void -_dl_dcbf(Elf64_Addr *addr) -{ -} - -static inline void _dl_wrstderr(const char *s) { while(*s) { @@ -131,34 +126,23 @@ _dl_strchr(const char *p, const int c) } static inline void -RELOC_RELA(Elf64_Rela *r, - const Elf64_Sym *s, Elf64_Addr *p, int v) +RELOC_RELA(Elf64_Rela *r, const Elf64_Sym *s, Elf64_Addr *p, unsigned long v) { - if(ELF64_R_TYPE((r)->r_info) == RELOC_RELATIVE) { - if((ELF64_ST_BIND((s)->st_info) == STB_LOCAL) && - ((ELF64_ST_TYPE((s)->st_info) == STT_SECTION) || - (ELF64_ST_TYPE((s)->st_info) == STT_NOTYPE)) ) { - *(p) = (v) + (r)->r_addend; - } else { - *(p) = (v) + (s)->st_value + (r)->r_addend; - } - } else if(ELF64_R_TYPE((r)->r_info) == RELOC_JMP_SLOT) { - Elf64_Addr val = (v) + (s)->st_value + (r)->r_addend - - (Elf64_Addr)(p); - if (((val & 0xfe000000) != 0) && - ((val & 0xfe000000) != 0xfe000000)) - { - /* invalid offset */ - _dl_exit(20); - } - val &= ~0xfc000000; - val |= 0x48000000; - *(p) = val; - _dl_dcbf(p); - } else if(ELF64_R_TYPE((r)->r_info) == RELOC_GLOB_DAT) { - *(p) = (v) + (s)->st_value + (r)->r_addend; - } else { - /* error */ + extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; + + if(ELF64_R_TYPE(r->r_info) == RELOC_RELATIVE) { + if ((caddr_t)p < (caddr_t)_GLOBAL_OFFSET_TABLE_ || + (caddr_t)p >= (caddr_t)&_DYNAMIC) + *p += (Elf_Addr)v; + } else if(ELF64_R_TYPE(r->r_info) == RELOC_JMP_SLOT) { + Elf64_Addr val = v + s->st_value + r->r_addend - + (Elf64_Addr)(p); + *p = val; + __asm __volatile("imb" : : : "memory"); + } else if(ELF64_R_TYPE(r->r_info) == RELOC_GLOB_DAT) { + *p = v + s->st_value + r->r_addend; + } else { + _dl_printf("unknown bootstrap relocation\n"); } } diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c index 3ce9c1dc4d0..dfdb2ac92a9 100644 --- a/libexec/ld.so/alpha/rtld_machine.c +++ b/libexec/ld.so/alpha/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.1 2001/05/14 22:18:21 niklas Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.2 2001/05/31 13:26:51 art Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -62,69 +62,29 @@ _dl_bcopy(void *src, void *dest, int size) int _dl_md_reloc(elf_object_t *object, int rel, int relasz) { - int i; - int numrela; - int fails = 0; + long i; + long numrela; + long fails = 0; Elf64_Addr loff; Elf64_Rela *relas; - /* for jmp table relocations */ - Elf64_Addr *pltcall; - Elf64_Addr *plttable; - - Elf64_Addr * first_rela; loff = object->load_offs; numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela); relas = (Elf64_Rela *)(object->Dyn.info[rel]); -#ifdef DL_PRINTF_DEBUG -_dl_printf("loff 0x%lx object relocation size %x, numrela %x\n", loff, - object->Dyn.info[relasz], numrela); -#endif - - if((object->status & STAT_RELOC_DONE) || !relas) { + if ((object->status & STAT_RELOC_DONE) || !relas) { return(0); } - /* for plt relocation usage */ - if (object->Dyn.info[DT_JMPREL] != 0) { - /* resolver stub not set up */ - Elf64_Addr val; - - first_rela = (Elf64_Addr *) - (((Elf64_Rela *)(object->Dyn.info[DT_JMPREL]))->r_offset - + loff); - /* Need to construct table to do jumps */ - pltcall = (Elf64_Addr *)(first_rela) - 12; -#ifdef DL_PRINTF_DEBUG -_dl_printf("creating pltcall at %p\n", pltcall); -_dl_printf("md_reloc( jumprel %p\n", first_rela ); -#endif - plttable = (Elf64_Addr *) - ((Elf64_Addr)first_rela) + (2 * - (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf64_Rela)) - ); - -#ifdef DL_PRINTF_DEBUG -_dl_printf("md_reloc: plttbl size %x\n", - (object->Dyn.info[DT_PLTRELSZ]/sizeof(Elf64_Rela)) -); -_dl_printf("md_reloc: plttable %p\n", plttable); -#endif - } else { - first_rela = NULL; - } - for(i = 0; i < numrela; i++, relas++) { - Elf64_Addr *r_addr = (Elf64_Addr *)(relas->r_offset + loff); + for (i = 0; i < numrela; i++, relas++) { + Elf64_Addr *r_addr; Elf64_Addr ooff; const Elf64_Sym *sym, *this; const char *symn; -#if 0 -_dl_printf("%d offset 0x%lx info 0x%lx addend 0x%lx\n", i, relas->r_offset, relas->r_info, relas->r_addend); -#endif + r_addr = (Elf64_Addr *)(relas->r_offset + loff); - if(ELF64_R_SYM(relas->r_info) == 0xffffff) { + if (ELF64_R_SYM(relas->r_info) == 0xffffffff) { continue; } @@ -133,180 +93,37 @@ _dl_printf("%d offset 0x%lx info 0x%lx addend 0x%lx\n", i, relas->r_offset, rela this = sym; symn = object->dyn.strtab + sym->st_name; - if(ELF64_R_SYM(relas->r_info) && - !(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && - ELF64_ST_TYPE (sym->st_info) == STT_NOTYPE)) { - - ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); - if(!this && ELF64_ST_BIND(sym->st_info) == STB_GLOBAL) { - _dl_printf("%s:" - " %s :can't resolve reference '%s'\n", - _dl_progname, object->load_name, - symn); - fails++; - } - - } - -#if 0 -_dl_printf("reloc %d\n", ELF64_R_TYPE(relas->r_info)); -#endif - switch(ELF64_R_TYPE(relas->r_info)) { -#if 1 + switch (ELF64_R_TYPE(relas->r_info)) { case R_TYPE(REFQUAD): - if(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && - (ELF64_ST_TYPE(sym->st_info) == STT_SECTION || - ELF64_ST_TYPE(sym->st_info) == STT_NOTYPE) ) { - *r_addr = ooff + relas->r_addend; - } else { - *r_addr = ooff + this->st_value + - relas->r_addend; - } + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if (this == NULL) + goto resolve_failed; + *r_addr += ooff + this->st_value + relas->r_addend; break; -#endif case R_TYPE(RELATIVE): #if 0 -_dl_printf("sym info %d r_addr %p relas %p\n", sym->st_info, r_addr, relas); -#endif - if(ELF64_ST_BIND(sym->st_info) == STB_LOCAL && - (ELF64_ST_TYPE(sym->st_info) == STT_SECTION || - ELF64_ST_TYPE(sym->st_info) == STT_NOTYPE) ) { -#if 0 -_dl_printf("addend 0x%lx\n", relas->r_addend); -_dl_printf("*r_addr 0x%lx\n", *r_addr); -#endif - *r_addr = loff + relas->r_addend; -#if 0 -_dl_printf("*r_addr 0x%lx\n", *r_addr); -#endif - -#ifdef DL_PRINTF_DEBUG -_dl_printf("rel1 r_addr %p val %lx loff %lx ooff %lx addend %lx\n", r_addr, -loff + relas->r_addend, loff, ooff, relas->r_addend); -#endif - - } else { -#if 0 -_dl_printf("this %p\n", this); + if ((caddr_t)r_addr < (caddr_t)_GLOBAL_OFFSET_TABLE_ || + (caddr_t)r_addr >= (caddr_t)&_DYNAMIC) #endif - *r_addr = loff + this->st_value + - relas->r_addend; - } + *r_addr += loff; break; case R_TYPE(JMP_SLOT): - { - Elf64_Addr val = ooff + this->st_value + - relas->r_addend - (Elf64_Addr)r_addr; - if (!(((val & 0xfe000000) == 0x00000000) || - ((val & 0xfe000000) == 0xfe000000))) - { - int index; -#ifdef DL_PRINTF_DEBUG -_dl_printf(" ooff %lx, sym val %lx, addend %lx" - " r_addr %lx symn [%s] -> %x\n", - ooff, this->st_value, relas->r_addend, - r_addr, symn, val); -#endif - /* if offset is > RELOC_24 deal with it */ - index = (r_addr - first_rela) >> 1; - - if (index > (2 << 14)) { - - /* addis r11,r11,.PLTtable@ha*/ - val = (index*4 >> 16) + - ((index*4 & 0x00008000) >> 15); - r_addr[0] = 0x3d600000 | val; - val = (Elf64_Addr)pltcall - - (Elf64_Addr)&r_addr[2]; - r_addr[1] = 0x396b0000 | val; - val &= ~0xfc000000; - val |= 0x48000000; - r_addr[2] = val; - - } else { -#ifdef DL_PRINTF_DEBUG - _dl_printf(" index %d, pltcall %x r_addr %lx\n", - index, pltcall, r_addr); -#endif - - r_addr[0] = 0x39600000 | (index * 4); - val = (Elf64_Addr)pltcall - - (Elf64_Addr)&r_addr[1]; - val &= ~0xfc000000; - val |= 0x48000000; - r_addr[1] = val; - - } - _dl_dcbf(r_addr); - _dl_dcbf(&r_addr[2]); - val= ooff + this->st_value + - relas->r_addend; -#ifdef DL_PRINTF_DEBUG - _dl_printf(" symn [%s] val 0x%x\n", symn, val); -#endif - plttable[index] = val; - } else { - /* if the offset is small enough, - * branch directy to the dest - */ - val &= ~0xfc000000; - val |= 0x48000000; - *r_addr = val; - _dl_dcbf(r_addr); - } - } - + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if (this == NULL) + goto resolve_failed; + *r_addr = ooff + this->st_value; break; case R_TYPE(GLOB_DAT): - *r_addr = ooff + this->st_value + relas->r_addend; - break; -#if 0 -#ifdef DL_PRINTF_DEBUG - /* should not be supported ??? */ - case RELOC_REL24: - { - Elf64_Addr val = ooff + this->st_value + - relas->r_addend - (Elf64_Addr)r_addr; - if ((val & 0xfe000000 != 0) && - (val & 0xfe000000 != 0xfe000000)) - { - /* invalid offset */ - _dl_exit(20); - } - val &= ~0xfc000003; - val |= (*r_addr & 0xfc000003); - *r_addr = val; - - _dl_dcbf(r_addr); - } -#endif - break; - case RELOC_REL14_TAKEN: - /* val |= 1 << (31-10) XXX? */ - case RELOC_REL14: - case RELOC_REL14_NTAKEN: - { - Elf64_Addr val = ooff + this->st_value + - relas->r_addend - (Elf64_Addr)r_addr; - if (((val & 0xffff8000) != 0) && - ((val & 0xffff8000) != 0xffff8000)) - { - /* invalid offset */ - _dl_exit(20); - } - val &= ~0xffff0003; - val |= (*r_addr & 0xffff0003); - *r_addr = val; -#ifdef DL_PRINTF_DEBUG - _dl_printf("rel 14 %lx val %lx\n", - r_addr, val); -#endif - - _dl_dcbf(r_addr); - } + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if (this == NULL) + goto resolve_failed; + *r_addr = ooff + this->st_value; break; -#endif case R_TYPE(COPY): +_dl_printf("copy relocation, not tested\n"); + ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1); + if (this == NULL) + goto resolve_failed; #ifdef DL_PRINTF_DEBUG _dl_printf("copy r_addr %lx, sym %x [%s] size %d val %lx\n", r_addr, sym, symn, sym->st_size, @@ -322,7 +139,7 @@ _dl_printf(" ooff %lx, sym val %lx, addend %lx" */ elf_object_t *cobj; const Elf64_Sym *cpysrc = NULL; - Elf64_Addr src_loff; + Elf64_Addr src_loff = 0; int size; for (cobj = _dl_objects; cobj != NULL && cpysrc == NULL; @@ -364,11 +181,13 @@ _dl_printf(" found other symbol at %x size %d\n", ELF64_R_TYPE(relas->r_info), r_addr ); _dl_exit(1); } + continue; +resolve_failed: + _dl_printf("%s: %s :can't resolve reference '%s'\n", + _dl_progname, object->load_name, symn); + fails++; } - object->status |= STAT_RELOC_DONE; -#if 0 -_dl_printf("<\n"); -#endif + __asm __volatile("imb" : : : "memory"); return(fails); } @@ -386,16 +205,3 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) { /* relocations all done via rela relocations above */ } - -/* should not be defined here, but is is 32 for all powerpc 603-G4 */ -#define CACHELINESIZE 32 -void -_dl_syncicache(char *from, size_t len) -{ - int l = len; - unsigned int off = 0; - - while (off < len) { - off += CACHELINESIZE; - } -} |