OSDN Git Service

Seperate out the symbol resolution debugging, so it doesn't clutter
[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                 int num_plt_entries;
182                 unsigned long plt_addr;
183                 unsigned long lbranch_addr;
184                 unsigned long *ptr;
185                 int index;
186
187                 plt_addr = (unsigned long)tpnt->dynamic_info[DT_PLTGOT] + 
188                         (unsigned long)tpnt->loadaddr;
189                 lbranch_addr = plt_addr + PLT_LONGBRANCH_ENTRY_WORDS*4;
190                 delta = lbranch_addr - insn_addr;
191                 index = (insn_addr - plt_addr - PLT_INITIAL_ENTRY_WORDS*4)/8;
192
193                 ptr = (unsigned long *)tpnt->data_words;
194                 DPRINTF("plt_addr=%x delta=%x index=%x ptr=%x\n",
195                         plt_addr, delta, index, ptr);
196                 ptr[index] = targ_addr;
197                 /* icache sync is not necessary, since this will be a data load */
198                 //PPC_DCBST(ptr+index);
199                 //PPC_SYNC;
200                 //PPC_ICBI(ptr+index);
201                 //PPC_ISYNC;
202                 insns[1] = OPCODE_B(delta - 4);
203         }
204
205         /* instructions were modified */
206         PPC_DCBST(insn_addr);
207         PPC_SYNC;
208         PPC_ICBI(insn_addr);
209         PPC_ISYNC;
210
211         return targ_addr;
212 }
213
214 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
215         unsigned long rel_addr, unsigned long rel_size, int type)
216 {
217         int i;
218         char *strtab;
219         int reloc_type;
220         int symtab_index;
221         Elf32_Sym *symtab;
222         ELF_RELOC *rpnt;
223         unsigned long reloc_addr;
224         unsigned long *insns;
225         unsigned long *plt;
226         int index;
227
228         DPRINTF("_dl_parse_lazy_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
229                 tpnt,rel_addr,rel_size,type);
230
231         /* Now parse the relocation information */
232         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
233         rel_size = rel_size / sizeof(ELF_RELOC);
234
235         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
236         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
237         plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
238
239         for (i = 0; i < rel_size; i++, rpnt++) {
240                 reloc_addr = (unsigned long)tpnt->loadaddr +
241                         (unsigned long) rpnt->r_offset;
242                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
243                 symtab_index = ELF32_R_SYM(rpnt->r_info);
244
245                 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
246                    Make sure we do not do them again */
247                 if (!symtab_index && tpnt->libtype == program_interpreter)
248                         continue;
249                 if (symtab_index && tpnt->libtype == program_interpreter &&
250                         _dl_symbol(strtab + symtab[symtab_index].st_name))
251                         continue;
252
253                 DPRINTF("L %x %s %s %x %x\n",
254                         reloc_addr, _dl_reltypes[reloc_type],
255                         symtab_index?strtab + symtab[symtab_index].st_name:"",0,0);
256
257                 switch (reloc_type) {
258                 case R_PPC_NONE:
259                         break;
260                 case R_PPC_JMP_SLOT:
261                         {
262                         int delta;
263                         
264                         delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
265                                 - (reloc_addr+4);
266
267                         index = (reloc_addr -
268                                 (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
269                                 /sizeof(unsigned long);
270                         index /= 2;
271                         DPRINTF("        index %x delta %x\n",index,delta);
272                         insns = (unsigned long *)reloc_addr;
273                         insns[0] = OPCODE_LI(11,index*4);
274                         insns[1] = OPCODE_B(delta);
275                         break;
276                         }
277                 default:
278                         _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ", 
279                                 _dl_progname);
280 #ifdef VERBOSE_DLINKER
281                         _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
282 #endif
283                         if (symtab_index)
284                                 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
285                         _dl_exit(1);
286                 };
287
288                 /* instructions were modified */
289                 PPC_DCBST(reloc_addr);
290                 PPC_SYNC;
291                 PPC_ICBI(reloc_addr);
292         };
293 }
294
295 int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
296         unsigned long rel_addr, unsigned long rel_size, int type)
297 {
298         int i;
299         char *strtab;
300         int reloc_type;
301         int goof = 0;
302         Elf32_Sym *symtab;
303         ELF_RELOC *rpnt;
304         unsigned long *reloc_addr;
305         unsigned long symbol_addr;
306         int symtab_index;
307         unsigned long addend;
308         unsigned long *plt;
309
310         DPRINTF("_dl_parse_relocation_information(tpnt=%x, rel_addr=%x, rel_size=%x, type=%d)\n",
311                 tpnt,rel_addr,rel_size,type);
312
313         /* Now parse the relocation information */
314
315         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
316         rel_size = rel_size / sizeof(ELF_RELOC);
317
318         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
319         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
320         plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
321
322         for (i = 0; i < rel_size; i++, rpnt++) {
323                 debug_reloc(rpnt);
324
325                 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
326                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
327                 symtab_index = ELF32_R_SYM(rpnt->r_info);
328                 addend = rpnt->r_addend;
329                 symbol_addr = 0;
330
331                 if (!symtab_index && tpnt->libtype == program_interpreter)
332                         continue;
333
334                 if (symtab_index) {
335
336                         if (tpnt->libtype == program_interpreter &&
337                                 _dl_symbol(strtab + symtab[symtab_index].st_name))
338                                 continue;
339
340                         symbol_addr = (unsigned long) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
341                                         tpnt->symbol_scope, (unsigned long) reloc_addr, 
342                                         (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), 0);
343
344                         /*
345                          * We want to allow undefined references to weak symbols - this might
346                          * have been intentional.  We should not be linking local symbols
347                          * here, so all bases should be covered.
348                          */
349                         if (!symbol_addr &&
350                                 ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
351                                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
352                                         _dl_progname, strtab + symtab[symtab_index].st_name);
353                                 goof++;
354                         }
355                 }
356                 debug_sym(symtab,strtab,symtab_index);
357
358                 switch (reloc_type) {
359                 case R_PPC_NONE:
360                         break;
361                 case R_PPC_REL24:
362                         {
363                         int delta = symbol_addr - (unsigned long)reloc_addr;
364                         if(delta<<6>>6 != delta){
365                                 _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
366                                 _dl_exit(1);
367                         }
368                         *reloc_addr &= 0xfc000003;
369                         *reloc_addr |= delta&0x03fffffc;
370                         }
371                         break;
372                 case R_PPC_RELATIVE:
373                         *reloc_addr = (unsigned long)tpnt->loadaddr + addend;
374                         break;
375                 case R_PPC_ADDR32:
376                         *reloc_addr += symbol_addr;
377                         break;
378                 case R_PPC_ADDR16_HA:
379                         /* XXX is this correct? */
380                         *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
381                         break;
382                 case R_PPC_ADDR16_HI:
383                         *(short *)reloc_addr += symbol_addr>>16;
384                         break;
385                 case R_PPC_ADDR16_LO:
386                         *(short *)reloc_addr += symbol_addr;
387                         break;
388                 case R_PPC_JMP_SLOT:
389                         {
390                         unsigned long targ_addr = (unsigned long)_dl_linux_resolve;
391                         int delta = targ_addr - (unsigned long)reloc_addr;
392                         if(delta<<6>>6 == delta){
393                                 *reloc_addr = OPCODE_B(delta);
394                         }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
395                                 *reloc_addr = OPCODE_BA (targ_addr);
396                         }else{
397         {
398         int delta;
399         int index;
400         
401         delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
402                 - (unsigned long)(reloc_addr+1);
403
404         index = ((unsigned long)reloc_addr -
405                 (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
406                 /sizeof(unsigned long);
407         index /= 2;
408         DPRINTF("        index %x delta %x\n",index,delta);
409         reloc_addr[0] = OPCODE_LI(11,index*4);
410         reloc_addr[1] = OPCODE_B(delta);
411         }
412                         }
413                         break;
414                         }
415                 case R_PPC_GLOB_DAT:
416                         *reloc_addr += symbol_addr;
417                         break;
418                 case R_PPC_COPY:
419                         // handled later
420                         break;
421                 default:
422                         _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
423 #ifdef VERBOSE_DLINKER
424                         _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
425 #endif
426                         if (symtab_index)
427                                 _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
428                         _dl_exit(1);
429                 };
430
431                 /* instructions were modified */
432                 PPC_DCBST(reloc_addr);
433                 PPC_SYNC;
434                 PPC_ICBI(reloc_addr);
435
436                 DPRINTF("reloc_addr %x: %x\n",reloc_addr,*reloc_addr);
437         };
438         return goof;
439 }
440
441
442 /* This is done as a separate step, because there are cases where
443    information is first copied and later initialized.  This results in
444    the wrong information being copied.  Someone at Sun was complaining about
445    a bug in the handling of _COPY by SVr4, and this may in fact be what he
446    was talking about.  Sigh. */
447
448 /* No, there are cases where the SVr4 linker fails to emit COPY relocs
449    at all */
450
451 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
452         unsigned long rel_size, int type)
453 {
454         int i;
455         char *strtab;
456         int reloc_type;
457         int goof = 0;
458         Elf32_Sym *symtab;
459         ELF_RELOC *rpnt;
460         unsigned long *reloc_addr;
461         unsigned long symbol_addr;
462         struct elf_resolve *tpnt;
463         int symtab_index;
464
465         DPRINTF("parse_copy xpnt=%x rel_addr=%x rel_size=%x type=%d\n",
466                 (int)xpnt,rel_addr,rel_size,type);
467
468         /* Now parse the relocation information */
469
470         tpnt = xpnt->dyn;
471
472         rpnt = (ELF_RELOC *) (rel_addr + tpnt->loadaddr);
473         rel_size = rel_size / sizeof(ELF_RELOC);
474
475         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
476         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
477
478         for (i = 0; i < rel_size; i++, rpnt++) {
479                 reloc_addr = (unsigned long *) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
480                 reloc_type = ELF32_R_TYPE(rpnt->r_info);
481                 if (reloc_type != R_PPC_COPY)
482                         continue;
483
484                 debug_reloc(rpnt);
485
486                 symtab_index = ELF32_R_SYM(rpnt->r_info);
487                 symbol_addr = 0;
488                 if (!symtab_index && tpnt->libtype == program_interpreter)
489                         continue;
490                 if (symtab_index) {
491
492                         if (tpnt->libtype == program_interpreter &&
493                                 _dl_symbol(strtab + symtab[symtab_index].st_name))
494                                 continue;
495
496                         symbol_addr = (unsigned long) _dl_find_hash(strtab + 
497                                 symtab[symtab_index].st_name, xpnt->next, 
498                                 (unsigned long) reloc_addr, NULL, 1);
499                         if (!symbol_addr) {
500                                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", 
501                                         _dl_progname, strtab + symtab[symtab_index].st_name);
502                                 goof++;
503                         };
504                 };
505
506                 debug_sym(symtab,strtab,symtab_index);
507
508                 DPRINTF("copy: to=%x from=%x size=%x\n",
509                         symtab[symtab_index].st_value, 
510                         symbol_addr, symtab[symtab_index].st_size);
511
512                 if (!goof) {
513                         _dl_memcpy((char *) symtab[symtab_index].st_value, 
514                                 (char *) symbol_addr,
515                                 symtab[symtab_index].st_size);
516                 }
517         };
518         return goof;
519 }
520
521
522 #ifdef unused
523 static void fixup_jmpslot(unsigned long reloc_addr, unsigned long targ_addr)
524 {
525         int delta = targ_addr - reloc_addr;
526         int index;
527         
528         if(delta<<6>>6 == delta){
529                 *reloc_addr = OPCODE_B(delta);
530         }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
531                 *reloc_addr = OPCODE_BA (targ_addr);
532         }else{
533                 delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2)
534                         - (unsigned long)(reloc_addr+1);
535
536                 index = ((unsigned long)reloc_addr -
537                         (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
538                         /sizeof(unsigned long);
539                 index /= 2;
540
541                 DPRINTF("        index %x delta %x\n",index,delta);
542
543                 reloc_addr[0] = OPCODE_LI(11,index*4);
544                 reloc_addr[1] = OPCODE_B(delta);
545         }
546 }
547 #endif
548
549
550 #ifdef DL_DEBUG_SYMBOLS
551 static void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
552 {
553         if(symtab_index){
554                 _dl_dprintf(2, "sym: name=%s value=%x size=%x info=%x other=%x shndx=%x\n",
555                         strtab + symtab[symtab_index].st_name,
556                         symtab[symtab_index].st_value,
557                         symtab[symtab_index].st_size,
558                         symtab[symtab_index].st_info,
559                         symtab[symtab_index].st_other,
560                         symtab[symtab_index].st_shndx);
561         }else{
562                 _dl_dprintf(2, "sym: null\n");
563         }
564 }
565
566 static void debug_reloc(ELF_RELOC *rpnt)
567 {
568         _dl_dprintf(2, "reloc: offset=%x type=%x sym=%x addend=%x\n",
569                 rpnt->r_offset,
570                 ELF32_R_TYPE(rpnt->r_info),
571                 ELF32_R_SYM(rpnt->r_info),
572                 rpnt->r_addend);
573 }
574
575 #endif
576
577