OSDN Git Service

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