summaryrefslogtreecommitdiff
path: root/lib/csu/boot.h
diff options
context:
space:
mode:
authorKurt Miller <kurt@cvs.openbsd.org>2014-12-22 03:51:09 +0000
committerKurt Miller <kurt@cvs.openbsd.org>2014-12-22 03:51:09 +0000
commit4c3e2b03181a91c59b536d4cdec6f6f5d1cdf236 (patch)
tree85e45cf9486a5541d2fe1b1a8331d72958564c26 /lib/csu/boot.h
parentd98892b19f775c4dd3ad9557727627fb148b2fd0 (diff)
Introduce new csu0 variant for -static -pie binaries to use called
rcsu0.o where the initial 'r' is for relocatable. rcsu0.o performs self-relocation on static pie binaries by calling a slightly modified copy of ld.so's _dl_boot_bind() in boot.h. The first arch implementatation is also included for amd64 where __start calls _dl_boot_bind() and then calls ___start(). Includes parts from kettenis@ to help get R_X86_64_64 relocations working and proper handling for undefined weak symbols. This is the first part of several to get static pie self-relocating binaries working. binutils, gcc and kernel changes are forthcoming to complete the solution, then per-arch implementations are needed for MD_RCRT0_START in csu. okay kettenis@ pascal@ deraadt@
Diffstat (limited to 'lib/csu/boot.h')
-rw-r--r--lib/csu/boot.h250
1 files changed, 250 insertions, 0 deletions
diff --git a/lib/csu/boot.h b/lib/csu/boot.h
new file mode 100644
index 00000000000..a5422d4cf15
--- /dev/null
+++ b/lib/csu/boot.h
@@ -0,0 +1,250 @@
+/* $OpenBSD: boot.h,v 1.1 2014/12/22 03:51:08 kurt 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.
+ *
+ */
+
+/*
+ * IMPORTANT: any functions below are NOT protected by SSP. Please
+ * do not add anything except what is required to reach GOT with
+ * an adjustment.
+ */
+
+#define _DYN_LOADER
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/exec.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <nlist.h>
+#include <link.h>
+#include <dlfcn.h>
+
+#include "syscall.h"
+#include "archdep.h"
+#include "path.h"
+#include "resolve.h"
+#include "sod.h"
+#include "stdlib.h"
+#include "dl_prebind.h"
+
+#include "../../lib/csu/os-note-elf.h"
+
+#ifdef RCRT0
+/*
+ * Local decls.
+ */
+void _dl_boot_bind(const long, long *, Elf_Dyn *);
+
+void
+_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
+{
+ struct elf_object dynld; /* Resolver data for the loader */
+ AuxInfo *auxstack;
+ long *stack;
+ Elf_Dyn *dynp;
+ int n, argc;
+ char **argv, **envp;
+ long loff;
+
+ /*
+ * Scan argument and environment vectors. Find dynamic
+ * data vector put after them.
+ */
+ stack = (long *)sp;
+ argc = *stack++;
+ argv = (char **)stack;
+ envp = &argv[argc + 1];
+ stack = (long *)envp;
+ while (*stack++ != 0L)
+ ;
+
+ /*
+ * Zero out dl_data.
+ */
+ for (n = 0; n <= AUX_entry; n++)
+ dl_data[n] = 0;
+
+ /*
+ * Dig out auxiliary data set up by exec call. Move all known
+ * tags to an indexed local table for easy access.
+ */
+ for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null;
+ auxstack++) {
+ if (auxstack->au_id > AUX_entry)
+ continue;
+ dl_data[auxstack->au_id] = auxstack->au_v;
+ }
+ loff = dl_data[AUX_base]; /* XXX assumes ld.so is linked at 0x0 */
+
+ /*
+ * We need to do 'selfreloc' in case the code weren't
+ * loaded at the address it was linked to.
+ *
+ * Scan the DYNAMIC section for the loader.
+ * Cache the data for easier access.
+ */
+
+#if defined(__alpha__)
+ dynp = (Elf_Dyn *)((long)_DYNAMIC);
+#elif defined(__sparc__) || defined(__sparc64__) || defined(__powerpc__) || \
+ defined(__hppa__) || defined(__sh__)
+ dynp = dynamicp;
+#else
+ dynp = (Elf_Dyn *)((long)_DYNAMIC + loff);
+#endif
+ _dl_memset(dynld.Dyn.info, 0, sizeof(dynld.Dyn.info));
+ while (dynp != NULL && dynp->d_tag != DT_NULL) {
+ if (dynp->d_tag < DT_NUM)
+ dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
+ else if (dynp->d_tag >= DT_LOPROC &&
+ dynp->d_tag < DT_LOPROC + DT_PROCNUM)
+ dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] =
+ dynp->d_un.d_val;
+ if (dynp->d_tag == DT_TEXTREL)
+ dynld.dyn.textrel = 1;
+ dynp++;
+ }
+
+ /*
+ * Do the 'bootstrap relocation'. This is really only needed if
+ * the code was loaded at another location than it was linked to.
+ * We don't do undefined symbols resolving (to difficult..)
+ */
+
+ /* "relocate" dyn.X values if they represent addresses */
+ {
+ int i, val;
+ /* must be code, not pic data */
+ int table[20];
+
+ i = 0;
+ table[i++] = DT_PLTGOT;
+ table[i++] = DT_HASH;
+ table[i++] = DT_STRTAB;
+ table[i++] = DT_SYMTAB;
+ table[i++] = DT_RELA;
+ table[i++] = DT_INIT;
+ table[i++] = DT_FINI;
+ table[i++] = DT_REL;
+ table[i++] = DT_JMPREL;
+ /* other processors insert their extras here */
+ table[i++] = DT_NULL;
+ for (i = 0; table[i] != DT_NULL; i++) {
+ val = table[i];
+ if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM)
+ val = val - DT_LOPROC + DT_NUM;
+ else if (val >= DT_NUM)
+ continue;
+ if (dynld.Dyn.info[val] != 0)
+ dynld.Dyn.info[val] += loff;
+ }
+ }
+
+ {
+ u_int32_t rs;
+ Elf_Rel *rp;
+ int i;
+
+ rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]);
+ rs = dynld.dyn.relsz;
+
+ for (i = 0; i < rs; i += sizeof (Elf_Rel)) {
+ Elf_Addr *ra;
+ const Elf_Sym *sp;
+
+ sp = dynld.dyn.symtab;
+ sp += ELF_R_SYM(rp->r_info);
+
+ if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
+#if 0
+/* cannot printf in this function */
+ _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
+ _dl_wrstderr("Undefined symbol: ");
+ _dl_wrstderr((char *)dynld.dyn.strtab +
+ sp->st_name);
+#endif
+ _dl_exit(5);
+ }
+
+ ra = (Elf_Addr *)(rp->r_offset + loff);
+ RELOC_REL(rp, sp, ra, loff);
+ rp++;
+ }
+ }
+
+ for (n = 0; n < 2; n++) {
+ unsigned long rs;
+ Elf_RelA *rp;
+ int i;
+
+ switch (n) {
+ case 0:
+ rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]);
+ rs = dynld.dyn.pltrelsz;
+ break;
+ case 1:
+ rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]);
+ rs = dynld.dyn.relasz;
+ break;
+ default:
+ rp = NULL;
+ rs = 0;
+ }
+ for (i = 0; i < rs; i += sizeof (Elf_RelA)) {
+ Elf_Addr *ra;
+ const Elf_Sym *sp;
+
+ sp = dynld.dyn.symtab;
+ sp += ELF_R_SYM(rp->r_info);
+ if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
+#if 0
+ _dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
+ _dl_wrstderr("Undefined symbol: ");
+ _dl_wrstderr((char *)dynld.dyn.strtab +
+ sp->st_name);
+#endif
+#ifdef RCRT0
+ continue;
+#else
+ _dl_exit(6);
+#endif
+ }
+
+ ra = (Elf_Addr *)(rp->r_offset + loff);
+ RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot);
+ rp++;
+ }
+ }
+
+ RELOC_GOT(&dynld, loff);
+
+ /*
+ * we have been fully relocated here, so most things no longer
+ * need the loff adjustment
+ */
+}
+#endif /* RCRT0 */