summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libexec/ld.so/sparc64/archdep.h12
-rw-r--r--libexec/ld.so/sparc64/ldasm.S43
-rw-r--r--libexec/ld.so/sparc64/rtld_machine.c244
3 files changed, 278 insertions, 21 deletions
diff --git a/libexec/ld.so/sparc64/archdep.h b/libexec/ld.so/sparc64/archdep.h
index 5013f14413c..14936fa9bce 100644
--- a/libexec/ld.so/sparc64/archdep.h
+++ b/libexec/ld.so/sparc64/archdep.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: archdep.h,v 1.1 2001/09/21 14:57:43 jason Exp $ */
+/* $OpenBSD: archdep.h,v 1.2 2001/09/23 00:14:56 drahn Exp $ */
/*
* Copyright (c) 1998 Per Fogelstrom, Opsycon AB
@@ -128,19 +128,21 @@ _dl_strchr(const char *p, const int c)
static inline void
RELOC_RELA(Elf64_Rela *r, const Elf64_Sym *s, Elf64_Addr *p, unsigned long v)
{
-#error "haven't fixed for sparc64 yet..."
extern Elf_Addr _GLOBAL_OFFSET_TABLE_[];
- if (ELF64_R_TYPE(r->r_info) == RELOC_RELATIVE) {
+ if (ELF64_R_TYPE(r->r_info) == R_SPARC_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) {
+ } else if (ELF64_R_TYPE(r->r_info) == R_SPARC_JMP_SLOT) {
Elf64_Addr val = v + s->st_value + r->r_addend -
(Elf64_Addr)(p);
*p = val;
+ /*
+ * need instruction cache flush? - XXX
__asm __volatile("imb" : : : "memory");
- } else if (ELF64_R_TYPE(r->r_info) == RELOC_GLOB_DAT) {
+ */
+ } else if (ELF64_R_TYPE(r->r_info) == R_SPARC_64) {
*p = v + s->st_value + r->r_addend;
} else {
_dl_printf("unknown bootstrap relocation\n");
diff --git a/libexec/ld.so/sparc64/ldasm.S b/libexec/ld.so/sparc64/ldasm.S
index 67148b06b67..f86f4b2a312 100644
--- a/libexec/ld.so/sparc64/ldasm.S
+++ b/libexec/ld.so/sparc64/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.1 2001/09/21 14:52:45 jason Exp $ */
+/* $OpenBSD: ldasm.S,v 1.2 2001/09/23 00:14:56 drahn Exp $ */
/* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */
/*
@@ -131,21 +131,21 @@ _dl_start:
* We have two separate entry points to the runtime linker.
* I'm implementing this following the SPARC v9 ABI spec.
*
- * _rtld_bind_start_0(x, y) is called from .PLT0, and is used for
+ * _dl_bind_start_0(x, y) is called from .PLT0, and is used for
* PLT entries above 32768.
*
- * _rtld_bind_start_1(x, y) is called from .PLT1, and is used for
+ * _dl_bind_start_1(x, y) is called from .PLT1, and is used for
* PLT entries below 32768.
*
* The first two entries of PLT2 contain the xword object pointer.
*
* These routines are called with two longword arguments,
* x and y. To calculate the address of the entry,
- * _rtld_bind_start_1(x, y) does:
+ * _dl_bind_start_1(x, y) does:
*
* n = x >> 15;
*
- * and _rtld_bind_start_0(x, y) does:
+ * and _dl_bind_start_0(x, y) does:
*
* i = x - y + 1048596;
* n = 32768 + (i/5120)*160 + (i%5120)/24;
@@ -154,15 +154,15 @@ _dl_start:
* done in the PLT entry.
*/
- /* NOTE: _rtld_bind_start_0 is untested. Hence the debug stuff */
+ /* NOTE: _dl_bind_start_0 is untested. Hence the debug stuff */
.section ".text"
.align 4
- .global _rtld_bind_start_0
- .type _rtld_bind_start_0,@function
-_rtld_bind_start_0: # (x, y)
+ .global _dl_bind_start_0
+ .type _dl_bind_start_0,@function
+_dl_bind_start_0: # (x, y)
#if 0
- call _rtld_bind_start_0_stub
+ call _dl_bind_start_0_stub
ldx [%o1 + (10*4)], %l7
mov %o0, %l5
@@ -170,7 +170,7 @@ _rtld_bind_start_0: # (x, y)
add %l6, %l5, %l5 /* is 3 longwords or 24 bytes. */
sllx %l5, 3, %o1 /* So multiply by 24. */
- call _rtld_bind
+ call _dl_bind
mov %l7, %o0
#else
sethi %hi(1048596), %l1
@@ -198,7 +198,7 @@ _rtld_bind_start_0: # (x, y)
add %l6, %l5, %l5 /* is 3 longwords or 24 bytes. */
sllx %l5, 3, %l5 /* So multiply by 24. */
- call _rtld_bind /* Call _rtld_bind(obj, offset) */
+ call _dl_bind /* Call _dl_bind(obj, offset) */
mov %l5, %o1
jmp %o0 /* return value == function address */
@@ -207,9 +207,9 @@ _rtld_bind_start_0: # (x, y)
.section ".text"
.align 4
- .global _rtld_bind_start_1
- .type _rtld_bind_start_1,@function
-_rtld_bind_start_1: # (x, y)
+ .global _dl_bind_start_1
+ .type _dl_bind_start_1,@function
+_dl_bind_start_1: # (x, y)
srax %o0, 15, %o2 /* %o0 is the index to our PLT slot */
sllx %o2, 1, %o3 /* Each element is an Elf_Rela which */
@@ -218,7 +218,7 @@ _rtld_bind_start_1: # (x, y)
ldx [%o1 + 8], %o0 /* The object pointer is at [%o1 + 8] */
- call _rtld_bind /* Call _rtld_bind(obj, offset) */
+ call _dl_bind /* Call _dl_bind(obj, offset) */
mov %o2, %o1
jmp %o0 /* return value == function address */
@@ -308,6 +308,17 @@ _dl_mmap:
retl
sub %g0, %o0, %o0 ! error: result = -errno
+ .section ".text"
+ .align 4
+ .global _dl_munmap
+ .type _dl_munmap,@function
+_dl_munmap:
+ mov SYS_munmap | SYSCALL_G2RFLAG, %g1 ! calling sys_mmap
+ add %o7, 8, %g2 ! just return on sucess
+ t ST_SYSCALL ! off to wonderland
+ retl
+ sub %g0, %o0, %o0 ! error: result = -errno
+
.section ".text"
.align 4
diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c
new file mode 100644
index 00000000000..2296ffd2ea9
--- /dev/null
+++ b/libexec/ld.so/sparc64/rtld_machine.c
@@ -0,0 +1,244 @@
+/* $OpenBSD: rtld_machine.c,v 1.1 2001/09/23 00:14:56 drahn Exp $ */
+
+/*
+ * Copyright (c) 1999 Dale Rahn
+ * Copyright (c) 2001 Niklas Hallqvist
+ * Copyright (c) 2001 Artur Grabowski
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed under OpenBSD by
+ * Dale Rahn.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#define _DYN_LOADER
+
+#include <sys/types.h>
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+
+#include <nlist.h>
+#include <link.h>
+
+#include "syscall.h"
+#include "archdep.h"
+#include "resolve.h"
+
+void
+_dl_bcopy(void *src, void *dest, int size)
+{
+ unsigned char *psrc, *pdest;
+ int i;
+ psrc = src;
+ pdest = dest;
+ for (i = 0; i < size; i++) {
+ pdest[i] = psrc[i];
+ }
+}
+
+int
+_dl_md_reloc(elf_object_t *object, int rel, int relasz)
+{
+ long i;
+ long numrela;
+ long fails = 0;
+ Elf64_Addr loff;
+ Elf64_Rela *relas;
+ load_list_t *llist;
+
+ loff = object->load_offs;
+ numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela);
+ relas = (Elf64_Rela *)(object->Dyn.info[rel]);
+
+ if ((object->status & STAT_RELOC_DONE) || !relas) {
+ return(0);
+ }
+
+ /*
+ * unprotect some segments if we need it.
+ * XXX - we unprotect waay to much. only the text can have cow
+ * relocations.
+ */
+ if ((rel == DT_REL || rel == DT_RELA)) {
+ for (llist = object->load_list; llist != NULL; llist = llist->next) {
+ if (!(llist->prot & PROT_WRITE)) {
+ _dl_mprotect(llist->start, llist->size,
+ llist->prot|PROT_WRITE);
+ }
+ }
+ }
+
+ for (i = 0; i < numrela; i++, relas++) {
+ Elf64_Addr *r_addr;
+ Elf64_Addr ooff;
+ const Elf64_Sym *sym, *this;
+ const char *symn;
+
+ r_addr = (Elf64_Addr *)(relas->r_offset + loff);
+
+ if (ELF64_R_SYM(relas->r_info) == 0xffffffff) {
+ continue;
+ }
+
+ sym = object->dyn.symtab;
+ sym += ELF64_R_SYM(relas->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ this = NULL;
+ switch (ELF64_R_TYPE(relas->r_info)) {
+ case R_TYPE(64):
+ 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;
+ case R_TYPE(RELATIVE):
+ /*
+ * There is a lot of unaligned RELATIVE
+ * relocs generated by gcc in the exception handlers.
+ */
+ if ((((Elf_Addr) r_addr) & 0x7) != 0) {
+ Elf_Addr tmp;
+#if 0
+_dl_printf("unaligned RELATIVE: %p type: %d %s 0x%lx -> 0x%lx\n", r_addr,
+ELF_R_TYPE(relas->r_info), object->load_name, *r_addr, *r_addr+loff);
+#endif
+ _dl_bcopy(r_addr, &tmp, sizeof(Elf_Addr));
+ tmp += loff;
+ _dl_bcopy(&tmp, r_addr, sizeof(Elf_Addr));
+ } else {
+ *r_addr += loff;
+ }
+ break;
+ case R_TYPE(JMP_SLOT):
+ 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;
+ case R_TYPE(GLOB_DAT):
+ 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;
+ case R_TYPE(NONE):
+ break;
+ default:
+ _dl_printf("%s:"
+ " %s: unsupported relocation '%s' %d at %lx\n",
+ _dl_progname, object->load_name, symn,
+ 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++;
+ }
+ /*
+ * flush ?? - XXX
+ __asm __volatile("imb" : : : "memory");
+ */
+
+ /* reprotect the unprotected segments */
+ if ((rel == DT_REL || rel == DT_RELA)) {
+ for (llist = object->load_list; llist != NULL; llist = llist->next) {
+ if (!(llist->prot & PROT_WRITE)) {
+ _dl_mprotect(llist->start, llist->size,
+ llist->prot);
+ }
+ }
+ }
+
+ return (fails);
+}
+
+/*
+ * Resolve a symbol at run-time.
+ */
+void *
+_dl_bind(elf_object_t *object, Elf_Word reloff)
+{
+ Elf_RelA *rela;
+ Elf_Addr *addr, ooff;
+ const Elf_Sym *sym, *this;
+ const char *symn;
+
+ rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
+
+ sym = object->dyn.symtab;
+ sym += ELF64_R_SYM(rela->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ addr = (Elf_Addr *)(object->load_offs + rela->r_offset);
+ ooff = _dl_find_symbol(symn, _dl_objects, &this, 0, 1);
+ if (this == NULL) {
+ _dl_printf("lazy binding failed!\n");
+ *((int *)0) = 0; /* XXX */
+ }
+ *addr = ooff + this->st_value + rela->r_addend;
+
+ return (void *)*addr;
+}
+
+/*
+ * Relocate the Global Offset Table (GOT).
+ */
+void
+_dl_md_reloc_got(elf_object_t *object, int lazy)
+{
+ Elf_Addr *pltgot;
+ extern void _dl_bind_start(void); /* XXX */
+
+ lazy = 0; /* not yet */
+ pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
+
+ if (object->obj_type == OBJTYPE_LDR || !lazy || pltgot == NULL) {
+ _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
+ return;
+ }
+
+#ifdef SUPPORT_LAZY
+ if (object->obj_type != OBJTYPE_EXE) {
+ int i, size;
+ Elf_Addr *addr;
+ Elf_RelA *rela;
+
+ size = object->Dyn.info[DT_PLTRELSZ] / sizeof(Elf_RelA);
+ rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]);
+
+ for (i = 0; i < size; i++) {
+ addr = (Elf_Addr *)(object->load_offs + rela[i].r_offset);
+ *addr += object->load_offs;
+ }
+ }
+
+ pltgot[2] = (Elf_Addr)_dl_bind_start;
+ pltgot[3] = (Elf_Addr)object;
+#endif /* SUPPORT_LAZY */
+}