add support for the AVR32 platform, namely the ATNGW100 board - joint work with wigyori
[oweals/openwrt.git] / toolchain / uClibc / patches / 407-ldso-avr32-2.patch
1 Subject: [PATCH] ldso: AVR32 support
2
3 This implements the AVR32-specific parts of the dynamic linker.
4
5 ---
6
7  ldso/ldso/avr32/dl-debug.h    |   45 +++++++++
8  ldso/ldso/avr32/dl-startup.h  |  110 ++++++++++++++++++++++++
9  ldso/ldso/avr32/dl-syscalls.h |    5 +
10  ldso/ldso/avr32/dl-sysdep.h   |  103 ++++++++++++++++++++++
11  ldso/ldso/avr32/elfinterp.c   |  191 ++++++++++++++++++++++++++++++++++++++++++
12  ldso/ldso/avr32/resolve.S     |   28 ++++++
13  6 files changed, 482 insertions(+)
14
15 Index: uClibc-0.9.28/ldso/ldso/avr32/dl-debug.h
16 ===================================================================
17 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
18 +++ uClibc-0.9.28/ldso/ldso/avr32/dl-debug.h    2006-05-05 09:30:43.000000000 +0200
19 @@ -0,0 +1,45 @@
20 +/*
21 + * AVR32 ELF shared libary loader support
22 + *
23 + * Copyright (C) 2005 Atmel Norway
24 + * All rights reserved.
25 + *
26 + * Redistribution and use in source and binary forms, with or without
27 + * modification, are permitted provided that the following conditions
28 + * are met:
29 + * 1. Redistributions of source code must retain the above copyright
30 + *    notice, this list of conditions and the following disclaimer.
31 + * 2. The name of the above contributors may not be
32 + *    used to endorse or promote products derived from this software
33 + *    without specific prior written permission.
34 + *
35 + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
36 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
38 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
39 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
40 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
41 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
42 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
43 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
44 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 + * SUCH DAMAGE.
46 + */
47 +
48 +static const char *_dl_reltypes_tab[] = {
49 +    "R_AVR32_NONE",
50 +    "R_AVR32_32", "R_AVR32_16", "R_AVR32_8",
51 +    "R_AVR32_32_PCREL", "R_AVR32_16_PCREL", "R_AVR32_8_PCREL",
52 +    "R_AVR32_DIFF32", "R_AVR32_DIFF16", "R_AVR32_DIFF8",
53 +    "R_AVR32_GOT32", "R_AVR32_GOT16", "R_AVR32_GOT8",
54 +    "R_AVR32_21S", "R_AVR32_16U", "R_AVR32_16S", "R_AVR32_8S", "R_AVR32_8S_EXT",
55 +    "R_AVR32_22H_PCREL", "R_AVR32_18W_PCREL", "R_AVR32_16B_PCREL",
56 +    "R_AVR32_16N_PCREL", "R_AVR32_14UW_PCREL", "R_AVR32_11H_PCREL",
57 +    "R_AVR32_10UW_PCREL", "R_AVR32_9H_PCREL", "R_AVR32_9UW_PCREL",
58 +    "R_AVR32_HI16", "R_AVR32_LO16",
59 +    "R_AVR32_GOTPC", "R_AVR32_GOTCALL", "R_AVR32_LDA_GOT",
60 +    "R_AVR32_GOT21S", "R_AVR32_GOT18SW", "R_AVR32_GOT16S", "R_AVR32_GOT7UW",
61 +    "R_AVR32_32_CPENT", "R_AVR32_CPCALL", "R_AVR32_16_CP", "R_AVR32_9W_CP",
62 +    "R_AVR32_RELATIVE", "R_AVR32_GLOB_DAT", "R_AVR32_JMP_SLOT",
63 +    "R_AVR32_ALIGN",
64 +};
65 Index: uClibc-0.9.28/ldso/ldso/avr32/dl-startup.h
66 ===================================================================
67 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
68 +++ uClibc-0.9.28/ldso/ldso/avr32/dl-startup.h  2006-05-05 09:29:45.000000000 +0200
69 @@ -0,0 +1,110 @@
70 +/* vi: set sw=4 ts=4: */
71 +/*
72 + * Architecture specific code used by dl-startup.c
73 + * Copyright (C) 2005 Atmel Norway
74 + */
75 +
76 +/* This is the library loader's main entry point. Let _dl_boot2 do its
77 + * initializations and jump to the application's entry point
78 + * afterwards. */
79 +asm(   "       .text\n"
80 +       "       .global _start\n"
81 +       "       .type   _start,@function\n"
82 +       "_start:\n"
83 +       /* All arguments are on the stack initially */
84 +       "       mov     r12, sp\n"
85 +       "       rcall   _dl_start\n"
86 +       /* Returns user entry point in r12. Save it. */
87 +       "       mov     r0, r12\n"
88 +       /* We're PIC, so get the Global Offset Table */
89 +       "       lddpc   r6, .L_GOT\n"
90 +       ".L_RGOT:\n"
91 +       "       rsub    r6, pc\n"
92 +       /* Adjust argc and argv according to _dl_skip_args */
93 +       "       ld.w    r1, r6[_dl_skip_args@got]\n"
94 +       "       ld.w    r1, r1[0]\n"
95 +       "       ld.w    r2, sp++\n"
96 +       "       sub     r2, r1\n"
97 +       "       add     sp, sp, r1 << 2\n"
98 +       "       st.w    --sp, r2\n"
99 +       /* Load the finalizer function */
100 +       "       ld.w    r12, r6[_dl_fini@got]\n"
101 +       /* Jump to the user's entry point */
102 +       "       mov     pc, r0\n\n"
103 +
104 +       "       .align  2\n"
105 +       ".L_GOT:"
106 +       "       .long   .L_RGOT - _GLOBAL_OFFSET_TABLE_\n"
107 +       "       .size   _start, . - _start\n"
108 +       "       .previous\n");
109 +
110 +/* Get a pointer to the argv array.  On many platforms this can be just
111 + * the address if the first argument, on other platforms we need to
112 + * do something a little more subtle here. */
113 +#define GET_ARGV(ARGVP, ARGS) ARGVP = ((unsigned long *)ARGS + 1)
114 +
115 +
116 +/* We can't call functions before the GOT has been initialized */
117 +#define NO_FUNCS_BEFORE_BOOTSTRAP
118 +
119 +/*
120 + * Relocate the GOT during dynamic loader bootstrap.  This will add
121 + * the load address to all entries in the GOT, which is necessary
122 + * because the linker doesn't generate R_AVR32_RELATIVE relocs for the
123 + * GOT.
124 + */
125 +static __always_inline
126 +void PERFORM_BOOTSTRAP_GOT(struct elf_resolve *tpnt)
127 +{
128 +       Elf32_Addr i, nr_got;
129 +       register Elf32_Addr *__r6 __asm__("r6");
130 +       Elf32_Addr *got = __r6;
131 +
132 +       nr_got = tpnt->dynamic_info[DT_AVR32_GOTSZ_IDX] / sizeof(*got);
133 +       for (i = 2; i < nr_got; i++)
134 +               got[i] += tpnt->loadaddr;
135 +}
136 +
137 +#define PERFORM_BOOTSTRAP_GOT(tpnt) PERFORM_BOOTSTRAP_GOT(tpnt)
138 +
139 +/* Handle relocation of the symbols in the dynamic loader. */
140 +static __always_inline
141 +void PERFORM_BOOTSTRAP_RELOC(ELF_RELOC *rpnt, unsigned long *reloc_addr,
142 +                            unsigned long symbol_addr,
143 +                            unsigned long load_addr, Elf32_Sym *symtab)
144 +{
145 +       switch(ELF32_R_TYPE(rpnt->r_info)) {
146 +       case R_AVR32_NONE:
147 +               break;
148 +       case R_AVR32_GLOB_DAT:
149 +       case R_AVR32_JMP_SLOT:
150 +               *reloc_addr = symbol_addr;
151 +               break;
152 +       case R_AVR32_RELATIVE:
153 +               SEND_STDERR_DEBUG("Applying RELATIVE relocation: ");
154 +               SEND_ADDRESS_STDERR_DEBUG(load_addr, 0);
155 +               SEND_STDERR_DEBUG(" + ");
156 +               SEND_ADDRESS_STDERR_DEBUG(rpnt->r_addend, 1);
157 +               *reloc_addr = load_addr + rpnt->r_addend;
158 +               break;
159 +       default:
160 +               SEND_STDERR("BOOTSTRAP_RELOC: unhandled reloc_type ");
161 +               SEND_NUMBER_STDERR(ELF32_R_TYPE(rpnt->r_info), 1);
162 +               SEND_STDERR("REL, SYMBOL, LOAD: ");
163 +               SEND_ADDRESS_STDERR(reloc_addr, 0);
164 +               SEND_STDERR(", ");
165 +               SEND_ADDRESS_STDERR(symbol_addr, 0);
166 +               SEND_STDERR(", ");
167 +               SEND_ADDRESS_STDERR(load_addr, 1);
168 +               _dl_exit(1);
169 +       }
170 +}
171 +
172 +/* Transfer control to the user's application, once the dynamic loader
173 + * is done. This routine has to exit the current function, then call
174 + * the _dl_elf_main function.
175 + *
176 + * Since our _dl_boot will simply call whatever is returned by
177 + * _dl_boot2, we can just return the address we're supposed to
178 + * call.  */
179 +#define START()        return _dl_elf_main;
180 Index: uClibc-0.9.28/ldso/ldso/avr32/dl-syscalls.h
181 ===================================================================
182 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
183 +++ uClibc-0.9.28/ldso/ldso/avr32/dl-syscalls.h 2006-05-05 09:29:25.000000000 +0200
184 @@ -0,0 +1,5 @@
185 +/* We can't use the real errno in ldso, since it has not yet
186 + * been dynamicly linked in yet. */
187 +extern int _dl_errno;
188 +#define __set_errno(X) {(_dl_errno) = (X);}
189 +#include "sys/syscall.h"
190 Index: uClibc-0.9.28/ldso/ldso/avr32/dl-sysdep.h
191 ===================================================================
192 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
193 +++ uClibc-0.9.28/ldso/ldso/avr32/dl-sysdep.h   2006-05-05 09:30:43.000000000 +0200
194 @@ -0,0 +1,103 @@
195 +/* vi: set sw=4 ts=4: */
196 +/*
197 + * Various assembly language/system dependent hacks that are required
198 + * so that we can minimize the amount of platform specific code.
199 + * Copyright (C) 2004-2005 Atmel Norway
200 + */
201 +
202 +/* Define this if the system uses RELOCA. */
203 +#define ELF_USES_RELOCA
204 +
205 +#include <elf.h>
206 +
207 +#define ARCH_NUM 1
208 +#define DT_AVR32_GOTSZ_IDX     (DT_NUM + OS_NUM)
209 +
210 +#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr)                   \
211 +       do {                                                            \
212 +               if (dpnt->d_tag == DT_AVR32_GOTSZ)                      \
213 +                       dynamic[DT_AVR32_GOTSZ_IDX] = dpnt->d_un.d_val; \
214 +       } while (0)
215 +
216 +/* Initialization sequence for the application/library GOT. */
217 +#define INIT_GOT(GOT_BASE,MODULE)                                      \
218 +       do {                                                            \
219 +               unsigned long i, nr_got;                                \
220 +                                                                       \
221 +               GOT_BASE[0] = (unsigned long) _dl_linux_resolve;        \
222 +               GOT_BASE[1] = (unsigned long) MODULE;                   \
223 +                                                                       \
224 +               /* Add load address displacement to all GOT entries */  \
225 +               nr_got = MODULE->dynamic_info[DT_AVR32_GOTSZ_IDX] / 4;  \
226 +               for (i = 2; i < nr_got; i++)                            \
227 +                       GOT_BASE[i] += (unsigned long)MODULE->loadaddr; \
228 +       } while (0)
229 +
230 +#define do_rem(result, n, base)        ((result) = (n) % (base))
231 +
232 +/* Here we define the magic numbers that this dynamic loader should accept */
233 +#define MAGIC1 EM_AVR32
234 +#undef MAGIC2
235 +
236 +/* Used for error messages */
237 +#define ELF_TARGET "AVR32"
238 +
239 +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got);
240 +
241 +/* 4096 bytes alignment */
242 +#define PAGE_ALIGN 0xfffff000
243 +#define ADDR_ALIGN 0xfff
244 +#define OFFS_ALIGN 0x7ffff000
245 +
246 +#define elf_machine_type_class(type)                           \
247 +       ((type == R_AVR32_JMP_SLOT) * ELF_RTYPE_CLASS_PLT)
248 +
249 +/* AVR32 doesn't need any COPY relocs */
250 +#define DL_NO_COPY_RELOCS
251 +
252 +/* Return the link-time address of _DYNAMIC.  Conveniently, this is the
253 +   first element of the GOT.  This must be inlined in a function which
254 +   uses global data.  */
255 +static inline Elf32_Addr
256 +elf_machine_dynamic (void)
257 +{
258 +       register Elf32_Addr *got asm ("r6");
259 +       return *got;
260 +}
261 +
262 +/* Return the run-time load address of the shared object.  */
263 +static inline Elf32_Addr
264 +elf_machine_load_address (void)
265 +{
266 +       extern void __dl_start asm("_dl_start");
267 +       Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
268 +       Elf32_Addr pcrel_addr;
269 +
270 +       asm   ("        lddpc   %0, 2f\n"
271 +              "1:      add     %0, pc\n"
272 +              "        rjmp    3f\n"
273 +              "        .align  2\n"
274 +              "2:      .long   _dl_start - 1b\n"
275 +              "3:\n"
276 +              : "=r"(pcrel_addr) : : "cc");
277 +
278 +       return pcrel_addr - got_addr;
279 +}
280 +
281 +/*
282 + * Perform any RELATIVE relocations specified by DT_RELCOUNT.
283 + * Currently, we don't use that tag, but we might in the future as
284 + * this would reduce the startup time somewhat (although probably not by much).
285 + */
286 +static inline void
287 +elf_machine_relative (Elf32_Addr load_off, const Elf32_Addr rel_addr,
288 +                     Elf32_Word relative_count)
289 +{
290 +       Elf32_Rela *rpnt = (void *)rel_addr;
291 +
292 +       do {
293 +               Elf32_Addr *reloc_addr;
294 +               reloc_addr = (void *)(load_off + (rpnt++)->r_offset);
295 +               *reloc_addr = load_off + rpnt->r_addend;
296 +       } while (--relative_count);
297 +}
298 Index: uClibc-0.9.28/ldso/ldso/avr32/elfinterp.c
299 ===================================================================
300 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
301 +++ uClibc-0.9.28/ldso/ldso/avr32/elfinterp.c   2006-05-05 09:30:43.000000000 +0200
302 @@ -0,0 +1,191 @@
303 +/*
304 + * AVR32 ELF shared library loader suppport
305 + *
306 + * Copyright (C) 2004-2006 Atmel Corporation
307 + *
308 + * All rights reserved.
309 + *
310 + * Redistribution and use in source and binary forms, with or without
311 + * modification, are permitted provided that the following conditions
312 + * are met:
313 + * 1. Redistributions of source code must retain the above copyright
314 + *    notice, this list of conditions and the following disclaimer.
315 + * 2. The name of the above contributors may not be
316 + *    used to endorse or promote products derived from this software
317 + *    without specific prior written permission.
318 + *
319 + * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
320 + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
321 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
322 + * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
323 + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
324 + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
325 + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
326 + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
327 + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
328 + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
329 + * SUCH DAMAGE.
330 + */
331 +
332 +unsigned long _dl_linux_resolver(unsigned long got_offset, unsigned long *got)
333 +{
334 +       struct elf_resolve *tpnt = (struct elf_resolve *)got[1];
335 +       Elf32_Sym *sym;
336 +       unsigned long local_gotno;
337 +       unsigned long gotsym;
338 +       unsigned long new_addr;
339 +       char *strtab, *symname;
340 +       unsigned long *entry;
341 +       unsigned long sym_index = got_offset / 4;
342 +
343 +#if 0
344 +       local_gotno = tpnt->dynamic_info[DT_AVR32_LOCAL_GOTNO];
345 +       gotsym = tpnt->dynamic_info[DT_AVR32_GOTSYM];
346 +
347 +       sym = ((Elf32_Sym *)(tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr))
348 +               + sym_index;
349 +       strtab = (char *)(tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
350 +       symname = strtab + sym->st_name;
351 +
352 +#if 0
353 +       new_addr = (unsigned long) _dl_find_hash(strtab + sym->st_name,
354 +                                                tpnt->symbol_scope, tpnt,
355 +                                                resolver);
356 +#endif
357 +
358 +       entry = (unsigned long *)(got + local_gotno + sym_index - gotsym);
359 +       *entry = new_addr;
360 +#endif
361 +
362 +       return new_addr;
363 +}
364 +
365 +static int
366 +_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
367 +         unsigned long rel_addr, unsigned long rel_size,
368 +         int (*reloc_func)(struct elf_resolve *tpnt, struct dyn_elf *scope,
369 +                           Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab))
370 +{
371 +       Elf32_Sym *symtab;
372 +       Elf32_Rela *rpnt;
373 +       char *strtab;
374 +       int i;
375 +
376 +       rpnt = (Elf32_Rela *)rel_addr;
377 +       rel_size /= sizeof(Elf32_Rela);
378 +       symtab = (Elf32_Sym *)tpnt->dynamic_info[DT_SYMTAB];
379 +       strtab = (char *)tpnt->dynamic_info[DT_STRTAB];
380 +
381 +       for (i = 0; i < rel_size; i++, rpnt++) {
382 +               int symtab_index, res;
383 +
384 +               symtab_index = ELF32_R_SYM(rpnt->r_info);
385 +
386 +               debug_sym(symtab, strtab, symtab_index);
387 +               debug_reloc(symtab, strtab, rpnt);
388 +
389 +               res = reloc_func(tpnt, scope, rpnt, symtab, strtab);
390 +
391 +               if (res == 0)
392 +                       continue;
393 +
394 +               _dl_dprintf(2, "\n%s: ", _dl_progname);
395 +
396 +               if (symtab_index)
397 +                       _dl_dprintf(2, "symbol '%s': ",
398 +                                   strtab + symtab[symtab_index].st_name);
399 +
400 +               if (res < 0) {
401 +                       int reloc_type = ELF32_R_TYPE(rpnt->r_info);
402 +#if defined(__SUPPORT_LD_DEBUG__)
403 +                       _dl_dprintf(2, "can't handle reloc type %s\n",
404 +                                   _dl_reltypes(reloc_type));
405 +#else
406 +                       _dl_dprintf(2, "can't handle reloc type %x\n",
407 +                                   reloc_type);
408 +#endif
409 +                       _dl_exit(-res);
410 +               } else {
411 +                       _dl_dprintf(2, "can't resolve symbol\n");
412 +                       return res;
413 +               }
414 +       }
415 +
416 +       return 0;
417 +}
418 +
419 +static int _dl_do_reloc(struct elf_resolve *tpnt, struct dyn_elf *scope,
420 +                       Elf32_Rela *rpnt, Elf32_Sym *symtab, char *strtab)
421 +{
422 +       int reloc_type;
423 +       int symtab_index;
424 +       char *symname;
425 +       unsigned long *reloc_addr;
426 +       unsigned long symbol_addr;
427 +#if defined(__SUPPORT_LD_DEBUG__)
428 +       unsigned long old_val;
429 +#endif
430 +
431 +       reloc_addr = (unsigned long *)(tpnt->loadaddr + rpnt->r_offset);
432 +       reloc_type = ELF32_R_TYPE(rpnt->r_info);
433 +       symtab_index = ELF32_R_SYM(rpnt->r_info);
434 +       symbol_addr = 0;
435 +       symname = strtab + symtab[symtab_index].st_name;
436 +
437 +       if (symtab_index) {
438 +               symbol_addr = (unsigned long)
439 +                       _dl_find_hash(strtab + symtab[symtab_index].st_name,
440 +                                     tpnt->symbol_scope, tpnt,
441 +                                     elf_machine_type_class(reloc_type));
442 +
443 +               /* Allow undefined references to weak symbols */
444 +               if (!symbol_addr &&
445 +                   ELF32_ST_BIND(symtab[symtab_index].st_info) != STB_WEAK) {
446 +                       _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
447 +                                   _dl_progname, symname);
448 +                       return 0;
449 +               }
450 +       }
451 +
452 +#if defined(__SUPPORT_LD_DEBUG__)
453 +       old_val = *reloc_addr;
454 +#endif
455 +       switch (reloc_type) {
456 +       case R_AVR32_NONE:
457 +               break;
458 +       case R_AVR32_GLOB_DAT:
459 +       case R_AVR32_JMP_SLOT:
460 +               *reloc_addr = symbol_addr + rpnt->r_addend;
461 +               break;
462 +       case R_AVR32_RELATIVE:
463 +               *reloc_addr = (unsigned long)tpnt->loadaddr
464 +                       + rpnt->r_addend;
465 +               break;
466 +       default:
467 +               return -1;
468 +       }
469 +
470 +#if defined(__SUPPORT_LD_DEBUG__)
471 +       if (_dl_debug_reloc && _dl_debug_detail)
472 +               _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x\n",
473 +                           old_val, *reloc_addr);
474 +#endif
475 +
476 +       return 0;
477 +}
478 +
479 +void _dl_parse_lazy_relocation_information(struct dyn_elf *rpnt,
480 +                                          unsigned long rel_addr,
481 +                                          unsigned long rel_size)
482 +{
483 +       /* TODO: Might want to support this in order to get faster
484 +        * startup times... */
485 +}
486 +
487 +int _dl_parse_relocation_information(struct dyn_elf *rpnt,
488 +                                    unsigned long rel_addr,
489 +                                    unsigned long rel_size)
490 +{
491 +       return _dl_parse(rpnt->dyn, rpnt->dyn->symbol_scope, rel_addr, rel_size,
492 +                        _dl_do_reloc);
493 +}
494 Index: uClibc-0.9.28/ldso/ldso/avr32/resolve.S
495 ===================================================================
496 --- /dev/null   1970-01-01 00:00:00.000000000 +0000
497 +++ uClibc-0.9.28/ldso/ldso/avr32/resolve.S     2006-05-05 09:29:25.000000000 +0200
498 @@ -0,0 +1,28 @@
499 +/*
500 + * Linux dynamic resolving code for AVR32. Fixes up the GOT entry as
501 + * indicated in register r12 and jumps to the resolved address.
502 + *
503 + * This file is subject to the terms and conditions of the GNU Lesser General
504 + * Public License.  See the file "COPYING.LIB" in the main directory of this
505 + * archive for more details.
506 + *
507 + * Copyright (C) 2004 Atmel Norway
508 + */
509 +
510 +#define ip r5
511 +
512 +       .text
513 +       .global _dl_linux_resolve
514 +       .type   _dl_linux_resolve,@function
515 +_dl_linux_resolve:
516 +       /* The PLT code pushed r8 for us. It contains the address of this
517 +          function's GOT entry, that is entry 0. ip contains the address
518 +          of the GOT entry of the function we wanted to call. */
519 +       stm     --sp, r9-r12, lr
520 +       mov     r11, r8
521 +       sub     r12, ip, r8
522 +       rcall   _dl_linux_resolver
523 +       mov     ip, r12
524 +       popm    r8-r12,lr
525 +       mov     pc, ip
526 +       .size   _dl_linux_resolve, . - _dl_linux_resolve