summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authordrahn <drahn@openbsd.org>2020-06-25 04:00:58 +0000
committerdrahn <drahn@openbsd.org>2020-06-25 04:00:58 +0000
commit6a2e3db89fda3dccb5827ac07cf3047f22233350 (patch)
tree6b686822898e1f4e5680f2d3862fce271cfd43f1 /libexec
parentreport rx ring state for all rings, not just the first one. (diff)
downloadwireguard-openbsd-6a2e3db89fda3dccb5827ac07cf3047f22233350.tar.xz
wireguard-openbsd-6a2e3db89fda3dccb5827ac07cf3047f22233350.zip
PowerPC64 ld.so code.
Mostly ported, code runs far enough to start first symbol string lookup. build with -gdwarf-4 to remove asm warnings. Do not bother supporting 32 bit non-pic relocations in shared libraries. (however leave the code there for now)
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ld.so/powerpc64/Makefile.inc11
-rw-r--r--libexec/ld.so/powerpc64/SYS.h39
-rw-r--r--libexec/ld.so/powerpc64/archdep.h83
-rw-r--r--libexec/ld.so/powerpc64/ld.script70
-rw-r--r--libexec/ld.so/powerpc64/ldasm.S127
-rw-r--r--libexec/ld.so/powerpc64/rtld_machine.c349
-rw-r--r--libexec/ld.so/powerpc64/syscall.h70
7 files changed, 749 insertions, 0 deletions
diff --git a/libexec/ld.so/powerpc64/Makefile.inc b/libexec/ld.so/powerpc64/Makefile.inc
new file mode 100644
index 00000000000..334821fc99a
--- /dev/null
+++ b/libexec/ld.so/powerpc64/Makefile.inc
@@ -0,0 +1,11 @@
+# $OpenBSD: Makefile.inc,v 1.1 2020/06/25 04:00:58 drahn Exp $
+
+# no jump tables in _dl_boot_bind()
+CFLAGS += -fno-jump-tables
+CFLAGS += -fPIC -msoft-float
+LD_SCRIPT = ${.CURDIR}/${MACHINE_CPU}/ld.script
+
+RELATIVE_RELOC=R_PPC64_RELATIVE
+
+# Suppress DWARF2 warnings
+DEBUG?= -gdwarf-4
diff --git a/libexec/ld.so/powerpc64/SYS.h b/libexec/ld.so/powerpc64/SYS.h
new file mode 100644
index 00000000000..3c8b413e78e
--- /dev/null
+++ b/libexec/ld.so/powerpc64/SYS.h
@@ -0,0 +1,39 @@
+/* $OpenBSD: SYS.h,v 1.1 2020/06/25 04:00:58 drahn Exp $ */
+
+/*
+ * Copyright (c) 1999 Dale Rahn
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#define DL_SYSCALL(n) \
+ENTRY(_dl_##n) \
+ li %r0, SYS_##n ;\
+ sc ;\
+ cmpdi %r0, 0 ;\
+ beqlr+ ;\
+ neg %r3, %r3 ;\
+ blr
diff --git a/libexec/ld.so/powerpc64/archdep.h b/libexec/ld.so/powerpc64/archdep.h
new file mode 100644
index 00000000000..953c93c77d9
--- /dev/null
+++ b/libexec/ld.so/powerpc64/archdep.h
@@ -0,0 +1,83 @@
+/* $OpenBSD: archdep.h,v 1.1 2020/06/25 04:00:58 drahn Exp $ */
+
+/*
+ * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _POWERPC_ARCHDEP_H_
+#define _POWERPC_ARCHDEP_H_
+
+#define RELOC_TAG DT_RELA
+
+#define MACHID EM_PPC64 /* ELF e_machine ID value checked */
+
+#include <elf.h>
+#include <machine/reloc.h>
+#include "syscall.h"
+#include "util.h"
+
+/*
+ * The following functions are declared inline so they can
+ * be used before bootstrap linking has been finished.
+ */
+
+static inline void
+_dl_dcbf(Elf_Addr *addr)
+{
+ __asm__ volatile ("dcbst %%r0, %0\n\t"
+ "sync\n\t"
+ "icbi %%r0, %0\n\t"
+ "sync\n\t"
+ "isync"
+ : : "r" (addr) : "0");
+}
+
+static inline void
+RELOC_DYN(Elf_RelA *r, const Elf_Sym *s, Elf_Addr *p, unsigned long v)
+{
+ if (ELF_R_TYPE(r->r_info) == RELOC_RELATIVE) {
+ *p = v + r->r_addend;
+ } else if (ELF_R_TYPE(r->r_info) == RELOC_JMP_SLOT) {
+ Elf_Addr val = v + s->st_value + r->r_addend -
+ (Elf_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 (ELF_R_TYPE((r)->r_info) == RELOC_GLOB_DAT) {
+ *p = v + s->st_value + r->r_addend;
+ } else {
+ _dl_exit(6);
+ }
+}
+
+#define RELOC_GOT(obj, offs)
+
+#endif /* _POWERPC_ARCHDEP_H_ */
diff --git a/libexec/ld.so/powerpc64/ld.script b/libexec/ld.so/powerpc64/ld.script
new file mode 100644
index 00000000000..96614bc9732
--- /dev/null
+++ b/libexec/ld.so/powerpc64/ld.script
@@ -0,0 +1,70 @@
+PHDRS
+{
+ rodata PT_LOAD FILEHDR PHDRS FLAGS (4);
+ text PT_LOAD;
+ data PT_LOAD;
+ random PT_OPENBSD_RANDOMIZE;
+ relro PT_GNU_RELRO;
+ dynamic PT_DYNAMIC;
+ note PT_NOTE;
+}
+
+SECTIONS
+{
+ . = 0 + SIZEOF_HEADERS;
+ /* RODATA */
+ .dynsym : { *(.dynsym) } :rodata
+ .gnu.hash : { *(.gnu.hash) } :rodata
+ .dynstr : { *(.dynstr) } :rodata
+ .rodata : { *(.rodata .rodata.*) } :rodata
+ .eh_frame : { *(.eh_frame) } :rodata
+
+ /* TEXT */
+ . = ALIGN(0x10000);
+ .boot.text :
+ {
+ boot_text_start = .;
+ *(.boot.text)
+ boot_text_end = .;
+ } :text
+ . = ALIGN(0x1000);
+ .text : { *(.text .text.*) } :text
+
+ /* RELRO DATA */
+ . = DATA_SEGMENT_ALIGN (0x10000, 0x1000);
+ .openbsd.randomdata :
+ {
+ *(.openbsd.randomdata .openbsd.randomdata.*)
+ } :data :relro :random
+ .data.rel.ro : { *(.data.rel.ro.local*) *(.data.rel.ro*) } :data :relro
+ .dynamic : { *(.dynamic) } :data :relro :dynamic
+ .got : { *(.got.plt) *(.got) } :data :relro
+ . = DATA_SEGMENT_RELRO_END (0, .);
+
+ /* BOOTDATA */
+ boot_data_start = .;
+ .rela.dyn :
+ {
+ *(.rela.text .rela.text.*)
+ *(.rela.rodata .rela.rodata.*)
+ *(.rela.data .rela.data.*)
+ *(.rela.got)
+ *(.rela.bss .rela.bss.*)
+ } :data
+/* XXX .rela.plt is unused but cannot delete: ld.bfd zeros DT_RELASZ then! */
+ .rela.plt : { *(.rela.plt) } :data
+ .hash : { *(.hash) } :data
+ .note : { *(.note.openbsd.*) } :data :note
+ .boot.data : { *(.boot.data .boot.data.*) } :data
+ boot_data_end = .;
+
+ /* DATA */
+ . = ALIGN(0x1000);
+ .sdata : { *(.sdata .sdata.*) } :data
+ .data : { *(.data .data.*) } :data
+ .sbss : { *(.sbss .sbss.*) } :data
+ .bss : { *(.dynbss) *(.bss .bss.*) *(COMMON) } :data
+ . = DATA_SEGMENT_END (.);
+
+ /DISCARD/ : { *(.note.GNU-stack) }
+}
diff --git a/libexec/ld.so/powerpc64/ldasm.S b/libexec/ld.so/powerpc64/ldasm.S
new file mode 100644
index 00000000000..4943cbbf228
--- /dev/null
+++ b/libexec/ld.so/powerpc64/ldasm.S
@@ -0,0 +1,127 @@
+/* $OpenBSD: ldasm.S,v 1.1 2020/06/25 04:00:58 drahn Exp $ */
+
+/*
+ * Copyright (c) 1999 Dale Rahn
+ *
+ * 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.
+ *
+ * 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 AUX_entry 9
+
+#include <machine/asm.h>
+#include <sys/syscall.h>
+
+ .section .boot.text,"ax",@progbits
+ .align 2
+ .globl _dl_start
+ .type _dl_start,@function
+_dl_start:
+ bl 1f
+1:
+ mflr %r30
+ addis %r2, %r30, .TOC.-1b@ha
+ addi %r2, %r2, .TOC.-1b@l
+
+ stdu %r1, (-16 -((AUX_entry+3)*8))(1) # Some space.
+
+ # squirrel away the arguments for main
+ mr %r20, %r3 #argc
+ mr %r21, %r4 #argv
+ mr %r22, %r5 #envp
+ mr %r23, %r6 # ???
+ nop
+
+ addis %r18, %r2, _DYNAMIC@toc@ha
+ addi %r18, %r18, _DYNAMIC@toc@l
+
+ ld %r4, -0x8000(%r2) # First entry of TOC is TOC base
+ sub %r4, %r2, %r4 # determine load offset
+
+ mr %r17, %r4 # save for _dl_boot
+
+ subi %r3, %r21, 8 # Get stack pointer (arg0 for _dl_boot).
+ addi %r4, %r1, 8 # dl_data
+ mr %r5, %r18 # dynamicp
+
+ bl _dl_boot_bind
+
+ mr %r3, %r21 # argv
+ mr %r4, %r22 # envp
+ mr %r5, %r17 # loff
+ addi %r6, %r1, 8 # dl_data
+
+ bl _dl_boot
+
+ mtctr %r3 # put return value into ctr to execute
+
+ # get back the squirreled away the arguments for main
+ mr %r3, %r20
+ mr %r4, %r21
+ mr %r5, %r22
+ mr %r6, %r23
+
+ addis %r7, %r2, _dl_dtors@toc@ha
+ addi %r7, %r7, _dl_dtors@toc@l
+
+ mtlr %r27
+ ld %r1, 0(%r1) # Restore stack pointer.
+ bctr # Go execute the 'real' program.
+END(_dl_start)
+
+ENTRY(_dl_bind_start)
+ stdu 1,-72(1)
+
+ std %r0,8(1) # save r0 - cerror ;-)
+ mflr %r0
+ std %r0,68(1) # save lr
+
+ std %r3,12(1) # save r3-r10, C calling convention
+ std %r4,20(1) # r13 - r31 are preserved by called code
+ std %r5,24(1)
+ std %r6,28(1)
+ std %r7,32(1)
+ std %r8,36(1)
+ std %r9,40(1)
+ std %r10,44(1)
+
+ mr %r3,%r12 # obj
+ mr %r4,%r11 # reloff
+ bl _dl_bind # _rtld_bind(obj, reloff)
+ mtctr %r3
+
+ ld %r3,12(%r1)
+ ld %r4,20(%r1)
+ ld %r5,24(%r1)
+ ld %r6,28(%r1)
+ ld %r7,32(%r1)
+ ld %r8,36(%r1)
+ ld %r9,40(%r1)
+ ld %r10,44(%r1)
+
+ ld %r0,68(%r1) # restore lr
+ mtlr %r0
+ ld %r0,8(%r1)
+
+ addi %r1,%r1,72
+ bctr
+END(_dl_bind_start)
diff --git a/libexec/ld.so/powerpc64/rtld_machine.c b/libexec/ld.so/powerpc64/rtld_machine.c
new file mode 100644
index 00000000000..f7e70be6a9f
--- /dev/null
+++ b/libexec/ld.so/powerpc64/rtld_machine.c
@@ -0,0 +1,349 @@
+/* $OpenBSD: rtld_machine.c,v 1.1 2020/06/25 04:00:58 drahn Exp $ */
+
+/*
+ * Copyright (c) 1999 Dale Rahn
+ *
+ * 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.
+ *
+ * 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/mman.h>
+#include <sys/syscall.h>
+#include <sys/unistd.h>
+
+#include <nlist.h>
+#include <link.h>
+
+#include "syscall.h"
+#include "archdep.h"
+#include "resolve.h"
+
+#define DT_PROC(n) ((n) - DT_LOPROC + DT_NUM)
+
+int64_t pcookie __attribute__((section(".openbsd.randomdata"))) __dso_hidden;
+
+/* relocation bits */
+#define B24_VALID_RANGE(x) \
+ ((((x) & 0xfe000000) == 0x00000000) || (((x) & 0xfe000000) == 0xfe000000))
+
+void _dl_bind_start(void); /* XXX */
+Elf_Addr _dl_bind(elf_object_t *object, int reloff);
+
+int
+_dl_md_reloc(elf_object_t *object, int rel, int relasz)
+{
+ int i;
+ int numrela;
+ long relrel;
+ int fails = 0;
+ Elf_Addr loff;
+ Elf_RelA *relas;
+ /* for jmp table relocations */
+ Elf_Addr prev_value = 0, prev_ooff = 0;
+ const Elf_Sym *prev_sym = NULL;
+
+ loff = object->obj_base;
+ numrela = object->Dyn.info[relasz] / sizeof(Elf_RelA);
+ relrel = rel == DT_RELA ? object->relacount : 0;
+ relas = (Elf_RelA *)(object->Dyn.info[rel]);
+
+ if (relas == NULL)
+ return 0;
+
+ if (relrel > numrela)
+ _dl_die("relcount > numrel: %ld > %d", relrel, numrela);
+
+ if (object->Dyn.info[DT_PROC(DT_PPC_GOT)] == 0)
+ _dl_die("unsupported insecure BSS PLT object");
+
+ /* tight loop for leading RELATIVE relocs */
+ for (i = 0; i < relrel; i++, relas++) {
+ Elf_Addr *r_addr;
+
+ r_addr = (Elf_Addr *)(relas->r_offset + loff);
+ *r_addr = loff + relas->r_addend;
+ }
+ for (; i < numrela; i++, relas++) {
+ Elf_Addr *r_addr = (Elf_Addr *)(relas->r_offset + loff);
+ const Elf_Sym *sym;
+ const char *symn;
+ int type;
+
+ if (ELF_R_SYM(relas->r_info) == 0xffffff)
+ continue;
+
+ type = ELF_R_TYPE(relas->r_info);
+
+ if (type == RELOC_JMP_SLOT && rel != DT_JMPREL)
+ continue;
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(relas->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ if (ELF_R_SYM(relas->r_info) &&
+ !(ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
+ ELF_ST_TYPE (sym->st_info) == STT_NOTYPE) &&
+ sym != prev_sym) {
+ struct sym_res sr;
+
+ sr = _dl_find_symbol(symn,
+ SYM_SEARCH_ALL|SYM_WARNNOTFOUND|
+ ((type == RELOC_JMP_SLOT) ?
+ SYM_PLT:SYM_NOTPLT), sym, object);
+
+ if (sr.sym == NULL) {
+ if (ELF_ST_BIND(sym->st_info) != STB_WEAK)
+ fails++;
+ continue;
+ }
+ prev_sym = sym;
+ prev_value = sr.sym->st_value;
+ prev_ooff = sr.obj->obj_base;
+ }
+
+ switch (type) {
+ case RELOC_ADDR64: //RELOC_64:
+ if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
+ (ELF_ST_TYPE(sym->st_info) == STT_SECTION ||
+ ELF_ST_TYPE(sym->st_info) == STT_NOTYPE) ) {
+ *r_addr = prev_ooff + relas->r_addend;
+ } else {
+ *r_addr = prev_ooff + prev_value +
+ relas->r_addend;
+ }
+ break;
+ case RELOC_RELATIVE:
+ if (ELF_ST_BIND(sym->st_info) == STB_LOCAL &&
+ (ELF_ST_TYPE(sym->st_info) == STT_SECTION ||
+ ELF_ST_TYPE(sym->st_info) == STT_NOTYPE) ) {
+ *r_addr = loff + relas->r_addend;
+ } else {
+ *r_addr = loff + prev_value +
+ relas->r_addend;
+ }
+ break;
+ /*
+ * For Secure-PLT, RELOC_JMP_SLOT simply sets PLT
+ * slots similarly to how RELOC_GLOB_DAT updates GOT
+ * slots.
+ */
+ case RELOC_JMP_SLOT:
+ case RELOC_GLOB_DAT:
+ *r_addr = prev_ooff + prev_value + relas->r_addend;
+ break;
+#if 0
+ /* should not be supported ??? */
+ case RELOC_REL24:
+ {
+ Elf_Addr val = prev_ooff + prev_value +
+ relas->r_addend - (Elf_Addr)r_addr;
+ if (!B24_VALID_RANGE(val)) {
+ /* invalid offset */
+ _dl_die("%s: invalid %s offset %llx at %p",
+ object->load_name, "REL24", val,
+ (void *)r_addr);
+ }
+ val &= ~0xfc000003;
+ val |= (*r_addr & 0xfc000003);
+ *r_addr = val;
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 0
+ case RELOC_16_LO:
+ {
+ Elf_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf_Half *)r_addr = val;
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 0
+ case RELOC_16_HI:
+ {
+ Elf_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf_Half *)r_addr = (val >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+#if 0
+ case RELOC_16_HA:
+ {
+ Elf_Addr val;
+
+ val = loff + relas->r_addend;
+ *(Elf_Half *)r_addr = ((val + 0x8000) >> 16);
+
+ _dl_dcbf(r_addr);
+ }
+ break;
+#endif
+ case RELOC_REL14_TAKEN:
+ /* val |= 1 << (31-10) XXX? */
+ case RELOC_REL14:
+ case RELOC_REL14_NTAKEN:
+ {
+ Elf_Addr val = prev_ooff + prev_value +
+ relas->r_addend - (Elf_Addr)r_addr;
+ if (((val & 0xffff8000) != 0) &&
+ ((val & 0xffff8000) != 0xffff8000)) {
+ /* invalid offset */
+ _dl_die("%s: invalid %s offset %llx at %p",
+ object->load_name, "REL14", val,
+ (void *)r_addr);
+ }
+ val &= ~0xffff0003;
+ val |= (*r_addr & 0xffff0003);
+ *r_addr = val;
+ _dl_dcbf(r_addr);
+ }
+ break;
+ case RELOC_COPY:
+ {
+ struct sym_res sr;
+ /*
+ * we need to find a symbol, that is not in the current
+ * object, start looking at the beginning of the list,
+ * searching all objects but _not_ the current object,
+ * first one found wins.
+ */
+ sr = _dl_find_symbol(symn,
+ SYM_SEARCH_OTHER|SYM_WARNNOTFOUND| SYM_NOTPLT,
+ sym, object);
+ if (sr.sym != NULL) {
+ _dl_bcopy((void *)(sr.obj->obj_base + sr.sym->st_value),
+ r_addr, sym->st_size);
+ } else
+ fails++;
+ }
+ break;
+ case RELOC_NONE:
+ break;
+
+ default:
+ _dl_die("%s: unsupported relocation '%s' %lld at %p\n",
+ object->load_name, symn,
+ ELF_R_TYPE(relas->r_info), (void *)r_addr );
+ }
+ }
+
+ return fails;
+}
+
+/*
+ * Relocate the Global Offset Table (GOT).
+ * This is done by calling _dl_md_reloc on DT_JMPREL for DL_BIND_NOW,
+ * otherwise the lazy binding plt initialization is performed.
+ */
+int
+_dl_md_reloc_got(elf_object_t *object, int lazy)
+{
+ int fails = 0;
+
+ if (object->Dyn.info[DT_PLTREL] != DT_RELA)
+ return 0;
+
+ if (!lazy) {
+ fails = _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ);
+ } else {
+ Elf_Addr *got;
+ Elf_Addr *plt;
+ int numplt, i;
+
+ /* Relocate processor-specific tags. */
+ object->Dyn.info[DT_PROC(DT_PPC_GOT)] += object->obj_base;
+
+ got = (Elf_Addr *)
+ (Elf_RelA *)(object->Dyn.info[DT_PROC(DT_PPC_GOT)]);
+ got[1] = (Elf_Addr)_dl_bind_start;
+ got[2] = (Elf_Addr)object;
+
+ plt = (Elf_Addr *)
+ (Elf_RelA *)(object->Dyn.info[DT_PLTGOT]);
+ numplt = object->Dyn.info[DT_PLTRELSZ] / sizeof(Elf_RelA);
+ for (i = 0; i < numplt; i++)
+ plt[i] += object->obj_base;
+ }
+
+ return fails;
+}
+
+Elf_Addr
+_dl_bind(elf_object_t *object, int reloff)
+{
+ const Elf_Sym *sym;
+ struct sym_res sr;
+ const char *symn;
+ Elf_RelA *relas;
+ Elf_Addr *plttable;
+ int64_t cookie = pcookie;
+ struct {
+ struct __kbind param;
+ Elf_Addr newval;
+ } buf;
+
+ relas = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff);
+
+ sym = object->dyn.symtab;
+ sym += ELF_R_SYM(relas->r_info);
+ symn = object->dyn.strtab + sym->st_name;
+
+ sr = _dl_find_symbol(symn, SYM_SEARCH_ALL|SYM_WARNNOTFOUND|SYM_PLT,
+ sym, object);
+ if (sr.sym == NULL)
+ _dl_die("lazy binding failed!");
+
+ buf.newval = sr.obj->obj_base + sr.sym->st_value;
+
+ if (__predict_false(sr.obj->traced) && _dl_trace_plt(sr.obj, symn))
+ return buf.newval;
+
+ plttable = (Elf_Addr *)(Elf_RelA *)(object->Dyn.info[DT_PLTGOT]);
+ buf.param.kb_addr = &plttable[ reloff / sizeof(Elf_RelA) ];
+ buf.param.kb_size = sizeof(Elf_Addr);
+
+ {
+ register long syscall_num __asm("r0") = SYS_kbind;
+ register void *arg1 __asm("r3") = &buf.param;
+ register long arg2 __asm("r4") = sizeof(struct __kbind) +
+ sizeof(Elf_Addr);
+ register long arg3 __asm("r5") = cookie;
+
+ __asm volatile("sc" : "+r" (syscall_num), "+r" (arg1),
+ "+r" (arg2) : "r" (arg3) : "cc", "memory");
+ }
+
+ return buf.newval;
+}
diff --git a/libexec/ld.so/powerpc64/syscall.h b/libexec/ld.so/powerpc64/syscall.h
new file mode 100644
index 00000000000..ca623a9e1a5
--- /dev/null
+++ b/libexec/ld.so/powerpc64/syscall.h
@@ -0,0 +1,70 @@
+/* $OpenBSD: syscall.h,v 1.1 2020/06/25 04:00:58 drahn Exp $ */
+
+/*
+ * Copyright (c) 1998 Per Fogelstrom, Opsycon AB
+ *
+ * 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef __DL_SYSCALL_H__
+#define __DL_SYSCALL_H__
+
+#include <sys/syscall.h>
+#include <sys/stat.h>
+
+#ifndef _dl_MAX_ERRNO
+#define _dl_MAX_ERRNO 512L
+#endif
+#define _dl_mmap_error(__res) \
+ ((long)__res < 0 && (long)__res >= -_dl_MAX_ERRNO)
+
+int _dl_close(int);
+__dead
+void _dl_exit(int);
+int _dl_fstat(int, struct stat *);
+ssize_t _dl_getdents(int, char *, size_t);
+int _dl_issetugid(void);
+int _dl_getthrid(void);
+int _dl_mprotect(const void *, size_t, int);
+int _dl_munmap(const void *, size_t);
+int _dl_open(const char *, int);
+int _dl_msyscall(void *addr, size_t len);
+ssize_t _dl_read(int, const char *, size_t);
+int _dl_pledge(const char *, const char **);
+long _dl___syscall(quad_t, ...);
+int _dl_sysctl(const int *, u_int, void *, size_t *, void *, size_t);
+int _dl_utrace(const char *, const void *, size_t);
+int _dl_getentropy(char *, size_t);
+int _dl_sendsyslog(const char *, size_t, int);
+void _dl___set_tcb(void *);
+__dead
+void _dl_thrkill(pid_t, int, void *);
+
+static inline void *
+_dl_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+ return (void *)_dl___syscall(SYS_mmap, addr, len, prot,
+ flags, fd, 0, offset);
+}
+
+#endif /*__DL_SYSCALL_H__*/