1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
#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
* the address of the first argument, on other platforms we need to
* do something a little more subtle here.
*/
#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
static __always_inline
void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
unsigned long symbol_addr, unsigned long load_addr, attribute_unused Elf32_Sym *symtab)
{
switch (ELF_R_TYPE(rpnt->r_info)) {
case R_NIOS2_RELATIVE:
*reloc_addr = load_addr + rpnt->r_addend;
break;
default:
_dl_exit(1);
break;
}
}
|