Browse Source

nios2: allow to hack on experimenting ld.so support

Waldemar Brodkorb 7 years ago
parent
commit
b30bd74dbc
3 changed files with 98 additions and 11 deletions
  1. 0 1
      extra/Configs/Config.nios2
  2. 12 0
      ldso/ldso/dl-startup.c
  3. 86 10
      ldso/ldso/nios2/dl-startup.h

+ 0 - 1
extra/Configs/Config.nios2

@@ -11,4 +11,3 @@ config FORCE_OPTIONS_FOR_ARCH
 	bool
 	default y
 	select ARCH_LITTLE_ENDIAN
-	select ARCH_HAS_NO_LDSO

+ 12 - 0
ldso/ldso/dl-startup.c

@@ -99,6 +99,10 @@
 extern ElfW(Addr) _begin[] attribute_hidden;
 #endif
 
+#ifdef LDSO_NEED_DPNT
+ElfW(Dyn) *_dl_saved_dpnt = 0;
+#endif
+
 /* Static declarations */
 static int (*_dl_elf_main) (int, char **, char **);
 
@@ -341,6 +345,14 @@ DL_START(unsigned long args)
 	   fixed up by now.  Still no function calls outside of this library,
 	   since the dynamic resolver is not yet ready. */
 
+#ifdef LDSO_NEED_DPNT
+/*XXX TODO this crashes on nios2: it translates to
+ * [r5] := (value of the local variable dpnt)
+ * but r5 is a NULL pointer at this place, which was
+ * retrieved from the GOT a few instructions further above.
+ */
+	_dl_saved_dpnt = dpnt;
+#endif
 	__rtld_stack_end = (void *)(argv - 1);
 
 	_dl_elf_main = (int (*)(int, char **, char **))

+ 86 - 10
ldso/ldso/nios2/dl-startup.h

@@ -1,13 +1,86 @@
-__asm__ ("\
-	.text\n\
-	.globl _start\n\
-	.type _start, %function\n\
-_start:\n\
-        mov r4, sp\n\
-        br _dl_start\n\
-	mov r16, r4\n\
-        jmp r16\n\
-");
+#define LDSO_NEED_DPNT
+
+unsigned int _dl_nios2_get_gp_value(ElfW(Dyn) *dpnt);
+
+unsigned int
+_dl_nios2_get_gp_value (ElfW(Dyn) *dpnt)
+{ 
+	while (dpnt->d_tag != DT_NULL) {
+		if (dpnt->d_tag == DT_NIOS2_GP) {
+			return (unsigned int)(dpnt->d_un.d_ptr);
+		}
+		++dpnt;
+	}
+	return 0;
+}
+
+__asm__ (
+".text\n"
+".globl _start\n"
+".type _start, %function\n"
+"_start:\n"
+"        /* At start time, all the args are on the stack.  */\n"
+"        mov r4, sp\n"
+"\n"
+"        /* Start the calculation of the GOT pointer.  */\n"
+"        nextpc r22\n"
+"1:      movhi r8, %hiadj(_gp_got - 1b)\n"
+"        addi r8, r8, %lo(_gp_got - 1b)\n"
+"\n"
+"        /* Figure out where _dl_start will need to return to.  */\n"
+"        movhi ra, %hiadj(2f - 1b)\n"
+"        addi ra, ra, %lo(2f - 1b)\n"
+"        add ra, ra, r22\n"
+"\n"
+"        /* Finish the calculation of the GOT pointer.  */\n"
+"        add r22, r22, r8\n"
+"\n"
+"        br _dl_start\n"
+"\n"
+"        /* Save the returned user entry point.  */\n"
+"2:      mov r16, r2\n"
+"\n"
+"        /* Initialize gp.  */\n"
+"        ldw r4, %got(_dl_saved_dpnt)(r22)\n"
+"        ldw r8, %call(_dl_nios2_get_gp_value)(r22)\n"
+"        callr r8\n"
+"        mov gp, r2\n"
+"\n"
+"        /* Find the number of arguments to skip.  */\n"
+"        ldw r8, %got(_dl_skip_args)(r22)\n"
+"        ldw r8, 0(r8)\n"
+"\n"
+"        /* Find argc.  */\n"
+"        ldw r5, 0(sp)\n"
+"        sub r5, r5, r8\n"
+"        stw r5, 0(sp)\n"
+"\n"
+"        /* Find the first unskipped argument.  */\n"
+"        slli r8, r8, 2\n"
+"        addi r6, sp, 4\n"
+"        add r9, r6, r8\n"
+"        mov r10, r6\n"
+"\n"
+"        /* Shuffle envp down.  */\n"
+"        mov r7, r10\n"
+"3:      ldw r11, 0(r9)\n"
+"        stw r11, 0(r10)\n"
+"        addi r9, r9, 4\n"
+"        addi r10, r10, 4\n"
+"        bne r11, zero, 3b\n"
+"\n"
+"        /* Shuffle auxv down.  */\n"
+"4:      ldw r11, 4(r9)\n"
+"        stw r11, 4(r10)\n"
+"        ldw r11, 0(r9)\n"
+"        stw r11, 0(r10)\n"
+"        addi r9, r9, 8\n"
+"        addi r10, r10, 8\n"
+"        bne r11, zero, 4b\n"
+"\n"
+"        /* Jump to the user's entry point.  */\n"
+"        jmp r16\n"
+);
 
 /*
  * Get a pointer to the argv array.  On many platforms this can be just
@@ -16,6 +89,9 @@ _start:\n\
  */
 #define GET_ARGV(ARGVP, ARGS) ARGVP = (((unsigned long*) ARGS)+1)
 
+/* We can't call functions earlier in the dl startup process */
+#define NO_FUNCS_BEFORE_BOOTSTRAP
+
 /* The ld.so library requires relocations */
 #define ARCH_NEEDS_BOOTSTRAP_RELOCS