summaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2015-04-13 02:56:26 -0400
committerRich Felker <dalias@aerifal.cx>2015-04-13 03:04:42 -0400
commitf3ddd173806fd5c60b3f034528ca24542aecc5b9 (patch)
tree63cc7432a3c40f011c4818de32ef6257acbf0e73 /arch/mips
parent385c01112c083eb383d972da45836d497cc0556d (diff)
downloadmusl-f3ddd173806fd5c60b3f034528ca24542aecc5b9.tar.gz
dynamic linker bootstrap overhaul
this overhaul further reduces the amount of arch-specific code needed by the dynamic linker and removes a number of assumptions, including: - that symbolic function references inside libc are bound at link time via the linker option -Bsymbolic-functions. - that libc functions used by the dynamic linker do not require access to data symbols. - that static/internal function calls and data accesses can be made without performing any relocations, or that arch-specific startup code handled any such relocations needed. removing these assumptions paves the way for allowing libc.so itself to be built with stack protector (among other things), and is achieved by a three-stage bootstrap process: 1. relative relocations are processed with a flat function. 2. symbolic relocations are processed with no external calls/data. 3. main program and dependency libs are processed with a fully-functional libc/ldso. reduction in arch-specific code is achived through the following: - crt_arch.h, used for generating crt1.o, now provides the entry point for the dynamic linker too. - asm is no longer responsible for skipping the beginning of argv[] when ldso is invoked as a command. - the functionality previously provided by __reloc_self for heavily GOT-dependent RISC archs is now the arch-agnostic stage-1. - arch-specific relocation type codes are mapped directly as macros rather than via an inline translation function/switch statement.
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/crt_arch.h49
-rw-r--r--arch/mips/reloc.h78
2 files changed, 38 insertions, 89 deletions
diff --git a/arch/mips/crt_arch.h b/arch/mips/crt_arch.h
index d4ae52d1..33bde4e6 100644
--- a/arch/mips/crt_arch.h
+++ b/arch/mips/crt_arch.h
@@ -1,21 +1,28 @@
-__asm__("\n\
-.set push\n\
-.set noreorder\n\
-.global __start\n\
-.global _start\n\
-.type __start, @function\n\
-.type _start, @function\n\
-__start:\n\
-_start:\n\
- bal 1f \n\
- move $fp, $0 \n\
-2: .gpword 2b \n\
-1: lw $gp, 0($ra) \n\
- subu $gp, $ra, $gp \n\
- move $4, $sp \n\
- subu $sp, $sp, 16 \n\
- and $sp, $sp, -8 \n\
- lw $25, %call16(__cstart)($gp) \n\
- jalr $25 \n\
- nop \n\
-.set pop");
+__asm__(
+".set push\n"
+".set noreorder\n"
+".global _" START "\n"
+".global " START "\n"
+".type _" START ", @function\n"
+".type " START ", @function\n"
+"_" START ":\n"
+"" START ":\n"
+" bal 1f \n"
+" move $fp, $0 \n"
+"2: .gpword 2b \n"
+ .gpword " START "_c \n"
+".weak _DYNAMIC \n"
+".hidden _DYNAMIC \n"
+" .gpword _DYNAMIC \n"
+"1: lw $gp, 0($ra) \n"
+" subu $gp, $ra, $gp \n"
+" move $4, $sp \n"
+" lw $5, 8($ra) \n"
+" addu $5, $5, $gp \n"
+" lw $25, 4($ra) \n"
+" addu $25, $25, $gp \n"
+" subu $sp, $sp, 16 \n"
+" jalr $25 \n"
+" and $sp, $sp, -8 \n"
+".set pop \n"
+);
diff --git a/arch/mips/reloc.h b/arch/mips/reloc.h
index 4b81d328..8aa02852 100644
--- a/arch/mips/reloc.h
+++ b/arch/mips/reloc.h
@@ -1,5 +1,3 @@
-#include <string.h>
-#include <elf.h>
#include <endian.h>
#if __BYTE_ORDER == __LITTLE_ENDIAN
@@ -18,72 +16,16 @@
#define TPOFF_K (-0x7000)
-static int remap_rel(int type)
-{
- switch(type) {
- case R_MIPS_REL32:
- return REL_SYM_OR_REL;
- case R_MIPS_JUMP_SLOT:
- return REL_PLT;
- case R_MIPS_COPY:
- return REL_COPY;
- case R_MIPS_TLS_DTPMOD32:
- return REL_DTPMOD;
- case R_MIPS_TLS_DTPREL32:
- return REL_DTPOFF;
- case R_MIPS_TLS_TPREL32:
- return REL_TPOFF;
- }
- return 0;
-}
+#define REL_SYM_OR_REL R_MIPS_REL32
+#define REL_PLT R_MIPS_JUMP_SLOT
+#define REL_COPY R_MIPS_COPY
+#define REL_DTPMOD R_MIPS_TLS_DTPMOD32
+#define REL_DTPOFF R_MIPS_TLS_DTPREL32
+#define REL_TPOFF R_MIPS_TLS_TPREL32
-void __reloc_self(int c, size_t *a, size_t *dynv, size_t *got)
-{
- char *base;
- size_t t[20], n;
- for (a+=c+1; *a; a++);
- for (a++; *a; a+=2) if (*a<20) t[*a] = a[1];
- base = (char *)t[AT_BASE];
- if (!base) base = (char *)(t[AT_PHDR] & -t[AT_PAGESZ]);
- for (a=dynv; *a; a+=2) if (*a-0x70000000UL<20) t[*a&31] = a[1];
- n = t[DT_MIPS_LOCAL_GOTNO - 0x70000000];
- for (a=got; n; a++, n--) *a += (size_t)base;
-}
-
-static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride);
-
-static void do_arch_relocs(struct dso *this, struct dso *head)
-{
- unsigned char *base = this->base;
- size_t *dynv = this->dynv;
- size_t dyn[20] = {0};
- size_t i;
- size_t rel[2], got=0;
- Sym *sym;
-
- for (i=0; dynv[i]; i+=2) {
- if (dynv[i]-0x70000000UL<20)
- dyn[dynv[i]&31] = dynv[i+1];
- else if (dynv[i] == DT_PLTGOT)
- got = dynv[i+1];
- }
- i = dyn[DT_MIPS_LOCAL_GOTNO-0x70000000];
- if (this->shortname && !strcmp(this->shortname, "libc.so")) {
- got += sizeof(size_t) * i;
- } else {
- for (; i; i--, got+=sizeof(size_t))
- *(size_t *)(base+got) += (size_t)base;
- }
- sym = this->syms + dyn[DT_MIPS_GOTSYM-0x70000000];
- i = dyn[DT_MIPS_SYMTABNO-0x70000000] - dyn[DT_MIPS_GOTSYM-0x70000000];
- for (; i; i--, got+=sizeof(size_t), sym++) {
- rel[0] = got;
- rel[1] = sym-this->syms << 8 | R_MIPS_JUMP_SLOT;
- *(size_t *)(base+got) = 0;
- do_relocs(this, rel, sizeof rel, 2);
- }
-}
-
-#define NEED_ARCH_RELOCS 1
+#define NEED_MIPS_GOT_RELOCS 1
#define DYNAMIC_IS_RO 1
#define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT))
+
+#define CRTJMP(pc,sp) __asm__ __volatile__( \
+ "move $sp,%1 ; jr %0" : : "r"(pc), "r"(sp) : "memory" )