OSDN Git Service

Patch from Stefan Allius and Edie C. Dost to add SuperH
[uclinux-h8/uClibc.git] / ldso / ldso / powerpc / elfinterp.c
1 /* vi: set sw=4 ts=4: */
2 /* i386 ELF shared library loader suppport
3  *
4  * Copyright (C) 2001-2002,  David A. Schleef
5  *
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  */
29
30 #ifndef VERBOSE_DLINKER
31 #define VERBOSE_DLINKER
32 #endif
33 #ifdef VERBOSE_DLINKER
34 static const char *_dl_reltypes[] =
35         { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
36         "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
37         "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
38         "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
39         "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
40         "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
41         "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
42         "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
43         "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
44         "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
45         "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
46 };
47 #define N_RELTYPES (sizeof(_dl_reltypes)/sizeof(_dl_reltypes[0]))
48 #endif
49
50 /* Program to load an ELF binary on a linux system, and run it.
51    References to symbols in sharable libraries can be resolved by either
52    an ELF sharable library or a linux style of shared library. */
53
54 /* Disclaimer:  I have never seen any AT&T source code for SVr4, nor have
55    I ever taken any courses on internals.  This program was developed using
56    information available through the book "UNIX SYSTEM V RELEASE 4,
57    Programmers guide: Ansi C and Programming Support Tools", which did
58    a more than adequate job of explaining everything required to get this
59    working. */
60
61
62 #ifdef LD_DEBUG_SYMBOLS
63 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index);
64 static void debug_reloc(ELF_RELOC *rpnt);
65 #define DPRINTF(fmt,args...) _dl_dprintf(2,fmt,args)
66 #else
67 #define debug_sym(a,b,c)
68 #define debug_reloc(a)
69 #define DPRINTF(fmt,args...)
70 #endif
71
72 extern int _dl_linux_resolve(void);
73
74 void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
75 {
76         unsigned long target_addr = (unsigned long)_dl_linux_resolve;
77         unsigned int n_plt_entries;
78         unsigned long *tramp;
79         unsigned long data_words;
80         unsigned int rel_offset_words;
81
82         DPRINTF("init_got plt=%x, tpnt=%x\n",
83                 (unsigned long)plt,(unsigned long)tpnt);
84
85         n_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
86         DPRINTF("n_plt_entries %d\n",n_plt_entries);
87
88         rel_offset_words = PLT_DATA_START_WORDS(n_plt_entries);
89         DPRINTF("rel_offset_words %x\n",rel_offset_words);
90         data_words = (unsigned long)(plt + rel_offset_words);
91         DPRINTF("data_words %x\n",data_words);
92
93         tpnt->data_words = data_words;
94
95         plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
96         plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
97
98         plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
99         plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
100
101         /* [4] */
102         /* [5] */
103
104         tramp = plt + PLT_TRAMPOLINE_ENTRY_WORDS;
105         tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
106         tramp[1] = OPCODE_ADDI(11,11,-data_words);
107         tramp[2] = OPCODE_SLWI(12,11,1);
108         tramp[3] = OPCODE_ADD(11,12,11);
109         tramp[4] = OPCODE_LI(12,target_addr);
110         tramp[5] = OPCODE_ADDIS_HI(12,12,target_addr);
111         tramp[6] = OPCODE_MTCTR(12);
112         tramp[7] = OPCODE_LI(12,(unsigned long)tpnt);
113         tramp[8] = OPCODE_ADDIS_HI(12,12,(unsigned long)tpnt);
114         tramp[9] = OPCODE_BCTR();
115
116         /* [16] unused */
117         /* [17] unused */
118
119         /* instructions were modified */
120         PPC_DCBST(plt);
121         PPC_DCBST(plt+4);
122         PPC_DCBST(plt+8);
123         PPC_SYNC;
124         PPC_ICBI(plt);
125         PPC_ICBI(plt+4);
126         PPC_ICBI(plt+8);
127         PPC_ISYNC;
128 }
129
130 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
131 {
132         int reloc_type;
133         ELF_RELOC *this_reloc;
134         char *strtab;
135         Elf32_Sym *symtab;
136         ELF_RELOC *rel_addr;
137         int symtab_index;
138         unsigned long insn_addr;
139         unsigned long *insns;
140         unsigned long targ_addr;
141         int delta;
142
143         //DPRINTF("linux_resolver tpnt=%x reloc_entry=%x\n", tpnt, reloc_entry);
144
145         rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
146
147         this_reloc = (void *)rel_addr + reloc_entry;
148         reloc_type = ELF32_R_TYPE(this_reloc->r_info);
149         symtab_index = ELF32_R_SYM(this_reloc->r_info);
150
151         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
152         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
153
154         //debug_reloc(this_reloc);
155
156         if (reloc_type != R_PPC_JMP_SLOT) {
157                 _dl_dprintf(2, "%s: Incorrect relocation type [%s] in jump relocations\n",
158                         _dl_progname,
159                         (reloc_type<N_RELTYPES)?_dl_reltypes[reloc_type]:"unknown");
160                 _dl_exit(1);
161         };
162
163         /* Address of dump instruction to fix up */
164         insn_addr = (unsigned long) tpnt->loadaddr +
165                 (unsigned long) this_reloc->r_offset;
166
167         DPRINTF("Resolving symbol %s %x --> ", 
168                 strtab + symtab[symtab_index].st_name,
169                 insn_addr);
170
171         /* Get the address of the GOT entry */
172         targ_addr = (unsigned long) _dl_find_hash(
173                 strtab + symtab[symtab_index].st_name, 
174                 tpnt->symbol_scope, tpnt, resolver);
175         if (!targ_addr) {
176                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
177                         _dl_progname, strtab + symtab[symtab_index].st_name);
178                 _dl_exit(1);
179         };
180         DPRINTF("%x\n", targ_addr);
181
182         insns = (unsigned long *)insn_addr;
183         delta = targ_addr - insn_addr;
184
185         if(delta<<6>>6 == delta){
186                 insns[0] = OPCODE_B(delta);
187         }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
188                 insns[0] = OPCODE_BA (targ_addr);
189         }else{
190                 /* Warning: we don't handle double-sized PLT entries */
191                 unsigned long plt_addr;
192                 unsigned long lbranch_addr;
193                 unsigned long *ptr;
194                 int index;
195
196                 plt_addr = (unsigned long)tpnt->dynamic_info[DT_PLTGOT] + 
197                         (unsigned long)tpnt->loadaddr;
198                 lbranch_addr = plt_addr + PLT_LONGBRANCH_ENTRY_WORDS*4;
199                 delta = lbranch_addr - insn_addr;
200                 index = (insn_addr - plt_addr - PLT_INITIAL_ENTRY_WORDS*4)/8;
201
202                 ptr = (unsigned long *)tpnt->data_words;
203                 DPRINTF("plt_addr=%x delta=%x index=%x ptr=%x\n",
204                         plt_addr, delta, index, ptr);
205                 ptr[index] = targ_addr;
206                 /* icache sync is not necessary, since this will be a data load */
207                 //PPC_DCBST(ptr+index);
208                 //PPC_SYNC;
209                 //PPC_ICBI(ptr+index);
210                 //PPC_ISYNC;
211                 insns[1] = OPCODE_B(delta - 4);
212         }
213
214         /* instructions were modified */
215         PPC_DCBST(insn_addr);
216         PPC_SYNC;
217         PPC_ICBI(insn_addr);
218         PPC_ISYNC;
219
220         return targ_addr;
221 }
222
223 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
224         unsigned long rel_addr, unsigned long rel_size, int type)
225 {
226         int i;
227         char *strtab;
228         int reloc_type;
229         int symtab_index;
230         Elf32_Sym *symtab;
231         ELF_RELOC *rpnt;
232         unsigned long reloc_addr;
233         unsigned long *insns;
234         unsigned long *plt;
235         int index;
236
237         DPRINTF("_dl_parse_lazy_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
238                 tpnt,rel_addr,rel_size,type);
239
240         /* Now parse the relocation information */
241         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
242         rel_size = rel_size / sizeof(ELF_RELOC);
243
244         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
245         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
246         plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
247
248         for (i = 0; i < rel_size; i++, rpnt++) {
249                 reloc_addr = (unsigned long)tpnt->loadaddr +
250                         (unsigned long) rpnt->r_offset;
251                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
252                 symtab_index = ELF32_R_SYM(rpnt->r_info);
253
254                 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
255                    Make sure we do not do them again */
256                 if (!symtab_index && tpnt->libtype == program_interpreter)
257                         continue;
258                 if (symtab_index && tpnt->libtype == program_interpreter &&
259                         _dl_symbol(strtab + symtab[symtab_index].st_name))
260                         continue;
261
262                 DPRINTF("L %x %s %s %x %x\n",
263                         reloc_addr, _dl_reltypes[reloc_type],
264                         symtab_index?strtab + symtab[symtab_index].st_name:"",0,0);
265
266                 switch (reloc_type) {
267                 case R_PPC_NONE:
268                         break;
269                 case R_PPC_JMP_SLOT:
270                         {
271                         int delta;
272                         
273                         delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
274                                 - (reloc_addr+4);
275
276                         index = (reloc_addr -
277                                 (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
278                                 /sizeof(unsigned long);
279                         index /= 2;
280                         DPRINTF("        index %x delta %x\n",index,delta);
281                         insns = (unsigned long *)reloc_addr;
282                         insns[0] = OPCODE_LI(11,index*4);
283                         insns[1] = OPCODE_B(delta);
284                         break;
285                         }
286                 default:
287                         _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", 
288                                 _dl_progname);
289 #ifdef VERBOSE_DLINKER
290                         _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
291 #endif
292                         if (symtab_index)
293                                 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
294                         _dl_exit(1);
295                 };
296
297                 /* instructions were modified */
298                 PPC_DCBST(reloc_addr);
299                 PPC_SYNC;
300                 PPC_ICBI(reloc_addr);
301         };
302 }
303
304 int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
305         unsigned long rel_addr, unsigned long rel_size, int type)
306 {
307         int i;
308         char *strtab;
309         int reloc_type;
310         int goof = 0;
311         Elf32_Sym *symtab;
312         ELF_RELOC *rpnt;
313         unsigned long *reloc_addr;
314         unsigned long symbol_addr;
315         int symtab_index;
316         unsigned long addend;
317         unsigned long *plt;
318
319         DPRINTF("_dl_parse_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
320                 tpnt,rel_addr,rel_size,type);
321
322         /* Now parse the relocation information */
323
324         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
325         rel_size = rel_size / sizeof(ELF_RELOC);
326
327         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
328         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
329         plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
330
331         for (i = 0; i < rel_size; i++, rpnt++) {
332                 debug_reloc(rpnt);
333
334                 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
335                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
336                 symtab_index = ELF32_R_SYM(rpnt->r_info);
337                 addend = rpnt->r_addend;
338                 symbol_addr = 0;
339
340                 if (!symtab_index && tpnt->libtype == program_interpreter)
341                         continue;
342
343                 if (symtab_index) {
344
345                         if (tpnt->libtype == program_interpreter &&
346                                 _dl_symbol(strtab + symtab[symtab_index].st_name))
347                                 continue;
348
349                         symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
350                                         tpnt->symbol_scope,
351                                         (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
352
353                         /*
354                          * We want to allow undefined references to weak symbols - this might
355                          * have been intentional.  We should not be linking local symbols
356                          * here, so all bases should be covered.
357                          */
358                         if (!symbol_addr &&
359                                 ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
360                                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
361                                         _dl_progname, strtab + symtab[symtab_index].st_name);
362                                 goof++;
363                         }
364                 }
365                 debug_sym(symtab,strtab,symtab_index);
366
367                 switch (reloc_type) {
368                 case R_PPC_NONE:
369                         break;
370                 case R_PPC_REL24:
371 #if 0
372                         {
373                         int delta = symbol_addr - (unsigned long)reloc_addr;
374                         if(delta<<6>>6 != delta){
375                                 _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
376                                 _dl_exit(1);
377                         }
378                         *reloc_addr &= 0xfc000003;
379                         *reloc_addr |= delta&0x03fffffc;
380                         }
381                         break;
382 #else
383                         _dl_dprintf(2,"R_PPC_REL24: Compile shared libraries with -fPIC!\n");
384                         _dl_exit(1);
385 #endif
386                 case R_PPC_RELATIVE:
387                         *reloc_addr = (unsigned long)tpnt->loadaddr + addend;
388                         break;
389                 case R_PPC_ADDR32:
390                         *reloc_addr += symbol_addr;
391                         break;
392                 case R_PPC_ADDR16_HA:
393                         /* XXX is this correct? */
394                         *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
395                         break;
396                 case R_PPC_ADDR16_HI:
397                         *(short *)reloc_addr += symbol_addr>>16;
398                         break;
399                 case R_PPC_ADDR16_LO:
400                         *(short *)reloc_addr += symbol_addr;
401                         break;
402                 case R_PPC_JMP_SLOT:
403                         {
404                         unsigned long targ_addr = (unsigned long)_dl_linux_resolve;
405                         int delta = targ_addr - (unsigned long)reloc_addr;
406                         if(delta<<6>>6 == delta){
407                                 *reloc_addr = OPCODE_B(delta);
408                         }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
409                                 *reloc_addr = OPCODE_BA (targ_addr);
410                         }else{
411         {
412         int delta;
413         int index;
414         
415         delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
416                 - (unsigned long)(reloc_addr+1);
417
418         index = ((unsigned long)reloc_addr -
419                 (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
420                 /sizeof(unsigned long);
421         index /= 2;
422         DPRINTF("        index %x delta %x\n",index,delta);
423         reloc_addr[0] = OPCODE_LI(11,index*4);
424         reloc_addr[1] = OPCODE_B(delta);
425         }
426                         }
427                         break;
428                         }
429                 case R_PPC_GLOB_DAT:
430                         *reloc_addr += symbol_addr;
431                         break;
432                 case R_PPC_COPY:
433                         // handled later
434                         break;
435                 default:
436                         _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
437 #ifdef VERBOSE_DLINKER
438                         _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
439 #endif
440                         if (symtab_index)
441                                 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
442                         _dl_exit(1);
443                 };
444
445                 /* instructions were modified */
446                 PPC_DCBST(reloc_addr);
447                 PPC_SYNC;
448                 PPC_ICBI(reloc_addr);
449
450                 DPRINTF("reloc_addr %x: %x\n",reloc_addr,*reloc_addr);
451         };
452         return goof;
453 }
454
455
456 /* This is done as a separate step, because there are cases where
457    information is first copied and later initialized.  This results in
458    the wrong information being copied.  Someone at Sun was complaining about
459    a bug in the handling of _COPY by SVr4, and this may in fact be what he
460    was talking about.  Sigh. */
461
462 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
463    at all */
464
465 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
466         unsigned long rel_size, int type)
467 {
468         int i;
469         char *strtab;
470         int reloc_type;
471         int goof = 0;
472         Elf32_Sym *symtab;
473         ELF_RELOC *rpnt;
474         unsigned long *reloc_addr;
475         unsigned long symbol_addr;
476         struct elf_resolve *tpnt;
477         int symtab_index;
478
479         DPRINTF("parse_copy xpnt=%x rel_addr=%x rel_size=%x type=%d\n",
480                 (int)xpnt,rel_addr,rel_size,type);
481
482         /* Now parse the relocation information */
483
484         tpnt = xpnt->dyn;
485
486         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
487         rel_size = rel_size / sizeof(ELF_RELOC);
488
489         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
490         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
491
492         for (i = 0; i < rel_size; i++, rpnt++) {
493                 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
494                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
495                 if (reloc_type != R_PPC_COPY)
496                         continue;
497
498                 debug_reloc(rpnt);
499
500                 symtab_index = ELF32_R_SYM(rpnt->r_info);
501                 symbol_addr = 0;
502                 if (!symtab_index && tpnt->libtype == program_interpreter)
503                         continue;
504                 if (symtab_index) {
505
506                         if (tpnt->libtype == program_interpreter &&
507                                 _dl_symbol(strtab + symtab[symtab_index].st_name))
508                                 continue;
509
510                         symbol_addr = (unsigned long) _dl_find_hash(strtab + 
511                                 symtab[symtab_index].st_name, xpnt->next, 
512                                 NULL, copyrel);
513                         if (!symbol_addr) {
514                                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
515                                         _dl_progname, strtab + symtab[symtab_index].st_name);
516                                 goof++;
517                         };
518                 };
519
520                 debug_sym(symtab,strtab,symtab_index);
521
522                 DPRINTF("copy: to=%x from=%x size=%x\n",
523                         symtab[symtab_index].st_value, 
524                         symbol_addr, symtab[symtab_index].st_size);
525
526                 if (!goof) {
527                         _dl_memcpy((char *) symtab[symtab_index].st_value, 
528                                 (char *) symbol_addr,
529                                 symtab[symtab_index].st_size);
530                 }
531         };
532         return goof;
533 }
534
535
536 #ifdef unused
537 static void fixup_jmpslot(unsigned long reloc_addr, unsigned long targ_addr)
538 {
539         int delta = targ_addr - reloc_addr;
540         int index;
541         
542         if(delta<<6>>6 == delta){
543                 *reloc_addr = OPCODE_B(delta);
544         }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
545                 *reloc_addr = OPCODE_BA (targ_addr);
546         }else{
547                 delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
548                         - (unsigned long)(reloc_addr+1);
549
550                 index = ((unsigned long)reloc_addr -
551                         (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
552                         /sizeof(unsigned long);
553                 index /= 2;
554
555                 DPRINTF("        index %x delta %x\n",index,delta);
556
557                 reloc_addr[0] = OPCODE_LI(11,index*4);
558                 reloc_addr[1] = OPCODE_B(delta);
559         }
560 }
561 #endif
562
563
564 #ifdef LD_DEBUG_SYMBOLS
565 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
566 {
567         if(symtab_index){
568                 _dl_dprintf(2, "sym: name=%s value=%x size=%x info=%x other=%x shndx=%x\n",
569                         strtab + symtab[symtab_index].st_name,
570                         symtab[symtab_index].st_value,
571                         symtab[symtab_index].st_size,
572                         symtab[symtab_index].st_info,
573                         symtab[symtab_index].st_other,
574                         symtab[symtab_index].st_shndx);
575         }else{
576                 _dl_dprintf(2, "sym: null\n");
577         }
578 }
579
580 static void debug_reloc(ELF_RELOC *rpnt)
581 {
582         _dl_dprintf(2, "reloc: offset=%x type=%x sym=%x addend=%x\n",
583                 rpnt->r_offset,
584                 ELF32_R_TYPE(rpnt->r_info),
585                 ELF32_R_SYM(rpnt->r_info),
586                 rpnt->r_addend);
587 }
588
589 #endif
590
591