2 * AVR32 ELF shared library loader suppport
4 * Copyright (C) 2004-2006 Atmel Corporation
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. The name of the above contributors may not be
14 * used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 unsigned long _dl_linux_resolver(unsigned long got_offset
, unsigned long *got
)
33 * AVR32 currently does not do lazy relocation.
36 struct elf_resolve
*tpnt
= (struct elf_resolve
*)got
[1];
38 unsigned long local_gotno
;
40 unsigned long new_addr
;
41 char *strtab
, *symname
;
43 unsigned long sym_index
= got_offset
/ 4;
45 local_gotno
= tpnt
->dynamic_info
[DT_AVR32_LOCAL_GOTNO
];
46 gotsym
= tpnt
->dynamic_info
[DT_AVR32_GOTSYM
];
48 sym
= ((Elf32_Sym
*)(tpnt
->dynamic_info
[DT_SYMTAB
] + tpnt
->loadaddr
))
50 strtab
= (char *)(tpnt
->dynamic_info
[DT_STRTAB
] + tpnt
->loadaddr
);
51 symname
= strtab
+ sym
->st_name
;
53 new_addr
= (unsigned long) _dl_find_hash(symname
,
54 tpnt
->symbol_scope
, tpnt
, ELF_RTYPE_CLASS_PLT
, NULL
);
56 entry
= (unsigned long *)(got
+ local_gotno
+ sym_index
- gotsym
);
65 _dl_parse(struct elf_resolve
*tpnt
, struct dyn_elf
*scope
,
66 unsigned long rel_addr
, unsigned long rel_size
,
67 int (*reloc_func
)(struct elf_resolve
*tpnt
, struct dyn_elf
*scope
,
68 Elf32_Rela
*rpnt
, Elf32_Sym
*symtab
, char *strtab
))
75 rpnt
= (Elf32_Rela
*)rel_addr
;
76 rel_size
/= sizeof(Elf32_Rela
);
77 symtab
= (Elf32_Sym
*)tpnt
->dynamic_info
[DT_SYMTAB
];
78 strtab
= (char *)tpnt
->dynamic_info
[DT_STRTAB
];
80 for (i
= 0; i
< rel_size
; i
++, rpnt
++) {
81 int symtab_index
, res
;
83 symtab_index
= ELF32_R_SYM(rpnt
->r_info
);
85 debug_sym(symtab
, strtab
, symtab_index
);
86 debug_reloc(symtab
, strtab
, rpnt
);
88 res
= reloc_func(tpnt
, scope
, rpnt
, symtab
, strtab
);
93 _dl_dprintf(2, "\n%s: ", _dl_progname
);
96 _dl_dprintf(2, "symbol '%s': ",
97 strtab
+ symtab
[symtab_index
].st_name
);
100 int reloc_type
= ELF32_R_TYPE(rpnt
->r_info
);
101 #if defined(__SUPPORT_LD_DEBUG__)
102 _dl_dprintf(2, "can't handle reloc type %s\n",
103 _dl_reltypes(reloc_type
));
105 _dl_dprintf(2, "can't handle reloc type %x\n",
110 _dl_dprintf(2, "can't resolve symbol\n");
118 static int _dl_do_reloc(struct elf_resolve
*tpnt
, struct dyn_elf
*scope
,
119 Elf32_Rela
*rpnt
, Elf32_Sym
*symtab
, char *strtab
)
124 unsigned long *reloc_addr
;
125 unsigned long symbol_addr
;
126 #if defined(__SUPPORT_LD_DEBUG__)
127 unsigned long old_val
;
129 struct symbol_ref sym_ref
;
131 reloc_addr
= (unsigned long *)(tpnt
->loadaddr
+ rpnt
->r_offset
);
132 reloc_type
= ELF32_R_TYPE(rpnt
->r_info
);
133 symtab_index
= ELF32_R_SYM(rpnt
->r_info
);
135 sym_ref
.sym
= &symtab
[symtab_index
];
137 symname
= strtab
+ symtab
[symtab_index
].st_name
;
140 symbol_addr
= (unsigned long)
141 _dl_find_hash(symname
, scope
, tpnt
,
142 elf_machine_type_class(reloc_type
), &sym_ref
);
144 /* Allow undefined references to weak symbols */
146 ELF32_ST_BIND(symtab
[symtab_index
].st_info
) != STB_WEAK
) {
147 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
148 _dl_progname
, symname
);
153 #if defined(__SUPPORT_LD_DEBUG__)
154 old_val
= *reloc_addr
;
156 switch (reloc_type
) {
159 case R_AVR32_GLOB_DAT
:
160 case R_AVR32_JMP_SLOT
:
161 *reloc_addr
= symbol_addr
+ rpnt
->r_addend
;
163 case R_AVR32_RELATIVE
:
164 *reloc_addr
= (unsigned long)tpnt
->loadaddr
171 #if defined(__SUPPORT_LD_DEBUG__)
172 if (_dl_debug_reloc
&& _dl_debug_detail
)
173 _dl_dprintf(_dl_debug_file
, "\tpatched: %x ==> %x @ %x\n",
174 old_val
, *reloc_addr
);
180 void _dl_parse_lazy_relocation_information(struct dyn_elf
*rpnt
,
181 unsigned long rel_addr
,
182 unsigned long rel_size
)
184 /* TODO: Might want to support this in order to get faster
185 * startup times... */
188 int _dl_parse_relocation_information(struct dyn_elf
*rpnt
,
189 unsigned long rel_addr
,
190 unsigned long rel_size
)
192 return _dl_parse(rpnt
->dyn
, rpnt
->dyn
->symbol_scope
, rel_addr
, rel_size
,