summaryrefslogtreecommitdiff
path: root/libexec/ld.so/powerpc
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2001-03-30 01:35:22 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2001-03-30 01:35:22 +0000
commit3cce29673e509737c9de72c84989642c9564e292 (patch)
treec26b82ebd9e02b5190b0f5ccfdb0da035f4611d7 /libexec/ld.so/powerpc
parent01237d63b727bd16f83cc6170dca9c942469a206 (diff)
Add infrastructure to allow mapping of text sections which are normally
RO, RW while ld.so is working. And then the information to set the sections back to RO (or appropriate mode). PowerPC now supports the typical NON-PIC relocations in ld.so. I do not know how well this will work with large shared libraries. I seem to recall a possible problem with large data where data is located in a different shared library.
Diffstat (limited to 'libexec/ld.so/powerpc')
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c83
1 files changed, 69 insertions, 14 deletions
diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c
index 299bfeae120..b044e0ce591 100644
--- a/libexec/ld.so/powerpc/rtld_machine.c
+++ b/libexec/ld.so/powerpc/rtld_machine.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld_machine.c,v 1.3 2000/10/06 17:39:30 rahnds Exp $ */
+/* $OpenBSD: rtld_machine.c,v 1.4 2001/03/30 01:35:21 drahn Exp $ */
/*
* Copyright (c) 1999 Dale Rahn
@@ -35,6 +35,7 @@
#define _DYN_LOADER
#include <sys/types.h>
+#include <sys/mman.h>
#include <nlist.h>
#include <link.h>
@@ -61,6 +62,7 @@ _dl_md_reloc(elf_object_t *object, int rel, int relasz)
int i;
int numrela;
int fails = 0;
+ load_list_t *load_list;
Elf32_Addr loff;
Elf32_Rela *relas;
/* for jmp table relocations */
@@ -120,6 +122,19 @@ _dl_printf("md_reloc: plttable %x\n", plttable);
first_rela = NULL;
}
+ /*
+ * Change protection of all write protected segments in the object
+ * so we can do relocations such as REL24, REL16 etc. After
+ * relocation restore protection.
+ */
+ load_list = object->load_list;
+ while(load_list != NULL) {
+ _dl_mprotect(load_list->start, load_list->size,
+ load_list->prot|PROT_WRITE);
+ load_list = load_list->next;
+ }
+
+
for(i = 0; i < numrela; i++, relas++) {
Elf32_Addr *r_addr = (Elf32_Addr *)(relas->r_offset + loff);
Elf32_Addr ooff;
@@ -246,26 +261,61 @@ _dl_printf(" ooff %x, sym val %x, addend %x"
case RELOC_GLOB_DAT:
*r_addr = ooff + this->st_value + relas->r_addend;
break;
-#ifdef DL_PRINTF_DEBUG
+#if 1
/* should not be supported ??? */
case RELOC_REL24:
- {
+ {
Elf32_Addr val = ooff + this->st_value +
relas->r_addend - (Elf32_Addr)r_addr;
if ((val & 0xfe000000 != 0) &&
- (val & 0xfe000000 != 0xfe000000))
- {
+ (val & 0xfe000000 != 0xfe000000)) {
/* invalid offset */
_dl_exit(20);
}
val &= ~0xfc000003;
val |= (*r_addr & 0xfc000003);
*r_addr = val;
-
+
+_dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 1
+ case RELOC_16_LO:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = val;
+
_dl_dcbf(r_addr);
- }
+ }
+ break;
#endif
- break;
+#if 1
+ case RELOC_16_HI:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = (val >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 1
+ case RELOC_16_HA:
+ {
+ Elf32_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf32_Half *)r_addr = ((val + 0x8000) >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
case RELOC_REL14_TAKEN:
/* val |= 1 << (31-10) XXX? */
case RELOC_REL14:
@@ -350,6 +400,11 @@ _dl_printf(" found other symbol at %x size %d\n",
}
}
object->status |= STAT_RELOC_DONE;
+ load_list = object->load_list;
+ while(load_list != NULL) {
+ _dl_mprotect(load_list->start, load_list->size, load_list->prot);
+ load_list = load_list->next;
+ }
return(fails);
}
@@ -373,16 +428,16 @@ _dl_md_reloc_got(elf_object_t *object, int lazy)
void
_dl_syncicache(char *from, size_t len)
{
- int l = len;
unsigned int off = 0;
+ int l = len + ((int)from & (CACHELINESIZE-1));
- while (off < len) {
- asm volatile ("dcbst %1,%0" :: "r"(from), "r"(off));
+ while (off < l) {
+ asm volatile ("dcbst %1,%0" :: "r"(from), "r"(off));
asm volatile ("sync");
- asm volatile ("icbi 0,%0" :: "r"(from), "r"(off));
+ asm volatile ("icbi %1, %0" :: "r"(from), "r"(off));
asm volatile ("sync");
asm volatile ("isync");
- off += CACHELINESIZE;
- }
+ off += CACHELINESIZE;
+ }
}