diff options
author | drahn <drahn@openbsd.org> | 2020-06-25 04:00:58 +0000 |
---|---|---|
committer | drahn <drahn@openbsd.org> | 2020-06-25 04:00:58 +0000 |
commit | 6a2e3db89fda3dccb5827ac07cf3047f22233350 (patch) | |
tree | 6b686822898e1f4e5680f2d3862fce271cfd43f1 /libexec | |
parent | report rx ring state for all rings, not just the first one. (diff) | |
download | wireguard-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.inc | 11 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/SYS.h | 39 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/archdep.h | 83 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/ld.script | 70 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/ldasm.S | 127 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/rtld_machine.c | 349 | ||||
-rw-r--r-- | libexec/ld.so/powerpc64/syscall.h | 70 |
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__*/ |