1 /* vi: set sw=4 ts=4: */
2 /* powerpc shared library loader suppport
4 * Copyright (C) 2001-2002, David A. Schleef
5 * Copyright (C) 2003, Erik Andersen
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. The name of the above contributors may not be
15 * used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 #if defined (__SUPPORT_LD_DEBUG__)
32 static const char *_dl_reltypes_tab[] =
33 { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
34 "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
35 "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
36 "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
37 "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
38 "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
39 "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
40 "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
41 "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
42 "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
43 "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
47 _dl_reltypes(int type)
52 if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
53 NULL == (str = _dl_reltypes_tab[type]))
55 str =_dl_simple_ltoa( buf, (unsigned long)(type));
61 void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
66 _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
67 strtab + symtab[symtab_index].st_name,
68 symtab[symtab_index].st_value,
69 symtab[symtab_index].st_size,
70 symtab[symtab_index].st_info,
71 symtab[symtab_index].st_other,
72 symtab[symtab_index].st_shndx);
78 void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
84 symtab_index = ELF32_R_SYM(rpnt->r_info);
85 sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
88 _dl_dprintf(_dl_debug_file, "\n\t");
90 _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
91 #ifdef ELF_USES_RELOCA
92 _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
93 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
97 _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
98 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
105 extern int _dl_linux_resolve(void);
107 void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
110 Elf32_Word num_plt_entries;
111 Elf32_Word data_words;
112 Elf32_Word rel_offset_words;
113 Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve;
115 num_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
116 rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries);
117 data_words = (Elf32_Word) (plt + rel_offset_words);
118 tpnt->data_words = data_words;
120 plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
121 plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
123 plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
124 plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
128 tramp = (Elf32_Word *) (plt + PLT_TRAMPOLINE_ENTRY_WORDS);
130 /* For the long entries, subtract off data_words. */
131 tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
132 tramp[1] = OPCODE_ADDI(11,11,-data_words);
134 /* Multiply index of entry by 3 (in r11). */
135 tramp[2] = OPCODE_SLWI(12,11,1);
136 tramp[3] = OPCODE_ADD(11,12,11);
137 if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000) {
138 /* Load address of link map in r12. */
139 tramp[4] = OPCODE_LI (12, (Elf32_Word) tpnt);
140 tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) tpnt);
142 /* Call _dl_linux_resolve . */
143 tramp[6] = OPCODE_BA (dlrr);
145 /* Get address of _dl_linux_resolve in CTR. */
146 tramp[4] = OPCODE_LI(12,dlrr);
147 tramp[5] = OPCODE_ADDIS_HI(12,12,dlrr);
148 tramp[6] = OPCODE_MTCTR(12);
150 /* Load address of link map in r12. */
151 tramp[7] = OPCODE_LI(12,(Elf32_Word) tpnt);
152 tramp[8] = OPCODE_ADDIS_HI(12,12,(Elf32_Word) tpnt);
154 /* Call _dl_linux_resolve. */
155 tramp[9] = OPCODE_BCTR();
171 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
173 ELF_RELOC *this_reloc;
179 Elf32_Addr *reloc_addr;
180 Elf32_Addr finaladdr;
183 rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
185 this_reloc = (void *)rel_addr + reloc_entry;
186 symtab_index = ELF32_R_SYM(this_reloc->r_info);
188 symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
189 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
190 symname = strtab + symtab[symtab_index].st_name;
192 #if defined (__SUPPORT_LD_DEBUG__)
193 debug_sym(symtab,strtab,symtab_index);
194 debug_reloc(symtab,strtab,this_reloc);
196 if (ELF32_R_TYPE(this_reloc->r_info) != R_PPC_JMP_SLOT) {
197 _dl_dprintf(2, "%s: Incorrect relocation type in jump relocation\n", _dl_progname);
202 /* Address of dump instruction to fix up */
203 reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + this_reloc->r_offset);
205 #if defined (__SUPPORT_LD_DEBUG__)
206 if(_dl_debug_reloc && _dl_debug_detail)
207 _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, (Elf32_Addr)reloc_addr);
210 /* Get the address of the GOT entry */
211 finaladdr = (Elf32_Addr) _dl_find_hash(strtab + symtab[symtab_index].st_name,
212 tpnt->symbol_scope, tpnt, resolver);
214 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
218 #if defined (__SUPPORT_LD_DEBUG__)
219 if(_dl_debug_reloc && _dl_debug_detail)
220 _dl_dprintf(_dl_debug_file, "%x\n", finaladdr);
222 delta = finaladdr - (Elf32_Word)reloc_addr;
223 if (delta<<6>>6 == delta) {
224 *reloc_addr = OPCODE_B(delta);
226 /* this will almost never be true */
227 } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
228 *reloc_addr = OPCODE_BA (finaladdr);
231 /* Warning: we don't handle double-sized PLT entries */
232 Elf32_Word *plt, *data_words, index, offset;
234 plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
235 offset = reloc_addr - plt;
236 index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
237 data_words = (Elf32_Word *)tpnt->data_words;
240 data_words[index] = finaladdr;
242 *reloc_addr = OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
245 /* instructions were modified */
246 PPC_DCBST(reloc_addr);
248 PPC_ICBI(reloc_addr);
255 _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
256 unsigned long rel_addr, unsigned long rel_size,
257 int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
258 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
266 /* Now parse the relocation information */
267 rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
268 rel_size = rel_size / sizeof(ELF_RELOC);
270 symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
271 strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
273 for (i = 0; i < rel_size; i++, rpnt++) {
276 symtab_index = ELF32_R_SYM(rpnt->r_info);
278 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
279 Make sure we do not do them again */
280 if (!symtab_index && tpnt->libtype == program_interpreter)
282 if (symtab_index && tpnt->libtype == program_interpreter &&
283 _dl_symbol(strtab + symtab[symtab_index].st_name))
286 #if defined (__SUPPORT_LD_DEBUG__)
287 debug_sym(symtab,strtab,symtab_index);
288 debug_reloc(symtab,strtab,rpnt);
291 res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
293 if (res==0) continue;
295 _dl_dprintf(2, "\n%s: ",_dl_progname);
298 _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
302 int reloc_type = ELF32_R_TYPE(rpnt->r_info);
303 #if defined (__SUPPORT_LD_DEBUG__)
304 _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
306 _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
312 _dl_dprintf(2, "can't resolve symbol\n");
320 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
321 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
326 Elf32_Addr *reloc_addr;
327 Elf32_Addr finaladdr;
329 unsigned long symbol_addr;
330 #if defined (__SUPPORT_LD_DEBUG__)
331 unsigned long old_val;
333 reloc_addr = (Elf32_Addr *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
334 reloc_type = ELF32_R_TYPE(rpnt->r_info);
335 if (reloc_type == R_PPC_RELATIVE) {
336 *reloc_addr = tpnt->loadaddr + rpnt->r_addend;
339 if (reloc_type == R_PPC_NONE || reloc_type == R_PPC_COPY) /* R_PPC_COPY is handled later */
341 symtab_index = ELF32_R_SYM(rpnt->r_info);
342 symname = strtab + symtab[symtab_index].st_name;
344 symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
345 (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
347 * We want to allow undefined references to weak symbols - this might
348 * have been intentional. We should not be linking local symbols
349 * here, so all bases should be covered.
351 if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
352 #if defined (__SUPPORT_LD_DEBUG__)
353 _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s', rel type: %s\n",
354 symname, tpnt->libname, _dl_reltypes(reloc_type));
358 #if defined (__SUPPORT_LD_DEBUG__)
359 old_val = *reloc_addr;
361 finaladdr = (Elf32_Addr) (symbol_addr + rpnt->r_addend);
363 switch (reloc_type) {
366 *reloc_addr = finaladdr;
367 return 0; /* No code code modified */
371 Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
373 if (delta<<6>>6 == delta) {
374 *reloc_addr = OPCODE_B(delta);
376 /* this will almost never be true */
377 } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
378 *reloc_addr = OPCODE_BA (finaladdr);
381 /* Warning: we don't handle double-sized PLT entries */
382 Elf32_Word *plt, *data_words, index, offset;
384 plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
385 offset = reloc_addr - plt;
386 index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
387 data_words = (Elf32_Word *)tpnt->data_words;
389 data_words[index] = finaladdr;
390 reloc_addr[0] = OPCODE_LI(11,index*4);
391 reloc_addr[1] = OPCODE_B((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
393 /* instructions were modified */
394 PPC_DCBST(reloc_addr+1);
396 PPC_ICBI(reloc_addr+1);
401 /* This does not work yet, R_PPC_COPY is handled later, see if statemet above */
403 #if defined (__SUPPORT_LD_DEBUG__)
405 _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
406 symname, symtab[symtab_index].st_size,
407 symbol_addr, symtab[symtab_index].st_value);
409 _dl_memcpy((char *) reloc_addr, (char *) finaladdr, symtab[symtab_index].st_size);
411 return 0; /* No code code modified */
413 case R_PPC_ADDR16_HA:
414 *(short *)reloc_addr = (finaladdr + 0x8000)>>16;
416 case R_PPC_ADDR16_HI:
417 *(short *)reloc_addr = finaladdr >> 16;
419 case R_PPC_ADDR16_LO:
420 *(short *)reloc_addr = finaladdr;
424 Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
425 if(delta<<6>>6 != delta){
426 _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\tCompile shared libraries with -fPIC!\n",
427 _dl_progname, symname);
430 *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc);
434 _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
435 #if defined (__SUPPORT_LD_DEBUG__)
436 _dl_dprintf(2, "%s ", _dl_reltypes(reloc_type));
439 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
443 /* instructions were modified */
444 PPC_DCBST(reloc_addr);
446 PPC_ICBI(reloc_addr);
448 #if defined (__SUPPORT_LD_DEBUG__)
449 if(_dl_debug_reloc && _dl_debug_detail)
450 _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
455 /* This is done as a separate step, because there are cases where
456 information is first copied and later initialized. This results in
457 the wrong information being copied. Someone at Sun was complaining about
458 a bug in the handling of _COPY by SVr4, and this may in fact be what he
459 was talking about. Sigh. */
461 _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
462 ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
466 unsigned long *reloc_addr;
467 unsigned long symbol_addr;
471 reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
472 reloc_type = ELF32_R_TYPE(rpnt->r_info);
473 if (reloc_type != R_PPC_COPY)
475 symtab_index = ELF32_R_SYM(rpnt->r_info);
477 symname = strtab + symtab[symtab_index].st_name;
480 symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
481 if (!symbol_addr) goof++;
484 #if defined (__SUPPORT_LD_DEBUG__)
486 _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
487 symname, symtab[symtab_index].st_size,
488 symbol_addr, symtab[symtab_index].st_value);
490 _dl_memcpy((char *) reloc_addr,
491 (char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
497 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
498 unsigned long rel_addr, unsigned long rel_size, int type)
500 Elf32_Word *plt, offset, i, num_plt_entries, rel_offset_words;
503 num_plt_entries = rel_size / sizeof(ELF_RELOC);
505 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
506 Make sure we do not do them again */
507 if (tpnt->libtype == program_interpreter)
509 rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries);
510 plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
512 /* Set up the lazy PLT entries. */
513 offset = PLT_INITIAL_ENTRY_WORDS;
515 /* Warning: we don't handle double-sized PLT entries */
516 while (i < num_plt_entries) {
517 plt[offset ] = OPCODE_LI(11, i * 4);
518 plt[offset+1] = OPCODE_B((PLT_TRAMPOLINE_ENTRY_WORDS + 2 - (offset+1)) * 4);
522 /* Now, we've modified code. We need to write the changes from
523 the data cache to a second-level unified cache, then make
524 sure that stale data in the instruction cache is removed.
525 (In a multiprocessor system, the effect is more complex.)
526 Most of the PLT shouldn't be in the instruction cache, but
527 there may be a little overlap at the start and the end.
529 Assumes that dcbst and icbi apply to lines of 16 bytes or
530 more. Current known line sizes are 16, 32, and 128 bytes. */
531 for (i = 0; i < rel_offset_words; i += 4)
533 PPC_DCBST (plt + rel_offset_words - 1);
536 PPC_ICBI (plt + rel_offset_words - 1);
540 int _dl_parse_relocation_information(struct elf_resolve *tpnt,
541 unsigned long rel_addr, unsigned long rel_size, int type)
544 return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
547 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
548 unsigned long rel_size, int type)
551 return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);