OSDN Git Service

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