OSDN Git Service

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