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
 	bool
 	default y
 	default y
 	select ARCH_LITTLE_ENDIAN
 	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;
 extern ElfW(Addr) _begin[] attribute_hidden;
 #endif
 #endif
 
 
+#ifdef LDSO_NEED_DPNT
+ElfW(Dyn) *_dl_saved_dpnt = 0;
+#endif
+
 /* Static declarations */
 /* Static declarations */
 static int (*_dl_elf_main) (int, char **, char **);
 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,
 	   fixed up by now.  Still no function calls outside of this library,
 	   since the dynamic resolver is not yet ready. */
 	   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);
 	__rtld_stack_end = (void *)(argv - 1);
 
 
 	_dl_elf_main = (int (*)(int, char **, char **))
 	_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
  * 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)
 #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 */
 /* The ld.so library requires relocations */
 #define ARCH_NEEDS_BOOTSTRAP_RELOCS
 #define ARCH_NEEDS_BOOTSTRAP_RELOCS