]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4re-core/uclibc/lib/contrib/uclibc/ldso/ldso/avr32/dl-startup.h
Update
[l4.git] / l4 / pkg / l4re-core / uclibc / lib / contrib / uclibc / ldso / ldso / avr32 / dl-startup.h
1 /*
2  * Architecture specific code used by dl-startup.c
3  *
4  * Copyright (C) 2005-2007 Atmel Corporation
5  *
6  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
7  */
8
9 /* This is the library loader's main entry point. Let _dl_boot2 do its
10  * initializations and jump to the application's entry point
11  * afterwards. */
12 __asm__("       .text\n"
13         "       .global _start\n"
14         "       .type   _start,@function\n"
15         "       .hidden _start\n"
16         "_start:\n"
17         /* All arguments are on the stack initially */
18         "       mov     r12, sp\n"
19         "       rcall   _dl_start\n"
20         /* Returns user entry point in r12. Save it. */
21         "       mov     r0, r12\n"
22         /* We're PIC, so get the Global Offset Table */
23         "       lddpc   r6, .L_GOT\n"
24         ".L_RGOT:\n"
25         "       rsub    r6, pc\n"
26         /* Adjust argc and argv according to _dl_skip_args */
27         "       ld.w    r1, r6[_dl_skip_args@got]\n"
28         "       ld.w    r1, r1[0]\n"
29         "       ld.w    r2, sp++\n"
30         "       sub     r2, r1\n"
31         "       add     sp, sp, r1 << 2\n"
32         "       st.w    --sp, r2\n"
33         /* Load the finalizer function */
34         "       ld.w    r12, r6[_dl_fini@got]\n"
35         /* Jump to the user's entry point */
36         "       mov     pc, r0\n\n"
37
38         "       .align  2\n"
39         ".L_GOT:"
40         "       .long   .L_RGOT - _GLOBAL_OFFSET_TABLE_\n"
41         "       .size   _start, . - _start\n"
42         "       .previous\n");
43
44 /* Get a pointer to the argv array.  On many platforms this can be just
45  * the address of the first argument, on other platforms we need to
46  * do something a little more subtle here. */
47 #define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1)
48
49
50 /* We can't call functions before the GOT has been initialized */
51 #define NO_FUNCS_BEFORE_BOOTSTRAP
52
53 /*
54  * Relocate the GOT during dynamic loader bootstrap.  This will add
55  * the load address to all entries in the GOT, which is necessary
56  * because the linker doesn't generate R_AVR32_RELATIVE relocs for the
57  * GOT.
58  */
59 static __always_inline
60 void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt)
61 {
62         Elf32_Addr i, nr_got;
63         register Elf32_Addr *__r6 __asm__("r6");
64         Elf32_Addr *got = __r6;
65
66         nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got);
67         for (i = 2; i < nr_got; i++)
68                 got[i] += tpnt->loadaddr;
69 }
70
71 #define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt)
72
73 /* Handle relocation of the symbols in the dynamic loader. */
74 static __always_inline
75 void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
76                              unsigned long symbol_addr,
77                              unsigned long load_addr, Elf32_Sym *symtab)
78 {
79         switch(ELF_R_TYPE(rpnt->r_info)) {
80         case R_AVR32_NONE:
81                 break;
82         case R_AVR32_GLOB_DAT:
83         case R_AVR32_JMP_SLOT:
84                 *reloc_addr = symbol_addr;
85                 break;
86         case R_AVR32_RELATIVE:
87                 SEND_STDERR_DEBUG("Applying RELATIVE relocation: ");
88                 SEND_ADDRESS_STDERR_DEBUG(load_addr, 0);
89                 SEND_STDERR_DEBUG(" + ");
90                 SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1);
91                 *reloc_addr = load_addr + rpnt->r_addend;
92                 break;
93         default:
94                 SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type ");
95                 SEND_NUMBER_STDERR(ELF_R_TYPE(rpnt->r_info), 1);
96                 SEND_STDERR("REL, SYMBOL, LOAD: ");
97                 SEND_ADDRESS_STDERR(reloc_addr, 0);
98                 SEND_STDERR(", ");
99                 SEND_ADDRESS_STDERR(symbol_addr, 0);
100                 SEND_STDERR(", ");
101                 SEND_ADDRESS_STDERR(load_addr, 1);
102                 _dl_exit(1);
103         }
104 }