summaryrefslogtreecommitdiff
path: root/libexec/ld.so/sparc
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so/sparc')
-rw-r--r--libexec/ld.so/sparc/ldasm.S20
-rw-r--r--libexec/ld.so/sparc/rtld_machine.c65
-rw-r--r--libexec/ld.so/sparc/syscall.h4
3 files changed, 86 insertions, 3 deletions
diff --git a/libexec/ld.so/sparc/ldasm.S b/libexec/ld.so/sparc/ldasm.S
index 9b3ff9fb81f..c7a3cf5f86c 100644
--- a/libexec/ld.so/sparc/ldasm.S
+++ b/libexec/ld.so/sparc/ldasm.S
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldasm.S,v 1.9 2002/11/23 19:50:45 drahn Exp $ */
+/* $OpenBSD: ldasm.S,v 1.10 2002/12/18 19:20:02 drahn Exp $ */
/*
* Copyright (c) 2001 Jason L. Wright (jason@thought.net)
@@ -292,6 +292,24 @@ _dl_sysctl:
retl
sub %g0, %o0, %o0 ! error: result = -errno
+
+ /* _dl_sigprocmask does not support NULL new mask */
+ .section ".text"
+ .align 4
+ .globl _dl_sigprocmask
+ .type _dl_sigprocmask,@function
+_dl_sigprocmask:
+ ld [%o1], %o1
+ mov SYS_sigprocmask, %g1 ! call sys___sigprocmask
+ t ST_SYSCALL ! off to wonderland
+
+ cmp %o2, 0
+ bne,a 1f
+ st %o0, [%o2]
+1:
+ retl
+ clr %o0
+
/*
* V8 sparc .{,u}{mul,div,rem} replacements.
* We try to mimic them 100%. Full 64 bit sources or outputs, and
diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c
index 73ccd4ffc3b..48c16f7fe98 100644
--- a/libexec/ld.so/sparc/rtld_machine.c
+++ b/libexec/ld.so/sparc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.10 2002/11/23 19:14:25 drahn Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.11 2002/12/18 19:20:02 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -44,6 +44,7 @@
#include <nlist.h>
#include <link.h>
+#include <signal.h>
#include "syscall.h"
#include "archdep.h"
@@ -335,6 +336,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff)
const char *symn;
Elf_Addr value;
Elf_RelA *rela;
+ sigset_t omask, nmask;
rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
@@ -353,8 +355,33 @@ _dl_bind(elf_object_t *object, Elf_Word reloff)
value = ooff + this->st_value;
+ /* if PLT is protected, allow the write */
+ if (object->plt_addr != NULL && object->plt_size != 0) {
+ sigfillset(&nmask);
+ _dl_sigprocmask(SIG_BLOCK, &nmask, &omask);
+#if 0
+ _dl_mprotect((void*)object->plt_addr, object->plt_size,
+ PROT_READ|PROT_WRITE|PROT_EXEC);
+#else
+ _dl_mprotect((void*)addr,sizeof (Elf_Addr) * 3,
+ PROT_READ|PROT_WRITE|PROT_EXEC);
+#endif
+ }
+
_dl_reloc_plt(addr, value);
+ /* if PLT is (to be protected, change back to RO/X */
+ if (object->plt_addr != NULL && object->plt_size != 0) {
+#if 0
+ _dl_mprotect((void*)object->plt_addr, object->plt_size,
+ PROT_READ|PROT_EXEC);
+#else
+ _dl_mprotect((void*)addr,sizeof (Elf_Addr) * 3,
+ PROT_READ|PROT_EXEC);
+#endif
+ _dl_sigprocmask(SIG_SETMASK, &omask, NULL);
+ }
+
return (value);
}
@@ -363,6 +390,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
{
Elf_Addr *pltgot;
extern void _dl_bind_start(void); /* XXX */
+ Elf_Addr ooff;
+ const Elf_Sym *this;
pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT];
@@ -393,11 +422,45 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
__asm __volatile("nop;nop;nop;nop;nop");
}
+ this = NULL;
+ ooff = _dl_find_symbol("__got_start", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT,
+ NULL);
+ if (this != NULL)
+ object->got_addr = ooff + this->st_value;
+
+ this = NULL;
+ ooff = _dl_find_symbol("__got_end", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT,
+ NULL);
+ if (this != NULL)
+ object->got_size = ooff + this->st_value - object->got_addr;
+
+ this = NULL;
+ ooff = _dl_find_symbol("__plt_start", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT,
+ NULL);
+ if (this != NULL)
+ object->plt_addr = ooff + this->st_value;
+
+ this = NULL;
+ ooff = _dl_find_symbol("__plt_end", object, &this,
+ SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT,
+ NULL);
+ if (this != NULL)
+ object->plt_size = ooff + this->st_value - object->plt_addr;
+
if (object->obj_type == OBJTYPE_LDR || !lazy || pltgot == NULL) {
_dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
return;
}
+ if (object->got_addr != NULL && object->got_size != 0)
+ _dl_mprotect((void*)object->got_addr, object->got_size,
+ PROT_READ);
+ if (object->plt_addr != NULL && object->plt_size != 0)
+ _dl_mprotect((void*)object->plt_addr, object->plt_size,
+ PROT_READ|PROT_EXEC);
}
diff --git a/libexec/ld.so/sparc/syscall.h b/libexec/ld.so/sparc/syscall.h
index c11613b6120..ac19f7fb0ca 100644
--- a/libexec/ld.so/sparc/syscall.h
+++ b/libexec/ld.so/sparc/syscall.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: syscall.h,v 1.2 2002/11/23 19:14:25 drahn Exp $ */
+/* $OpenBSD: syscall.h,v 1.3 2002/12/18 19:20:02 drahn Exp $ */
/*
* Copyright (c) 2001 Niklas Hallqvist
@@ -37,6 +37,7 @@
#include <sys/syscall.h>
#include <sys/stat.h>
+#include <sys/signal.h>
#ifndef _dl_MAX_ERRNO
#define _dl_MAX_ERRNO 4096
@@ -59,6 +60,7 @@ int _dl_fcntl(int, int, ...);
int _dl_getdirentries(int, char*, int, long *);
int _dl_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+int _dl_sigprocmask(int, const sigset_t *, sigset_t *);
static inline off_t
_dl_lseek(int fildes, off_t offset, int whence)