OSDN Git Service

Joakim Tjernlund writes:
[uclinux-h8/uClibc.git] / ldso / ldso / powerpc / elfinterp.c
1 /* vi: set sw=4 ts=4: */
2 /* powerpc shared library loader suppport
3  *
4  * Copyright (C) 2001-2002,  David A. Schleef
5  * Copyright (C) 2003, Erik Andersen
6  *
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. The name of the above contributors may not be
15  *    used to endorse or promote products derived from this software
16  *    without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30
31 #if defined (__SUPPORT_LD_DEBUG__)
32 static const char *_dl_reltypes_tab[] =
33         { "R_PPC_NONE", "R_PPC_ADDR32", "R_PPC_ADDR24", "R_PPC_ADDR16",
34         "R_PPC_ADDR16_LO", "R_PPC_ADDR16_HI", "R_PPC_ADDR16_HA",
35         "R_PPC_ADDR14", "R_PPC_ADDR14_BRTAKEN", "R_PPC_ADDR14_BRNTAKEN",
36         "R_PPC_REL24", "R_PPC_REL14", "R_PPC_REL14_BRTAKEN",
37         "R_PPC_REL14_BRNTAKEN", "R_PPC_GOT16", "R_PPC_GOT16_LO",
38         "R_PPC_GOT16_HI", "R_PPC_GOT16_HA", "R_PPC_PLTREL24",
39         "R_PPC_COPY", "R_PPC_GLOB_DAT", "R_PPC_JMP_SLOT", "R_PPC_RELATIVE",
40         "R_PPC_LOCAL24PC", "R_PPC_UADDR32", "R_PPC_UADDR16", "R_PPC_REL32",
41         "R_PPC_PLT32", "R_PPC_PLTREL32", "R_PPC_PLT16_LO", "R_PPC_PLT16_HI",
42         "R_PPC_PLT16_HA", "R_PPC_SDAREL16", "R_PPC_SECTOFF",
43         "R_PPC_SECTOFF_LO", "R_PPC_SECTOFF_HI", "R_PPC_SECTOFF_HA",
44 };
45
46 static const char *
47 _dl_reltypes(int type)
48 {
49   static char buf[22];  
50   const char *str;
51   
52   if (type >= (int)(sizeof (_dl_reltypes_tab)/sizeof(_dl_reltypes_tab[0])) ||
53       NULL == (str = _dl_reltypes_tab[type]))
54   {
55     str =_dl_simple_ltoa( buf, (unsigned long)(type));
56   }
57   return str;
58 }
59
60 static 
61 void debug_sym(Elf32_Sym *symtab,char *strtab,int symtab_index)
62 {
63   if(_dl_debug_symbols)
64   {
65     if(symtab_index){
66       _dl_dprintf(_dl_debug_file, "\n%s\n\tvalue=%x\tsize=%x\tinfo=%x\tother=%x\tshndx=%x",
67                   strtab + symtab[symtab_index].st_name,
68                   symtab[symtab_index].st_value,
69                   symtab[symtab_index].st_size,
70                   symtab[symtab_index].st_info,
71                   symtab[symtab_index].st_other,
72                   symtab[symtab_index].st_shndx);
73     }
74   }
75 }
76
77 static 
78 void debug_reloc(Elf32_Sym *symtab,char *strtab, ELF_RELOC *rpnt)
79 {
80   if(_dl_debug_reloc)
81   {
82     int symtab_index;
83     const char *sym;
84     symtab_index = ELF32_R_SYM(rpnt->r_info);
85     sym = symtab_index ? strtab + symtab[symtab_index].st_name : "sym=0x0";
86     
87   if(_dl_debug_symbols)
88           _dl_dprintf(_dl_debug_file, "\n\t");
89   else
90           _dl_dprintf(_dl_debug_file, "\n%s\n\t", sym);
91 #ifdef ELF_USES_RELOCA
92     _dl_dprintf(_dl_debug_file, "%s\toffset=%x\taddend=%x",
93                 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
94                 rpnt->r_offset,
95                 rpnt->r_addend);
96 #else
97     _dl_dprintf(_dl_debug_file, "%s\toffset=%x\n",
98                 _dl_reltypes(ELF32_R_TYPE(rpnt->r_info)),
99                 rpnt->r_offset);
100 #endif
101   }
102 }
103 #endif
104
105 extern int _dl_linux_resolve(void);
106
107 void _dl_init_got(unsigned long *plt,struct elf_resolve *tpnt)
108 {
109         Elf32_Word *tramp;
110         Elf32_Word num_plt_entries;
111         Elf32_Word data_words;
112         Elf32_Word rel_offset_words;
113         Elf32_Word dlrr = (Elf32_Word) _dl_linux_resolve;
114
115         //DPRINTF("init_got plt=%x, tpnt=%x\n", (unsigned long)plt,(unsigned long)tpnt);
116
117         num_plt_entries = tpnt->dynamic_info[DT_PLTRELSZ] / sizeof(ELF_RELOC);
118         //DPRINTF("n_plt_entries %d\n",n_plt_entries);
119
120         rel_offset_words = PLT_DATA_START_WORDS(num_plt_entries);
121         //DPRINTF("rel_offset_words %x\n",rel_offset_words);
122         data_words = (Elf32_Word) (plt + rel_offset_words);
123         //DPRINTF("data_words %x\n",data_words);
124
125         tpnt->data_words = data_words;
126
127         plt[PLT_LONGBRANCH_ENTRY_WORDS] = OPCODE_ADDIS_HI(11, 11, data_words);
128         plt[PLT_LONGBRANCH_ENTRY_WORDS+1] = OPCODE_LWZ(11,data_words,11);
129
130         plt[PLT_LONGBRANCH_ENTRY_WORDS+2] = OPCODE_MTCTR(11);
131         plt[PLT_LONGBRANCH_ENTRY_WORDS+3] = OPCODE_BCTR();
132
133         /* [4] */
134         /* [5] */
135         tramp = (Elf32_Word *) (plt + PLT_TRAMPOLINE_ENTRY_WORDS);
136
137         /* For the long entries, subtract off data_words.  */
138         tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
139         tramp[1] = OPCODE_ADDI(11,11,-data_words);
140
141         /* Multiply index of entry by 3 (in r11).  */
142         tramp[2] = OPCODE_SLWI(12,11,1);
143         tramp[3] = OPCODE_ADD(11,12,11);
144         if (dlrr <= 0x01fffffc || dlrr >= 0xfe000000) {
145                 /* Load address of link map in r12.  */
146                 tramp[4] = OPCODE_LI (12, (Elf32_Word) tpnt);
147                 tramp[5] = OPCODE_ADDIS_HI (12, 12, (Elf32_Word) tpnt);
148
149                 /* Call _dl_runtime_resolve.  */
150                 tramp[6] = OPCODE_BA (dlrr);
151         } else {
152                 /* Get address of _dl_runtime_resolve in CTR.  */
153                 tramp[4] = OPCODE_LI(12,dlrr);
154                 tramp[5] = OPCODE_ADDIS_HI(12,12,dlrr);
155                 tramp[6] = OPCODE_MTCTR(12);
156
157                 /* Load address of link map in r12.  */
158                 tramp[7] = OPCODE_LI(12,(Elf32_Word) tpnt);
159                 tramp[8] = OPCODE_ADDIS_HI(12,12,(Elf32_Word) tpnt);
160
161                 /* Call _dl_runtime_resolve.  */
162                 tramp[9] = OPCODE_BCTR();
163         }
164         /* [16] unused */
165         /* [17] unused */
166
167         PPC_DCBST(plt);
168         PPC_DCBST(plt+4);
169         PPC_DCBST(plt+8);
170         PPC_DCBST(plt+12);
171         PPC_DCBST(plt+16-1);
172         PPC_SYNC;
173         PPC_ICBI(plt);
174         PPC_ICBI(plt+16-1);
175         PPC_ISYNC;
176 }
177
178 unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
179 {
180         ELF_RELOC *this_reloc;
181         char *strtab;
182         Elf32_Sym *symtab;
183         ELF_RELOC *rel_addr;
184         int symtab_index;
185         char *symname;
186         Elf32_Addr *reloc_addr;
187         Elf32_Addr  finaladdr;
188         Elf32_Sword delta;
189
190         rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
191
192         this_reloc = (void *)rel_addr + reloc_entry;
193         symtab_index = ELF32_R_SYM(this_reloc->r_info);
194
195         symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
196         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
197         symname      = strtab + symtab[symtab_index].st_name;
198
199 #if defined (__SUPPORT_LD_DEBUG__)
200         debug_sym(symtab,strtab,symtab_index);
201         debug_reloc(symtab,strtab,this_reloc);
202
203         if (ELF32_R_TYPE(this_reloc->r_info) != R_PPC_JMP_SLOT) {
204                 _dl_dprintf(2, "%s: Incorrect relocation type in jump relocation\n", _dl_progname);
205                 _dl_exit(1);
206         };
207 #endif
208
209         /* Address of dump instruction to fix up */
210         reloc_addr = (Elf32_Addr *) (tpnt->loadaddr + this_reloc->r_offset);
211
212 #if defined (__SUPPORT_LD_DEBUG__)
213         if(_dl_debug_reloc && _dl_debug_detail)
214                 _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, (Elf32_Addr)reloc_addr);
215 #endif
216
217         /* Get the address of the GOT entry */
218         finaladdr = (Elf32_Addr) _dl_find_hash(strtab + symtab[symtab_index].st_name, 
219                                                 tpnt->symbol_scope, tpnt, resolver);
220         if (!finaladdr) {
221                 _dl_dprintf(2, "%s: can't resolve symbol '%s'\n", _dl_progname, symname);
222                 _dl_exit(1);
223         };
224
225 #if defined (__SUPPORT_LD_DEBUG__)
226         if(_dl_debug_reloc && _dl_debug_detail)
227                 _dl_dprintf(_dl_debug_file, "%x\n", finaladdr);
228 #endif
229         delta = finaladdr - (Elf32_Word)reloc_addr;
230         if (delta<<6>>6 == delta) {
231                 *reloc_addr = OPCODE_B(delta);
232         } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
233                 *reloc_addr = OPCODE_BA (finaladdr);
234         } else {
235                 /* Warning: we don't handle double-sized PLT entries */
236                 Elf32_Word *plt, *data_words, index, offset;
237
238                 plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
239                 offset = reloc_addr - plt;
240                 index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
241                 data_words = (Elf32_Word *)tpnt->data_words;
242                 reloc_addr += 1;
243
244                 data_words[index] = finaladdr;
245                 PPC_SYNC;
246                 *reloc_addr =  OPCODE_B ((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
247         }
248
249         /* instructions were modified */
250         PPC_DCBST(reloc_addr);
251         PPC_SYNC;
252         PPC_ICBI(reloc_addr);
253         PPC_ISYNC;
254
255         return finaladdr;
256 }
257
258 static int
259 _dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
260           unsigned long rel_addr, unsigned long rel_size,
261           int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
262                             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
263 {
264         unsigned int i;
265         char *strtab;
266         Elf32_Sym *symtab;
267         ELF_RELOC *rpnt;
268         int symtab_index;
269
270         /* Now parse the relocation information */
271         rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
272         rel_size = rel_size / sizeof(ELF_RELOC);
273
274         symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
275         strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
276
277           for (i = 0; i < rel_size; i++, rpnt++) {
278                 int res;
279             
280                 symtab_index = ELF32_R_SYM(rpnt->r_info);
281                 
282                 /* When the dynamic linker bootstrapped itself, it resolved some symbols.
283                    Make sure we do not do them again */
284                 if (!symtab_index && tpnt->libtype == program_interpreter)
285                         continue;
286                 if (symtab_index && tpnt->libtype == program_interpreter &&
287                     _dl_symbol(strtab + symtab[symtab_index].st_name))
288                         continue;
289
290 #if defined (__SUPPORT_LD_DEBUG__)
291                 debug_sym(symtab,strtab,symtab_index);
292                 debug_reloc(symtab,strtab,rpnt);
293 #endif
294
295                 res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
296
297                 if (res==0) continue;
298
299                 _dl_dprintf(2, "\n%s: ",_dl_progname);
300                 
301                 if (symtab_index)
302                   _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
303                   
304                 if (res <0)
305                 {
306                         int reloc_type = ELF32_R_TYPE(rpnt->r_info);
307 #if defined (__SUPPORT_LD_DEBUG__)
308                         _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
309 #else
310                         _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
311 #endif                  
312                         _dl_exit(-res);
313                 }
314                 else if (res >0)
315                 {
316                         _dl_dprintf(2, "can't resolve symbol\n");
317                         return res;
318                 }
319           }
320           return 0;
321 }
322
323 static int
324 _dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
325                    ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
326 {
327         Elf32_Addr *reloc_addr;
328         Elf32_Word *plt, index, offset;
329
330         (void)scope;
331         (void)symtab;
332         (void)strtab;
333
334         reloc_addr = (Elf32_Addr *)(tpnt->loadaddr + rpnt->r_offset);
335 #if defined (__SUPPORT_LD_DEBUG__)
336         if (ELF32_R_TYPE(rpnt->r_info) != R_PPC_JMP_SLOT) {
337                 _dl_dprintf(2, "Reloc type != R_PPC_JMP_SLOT. Type is 0x%x\n", ELF32_R_TYPE(rpnt->r_info));
338                 return -1;
339         }
340 #endif
341         plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
342         offset = reloc_addr - plt;
343         index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
344         reloc_addr[0] = OPCODE_LI(11,index*4);
345         reloc_addr[1] = OPCODE_B((PLT_TRAMPOLINE_ENTRY_WORDS + 2 - (offset+1)) * 4);
346
347         /* instructions were modified */
348         PPC_DCBST(reloc_addr);
349         PPC_DCBST(reloc_addr+1);
350         PPC_SYNC;
351         PPC_ICBI(reloc_addr);
352         PPC_ICBI(reloc_addr+1);
353         PPC_ISYNC;
354
355 #if defined (__SUPPORT_LD_DEBUG__)
356         if(_dl_debug_reloc && _dl_debug_detail)
357                 _dl_dprintf(_dl_debug_file, "\tpatched: %x", reloc_addr);
358 #endif
359         return 0;
360 }
361
362 static int
363 _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
364               ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
365 {
366         int reloc_type;
367         int symtab_index;
368         char *symname;
369         Elf32_Addr *reloc_addr;
370         Elf32_Addr finaladdr;
371
372         unsigned long symbol_addr;
373 #if defined (__SUPPORT_LD_DEBUG__)
374         unsigned long old_val;
375 #endif
376         reloc_addr   = (Elf32_Addr *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
377         reloc_type   = ELF32_R_TYPE(rpnt->r_info);
378         if (reloc_type == R_PPC_RELATIVE) {
379                 *reloc_addr = tpnt->loadaddr + rpnt->r_addend;
380                 return 0;
381         }
382         if (reloc_type == R_PPC_NONE || reloc_type == R_PPC_COPY) /*  R_PPC_COPY is handled later */
383                 return 0;
384         symtab_index = ELF32_R_SYM(rpnt->r_info);
385         symname      = strtab + symtab[symtab_index].st_name;
386
387         symbol_addr = (unsigned long) _dl_find_hash(symname, scope, 
388                                                     (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
389         /*
390          * We want to allow undefined references to weak symbols - this might
391          * have been intentional.  We should not be linking local symbols
392          * here, so all bases should be covered.
393          */
394         if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
395 #if defined (__SUPPORT_LD_DEBUG__)
396                 _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s', rel type: %s\n",
397                             symname, tpnt->libname, _dl_reltypes(reloc_type));
398 #endif
399                 return 0;
400         }
401 #if defined (__SUPPORT_LD_DEBUG__)
402         old_val = *reloc_addr;
403 #endif
404         finaladdr = (Elf32_Addr) (symbol_addr + rpnt->r_addend);
405
406         switch (reloc_type) {
407         case R_PPC_ADDR32:
408         case R_PPC_GLOB_DAT:
409                 *reloc_addr = finaladdr;
410                 return 0; /* No code code modified */
411                 break;
412         case R_PPC_JMP_SLOT:
413         {
414                 Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
415                 
416                 if (delta<<6>>6 == delta) {
417                         *reloc_addr = OPCODE_B(delta);
418                 } else if (finaladdr <= 0x01fffffc || finaladdr >= 0xfe000000) {
419                         *reloc_addr = OPCODE_BA (finaladdr);
420                 } else {
421                         /* Warning: we don't handle double-sized PLT entries */
422                         Elf32_Word *plt, *data_words, index, offset;
423
424                         plt = (Elf32_Word *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
425                         offset = reloc_addr - plt;
426                         index = (offset - PLT_INITIAL_ENTRY_WORDS)/2;
427                         data_words = (Elf32_Word *)tpnt->data_words;
428
429                         data_words[index] = finaladdr;
430                         reloc_addr[0] = OPCODE_LI(11,index*4);
431                         reloc_addr[1] = OPCODE_B((PLT_LONGBRANCH_ENTRY_WORDS - (offset+1)) * 4);
432
433                         /* instructions were modified */
434                         PPC_DCBST(reloc_addr+1);
435                         PPC_SYNC;
436                         PPC_ICBI(reloc_addr+1);
437                 }
438                 break;
439         }
440         case R_PPC_COPY:
441                 /* This does not work yet, R_PPC_COPY is handled later, see if statemet above */
442                 if (symbol_addr) {
443 #if defined (__SUPPORT_LD_DEBUG__)
444                         if(_dl_debug_move)
445                                 _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
446                                             symname, symtab[symtab_index].st_size,
447                                             symbol_addr, symtab[symtab_index].st_value);
448 #endif
449                         _dl_memcpy((char *) reloc_addr, (char *) finaladdr, symtab[symtab_index].st_size);
450                 }
451                 return 0; /* No code code modified */
452                 break;
453         case R_PPC_ADDR16_HA:
454                 *(short *)reloc_addr = (finaladdr + 0x8000)>>16;
455                 break;
456         case R_PPC_ADDR16_HI:
457                 *(short *)reloc_addr = finaladdr >> 16;
458                 break;
459         case R_PPC_ADDR16_LO:
460                 *(short *)reloc_addr = finaladdr;
461                 break;
462         case R_PPC_REL24:
463         {
464                 Elf32_Sword delta = finaladdr - (Elf32_Word)reloc_addr;
465                 if(delta<<6>>6 != delta){
466                         _dl_dprintf(2, "%s: symbol '%s' R_PPC_REL24 is out of range.\n\tCompile shared libraries with -fPIC!\n",
467                                     _dl_progname, symname);
468                         _dl_exit(1);
469                 }
470                 *reloc_addr = (*reloc_addr & 0xfc000003) | (delta & 0x3fffffc);
471                 break;
472         }
473         default:
474                 _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
475 #if defined (__SUPPORT_LD_DEBUG__)
476                 _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
477 #endif
478                 if (symtab_index)
479                         _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
480                 return -1;
481         };
482
483         /* instructions were modified */
484         PPC_DCBST(reloc_addr);
485         PPC_SYNC;
486         PPC_ICBI(reloc_addr);
487         PPC_ISYNC;
488 #if defined (__SUPPORT_LD_DEBUG__)
489         if(_dl_debug_reloc && _dl_debug_detail)
490                 _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
491 #endif
492         return 0;
493 }
494
495 /* This is done as a separate step, because there are cases where
496    information is first copied and later initialized.  This results in
497    the wrong information being copied.  Someone at Sun was complaining about
498    a bug in the handling of _COPY by SVr4, and this may in fact be what he
499    was talking about.  Sigh. */
500 static int
501 _dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
502              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
503 {
504         int reloc_type;
505         int symtab_index;
506         unsigned long *reloc_addr;
507         unsigned long symbol_addr;
508         int goof = 0;
509         char *symname;
510           
511         reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
512         reloc_type = ELF32_R_TYPE(rpnt->r_info);
513         if (reloc_type != R_PPC_COPY) 
514                 return 0;
515         symtab_index = ELF32_R_SYM(rpnt->r_info);
516         symbol_addr = 0;
517         symname      = strtab + symtab[symtab_index].st_name;
518                 
519         if (symtab_index) {
520                 symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
521                 if (!symbol_addr) goof++;
522         }
523         if (!goof) {
524 #if defined (__SUPPORT_LD_DEBUG__)
525                 if(_dl_debug_move)
526                   _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
527                              symname, symtab[symtab_index].st_size,
528                              symbol_addr, symtab[symtab_index].st_value);
529 #endif
530                         _dl_memcpy((char *) reloc_addr,
531                                         (char *) (symbol_addr + (unsigned long)rpnt->r_addend), symtab[symtab_index].st_size);
532         }
533
534         return goof;
535 }
536
537 void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt, 
538         unsigned long rel_addr, unsigned long rel_size, int type)
539 {
540         (void) type;
541         (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
542 }
543
544 int _dl_parse_relocation_information(struct elf_resolve *tpnt, 
545         unsigned long rel_addr, unsigned long rel_size, int type)
546 {
547         (void) type;
548         return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
549 }
550
551 int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr, 
552         unsigned long rel_size, int type)
553 {
554         (void) type;
555         return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
556 }