OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [ldso/] [ldso/] [powerpc/] [elfinterp.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* 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
        unsigned long target_addr = (unsigned long)_dl_linux_resolve;
110
        unsigned int n_plt_entries;
111
        unsigned long *tramp;
112
        unsigned long data_words;
113
        unsigned int rel_offset_words;
114
 
115
        //DPRINTF("init_got plt=%x, tpnt=%x\n", (unsigned long)plt,(unsigned long)tpnt);
116
 
117
        n_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(n_plt_entries);
121
        //DPRINTF("rel_offset_words %x\n",rel_offset_words);
122
        data_words = (unsigned long)(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
 
136
        tramp = plt + PLT_TRAMPOLINE_ENTRY_WORDS;
137
        tramp[0] = OPCODE_ADDIS_HI(11,11,-data_words);
138
        tramp[1] = OPCODE_ADDI(11,11,-data_words);
139
        tramp[2] = OPCODE_SLWI(12,11,1);
140
        tramp[3] = OPCODE_ADD(11,12,11);
141
        tramp[4] = OPCODE_LI(12,target_addr);
142
        tramp[5] = OPCODE_ADDIS_HI(12,12,target_addr);
143
        tramp[6] = OPCODE_MTCTR(12);
144
        tramp[7] = OPCODE_LI(12,(unsigned long)tpnt);
145
        tramp[8] = OPCODE_ADDIS_HI(12,12,(unsigned long)tpnt);
146
        tramp[9] = OPCODE_BCTR();
147
 
148
        /* [16] unused */
149
        /* [17] unused */
150
 
151
        /* instructions were modified */
152
        PPC_DCBST(plt);
153
        PPC_DCBST(plt+4);
154
        PPC_DCBST(plt+8);
155
        PPC_DCBST(plt+12);
156
        PPC_DCBST(plt+16-1);
157
        PPC_SYNC;
158
        PPC_ICBI(plt);
159
        PPC_ICBI(plt+4); /* glibc thinks this is not needed */
160
        PPC_ICBI(plt+8); /* glibc thinks this is not needed */
161
        PPC_ICBI(plt+12); /* glibc thinks this is not needed */
162
        PPC_ICBI(plt+16-1);
163
        PPC_ISYNC;
164
}
165
 
166
unsigned long _dl_linux_resolver(struct elf_resolve *tpnt, int reloc_entry)
167
{
168
        int reloc_type;
169
        ELF_RELOC *this_reloc;
170
        char *strtab;
171
        Elf32_Sym *symtab;
172
        ELF_RELOC *rel_addr;
173
        int symtab_index;
174
        char *symname;
175
        unsigned long insn_addr;
176
        unsigned long *insns;
177
        unsigned long new_addr;
178
        unsigned long delta;
179
 
180
        rel_addr = (ELF_RELOC *) (tpnt->dynamic_info[DT_JMPREL] + tpnt->loadaddr);
181
 
182
        this_reloc = (void *)rel_addr + reloc_entry;
183
        reloc_type = ELF32_R_TYPE(this_reloc->r_info);
184
        symtab_index = ELF32_R_SYM(this_reloc->r_info);
185
 
186
        symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
187
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
188
        symname      = strtab + symtab[symtab_index].st_name;
189
 
190
#if defined (__SUPPORT_LD_DEBUG__)
191
        debug_sym(symtab,strtab,symtab_index);
192
        debug_reloc(symtab,strtab,this_reloc);
193
#endif
194
 
195
        if (reloc_type != R_PPC_JMP_SLOT) {
196
                _dl_dprintf(2, "%s: Incorrect relocation type in jump relocation\n", _dl_progname);
197
                _dl_exit(1);
198
        };
199
 
200
        /* Address of dump instruction to fix up */
201
        insn_addr = (unsigned long) tpnt->loadaddr +
202
                (unsigned long) this_reloc->r_offset;
203
 
204
#if defined (__SUPPORT_LD_DEBUG__)
205
        if(_dl_debug_reloc && _dl_debug_detail)
206
                _dl_dprintf(_dl_debug_file, "\n\tResolving symbol %s %x --> ", symname, insn_addr);
207
#endif
208
 
209
        /* Get the address of the GOT entry */
210
        new_addr = (unsigned long) _dl_find_hash(
211
                strtab + symtab[symtab_index].st_name,
212
                tpnt->symbol_scope, tpnt, resolver);
213
        if (!new_addr) {
214
                _dl_dprintf(2, "%s: can't resolve symbol '%s'\n",
215
                        _dl_progname, symname);
216
                _dl_exit(1);
217
        };
218
 
219
#if defined (__SUPPORT_LD_DEBUG__)
220
        if(_dl_debug_reloc && _dl_debug_detail)
221
                _dl_dprintf(_dl_debug_file, "%x\n", new_addr);
222
#endif
223
 
224
        insns = (unsigned long *)insn_addr;
225
        delta = new_addr - insn_addr;
226
 
227
        if(delta<<6>>6 == delta){
228
                insns[0] = OPCODE_B(delta);
229
        }else if (new_addr <= 0x01fffffc || new_addr >= 0xfe000000){
230
                insns[0] = OPCODE_BA (new_addr);
231
        }else{
232
                /* Warning: we don't handle double-sized PLT entries */
233
                unsigned long plt_addr;
234
                unsigned long *ptr;
235
                int index;
236
 
237
                plt_addr = (unsigned long)tpnt->dynamic_info[DT_PLTGOT] +
238
                        (unsigned long)tpnt->loadaddr;
239
 
240
                delta = PLT_LONGBRANCH_ENTRY_WORDS*4 - (insn_addr-plt_addr+4);
241
 
242
                index = (insn_addr - plt_addr - PLT_INITIAL_ENTRY_WORDS*4)/8;
243
 
244
                ptr = (unsigned long *)tpnt->data_words;
245
                //DPRINTF("plt_addr=%x delta=%x index=%x ptr=%x\n", plt_addr, delta, index, ptr);
246
                insns += 1;
247
 
248
                ptr[index] = new_addr;
249
                PPC_SYNC;
250
                /* icache sync is not necessary, since this will be a data load */
251
                //PPC_DCBST(ptr+index);
252
                //PPC_SYNC;
253
                //PPC_ICBI(ptr+index);
254
                //PPC_ISYNC;
255
 
256
                insns[0] = OPCODE_B(delta);
257
 
258
        }
259
 
260
        /* instructions were modified */
261
        PPC_DCBST(insns);
262
        PPC_SYNC;
263
        PPC_ICBI(insns);
264
        PPC_ISYNC;
265
 
266
        return new_addr;
267
}
268
 
269
static int
270
_dl_parse(struct elf_resolve *tpnt, struct dyn_elf *scope,
271
          unsigned long rel_addr, unsigned long rel_size,
272
          int (*reloc_fnc) (struct elf_resolve *tpnt, struct dyn_elf *scope,
273
                            ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab))
274
{
275
        unsigned int i;
276
        char *strtab;
277
        Elf32_Sym *symtab;
278
        ELF_RELOC *rpnt;
279
        int symtab_index;
280
 
281
        /* Now parse the relocation information */
282
        rpnt = (ELF_RELOC *)(intptr_t) (rel_addr + tpnt->loadaddr);
283
        rel_size = rel_size / sizeof(ELF_RELOC);
284
 
285
        symtab = (Elf32_Sym *)(intptr_t) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr);
286
        strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
287
 
288
          for (i = 0; i < rel_size; i++, rpnt++) {
289
                int res;
290
 
291
                symtab_index = ELF32_R_SYM(rpnt->r_info);
292
 
293
                /* When the dynamic linker bootstrapped itself, it resolved some symbols.
294
                   Make sure we do not do them again */
295
                if (!symtab_index && tpnt->libtype == program_interpreter)
296
                        continue;
297
                if (symtab_index && tpnt->libtype == program_interpreter &&
298
                    _dl_symbol(strtab + symtab[symtab_index].st_name))
299
                        continue;
300
 
301
#if defined (__SUPPORT_LD_DEBUG__)
302
                debug_sym(symtab,strtab,symtab_index);
303
                debug_reloc(symtab,strtab,rpnt);
304
#endif
305
 
306
                res = reloc_fnc (tpnt, scope, rpnt, symtab, strtab);
307
 
308
                if (res==0) continue;
309
 
310
                _dl_dprintf(2, "\n%s: ",_dl_progname);
311
 
312
                if (symtab_index)
313
                  _dl_dprintf(2, "symbol '%s': ", strtab + symtab[symtab_index].st_name);
314
 
315
                if (res <0)
316
                {
317
                        int reloc_type = ELF32_R_TYPE(rpnt->r_info);
318
#if defined (__SUPPORT_LD_DEBUG__)
319
                        _dl_dprintf(2, "can't handle reloc type %s\n ", _dl_reltypes(reloc_type));
320
#else
321
                        _dl_dprintf(2, "can't handle reloc type %x\n", reloc_type);
322
#endif                  
323
                        _dl_exit(-res);
324
                }
325
                else if (res >0)
326
                {
327
                        _dl_dprintf(2, "can't resolve symbol\n");
328
                        return res;
329
                }
330
          }
331
          return 0;
332
}
333
 
334
static int
335
_dl_do_lazy_reloc (struct elf_resolve *tpnt, struct dyn_elf *scope,
336
                   ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
337
{
338
        int reloc_type;
339
        unsigned long reloc_addr;
340
#if defined (__SUPPORT_LD_DEBUG__)
341
        unsigned long old_val;
342
#endif
343
        (void)scope;
344
        (void)symtab;
345
        (void)strtab;
346
 
347
        reloc_addr = (unsigned long)tpnt->loadaddr + (unsigned long) rpnt->r_offset;
348
        reloc_type = ELF32_R_TYPE(rpnt->r_info);
349
 
350
#if defined (__SUPPORT_LD_DEBUG__)
351
        old_val = reloc_addr;
352
#endif
353
 
354
        switch (reloc_type) {
355
                case R_PPC_NONE:
356
                        return 0;
357
                        break;
358
                case R_PPC_JMP_SLOT:
359
                        {
360
                                int index;
361
                                unsigned long delta;
362
                                unsigned long *plt;
363
                                unsigned long *insns;
364
 
365
                                plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
366
 
367
                                delta = (unsigned long)(plt+PLT_TRAMPOLINE_ENTRY_WORDS+2) - (reloc_addr+4);
368
 
369
                                index = (reloc_addr - (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
370
                                                /sizeof(unsigned long);
371
                                index /= 2;
372
                                //DPRINTF("        index %x delta %x\n",index,delta);
373
                                insns = (unsigned long *)reloc_addr;
374
                                insns[0] = OPCODE_LI(11,index*4);
375
                                insns[1] = OPCODE_B(delta);
376
                                break;
377
                        }
378
                default:
379
#if 0
380
                        _dl_dprintf(2, "%s: (LAZY) can't handle reloc type ",
381
                                        _dl_progname);
382
#if defined (__SUPPORT_LD_DEBUG__)
383
                        _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
384
#endif
385
                        if (symtab_index)
386
                                _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
387
#endif
388
                        //_dl_exit(1);
389
                        return -1;
390
        };
391
 
392
        /* instructions were modified */
393
        PPC_DCBST(reloc_addr);
394
        PPC_DCBST(reloc_addr+4);
395
        PPC_SYNC;
396
        PPC_ICBI(reloc_addr);
397
        PPC_ICBI(reloc_addr+4);
398
        PPC_ISYNC;
399
 
400
#if defined (__SUPPORT_LD_DEBUG__)
401
        if(_dl_debug_reloc && _dl_debug_detail)
402
                _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x", old_val, reloc_addr);
403
#endif
404
        return 0;
405
 
406
}
407
 
408
static int
409
_dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
410
              ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
411
{
412
        int reloc_type;
413
        int symtab_index;
414
        char *symname;
415
        unsigned long *reloc_addr;
416
        unsigned long symbol_addr;
417
#if defined (__SUPPORT_LD_DEBUG__)
418
        unsigned long old_val;
419
#endif
420
 
421
        reloc_addr   = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
422
        reloc_type   = ELF32_R_TYPE(rpnt->r_info);
423
        symtab_index = ELF32_R_SYM(rpnt->r_info);
424
        symbol_addr  = 0;
425
        symname      = strtab + symtab[symtab_index].st_name;
426
 
427
        if (symtab_index) {
428
 
429
                symbol_addr = (unsigned long) _dl_find_hash(symname, scope,
430
                                (reloc_type == R_PPC_JMP_SLOT ? tpnt : NULL), symbolrel);
431
 
432
                /*
433
                 * We want to allow undefined references to weak symbols - this might
434
                 * have been intentional.  We should not be linking local symbols
435
                 * here, so all bases should be covered.
436
                 */
437
 
438
                if (!symbol_addr && ELF32_ST_BIND(symtab[symtab_index].st_info) == STB_GLOBAL) {
439
#if defined (__SUPPORT_LD_DEBUG__)
440
                        _dl_dprintf(2, "\tglobal symbol '%s' already defined in '%s'\n",
441
                                        symname, tpnt->libname);
442
#endif
443
                        return 0;
444
                }
445
        }
446
 
447
#if defined (__SUPPORT_LD_DEBUG__)
448
        old_val = *reloc_addr;
449
#endif
450
                switch (reloc_type) {
451
                        case R_PPC_NONE:
452
                                return 0;
453
                                break;
454
                        case R_PPC_REL24:
455
#if 0
456
                                {
457
                                        unsigned long delta = symbol_addr - (unsigned long)reloc_addr;
458
                                        if(delta<<6>>6 != delta){
459
                                                _dl_dprintf(2,"R_PPC_REL24: Reloc out of range\n");
460
                                                _dl_exit(1);
461
                                        }
462
                                        *reloc_addr &= 0xfc000003;
463
                                        *reloc_addr |= delta&0x03fffffc;
464
                                }
465
                                break;
466
#else
467
                                _dl_dprintf(2, "%s: symbol '%s' is type R_PPC_REL24\n\tCompile shared libraries with -fPIC!\n",
468
                                                _dl_progname, symname);
469
                                _dl_exit(1);
470
#endif
471
                        case R_PPC_RELATIVE:
472
                                *reloc_addr = (unsigned long)tpnt->loadaddr + (unsigned long)rpnt->r_addend;
473
                                break;
474
                        case R_PPC_ADDR32:
475
                                *reloc_addr += symbol_addr;
476
                                break;
477
                        case R_PPC_ADDR16_HA:
478
                                /* XXX is this correct? */
479
                                *(short *)reloc_addr += (symbol_addr+0x8000)>>16;
480
                                break;
481
                        case R_PPC_ADDR16_HI:
482
                                *(short *)reloc_addr += symbol_addr>>16;
483
                                break;
484
                        case R_PPC_ADDR16_LO:
485
                                *(short *)reloc_addr += symbol_addr;
486
                                break;
487
                        case R_PPC_JMP_SLOT:
488
                                {
489
                                        unsigned long targ_addr = (unsigned long)*reloc_addr;
490
                                        unsigned long delta = targ_addr - (unsigned long)reloc_addr;
491
                                        if(delta<<6>>6 == delta){
492
                                                *reloc_addr = OPCODE_B(delta);
493
                                        }else if (targ_addr <= 0x01fffffc || targ_addr >= 0xfe000000){
494
                                                *reloc_addr = OPCODE_BA (targ_addr);
495
                                        }else{
496
                                                {
497
                                                        int index;
498
                                                        unsigned long delta2;
499
                                                        unsigned long *plt, *ptr;
500
                                                        plt = (unsigned long *)(tpnt->dynamic_info[DT_PLTGOT] + tpnt->loadaddr);
501
 
502
                                                        delta2 = (unsigned long)(plt+PLT_LONGBRANCH_ENTRY_WORDS)
503
                                                                - (unsigned long)(reloc_addr+1);
504
 
505
                                                        index = ((unsigned long)reloc_addr -
506
                                                                        (unsigned long)(plt+PLT_INITIAL_ENTRY_WORDS))
507
                                                                /sizeof(unsigned long);
508
                                                        index /= 2;
509
                                                        //DPRINTF("        index %x delta %x\n",index,delta2);
510
                                                        ptr = (unsigned long *)tpnt->data_words;
511
                                                        ptr[index] = targ_addr;
512
                                                        reloc_addr[0] = OPCODE_LI(11,index*4);
513
                                                        reloc_addr[1] = OPCODE_B(delta2);
514
 
515
                                                        /* instructions were modified */
516
                                                        PPC_DCBST(reloc_addr+1);
517
                                                        PPC_SYNC;
518
                                                        PPC_ICBI(reloc_addr+1);
519
                                                }
520
                                        }
521
                                        break;
522
                                }
523
                        case R_PPC_GLOB_DAT:
524
                                *reloc_addr += symbol_addr;
525
                                break;
526
                        case R_PPC_COPY:
527
                                // handled later
528
                                return 0;
529
                                break;
530
                        default:
531
#if 0
532
                                _dl_dprintf(2, "%s: can't handle reloc type ", _dl_progname);
533
#if defined (__SUPPORT_LD_DEBUG__)
534
                                _dl_dprintf(2, "%s ", _dl_reltypes[reloc_type]);
535
#endif
536
                                if (symtab_index)
537
                                        _dl_dprintf(2, "'%s'\n", strtab + symtab[symtab_index].st_name);
538
#endif
539
                                //_dl_exit(1);
540
                                return -1;
541
                };
542
 
543
                /* instructions were modified */
544
                PPC_DCBST(reloc_addr);
545
                PPC_SYNC;
546
                PPC_ICBI(reloc_addr);
547
                PPC_ISYNC;
548
 
549
#if defined (__SUPPORT_LD_DEBUG__)
550
        if(_dl_debug_reloc && _dl_debug_detail)
551
                _dl_dprintf(_dl_debug_file, "\tpatched: %x ==> %x @ %x", old_val, *reloc_addr, reloc_addr);
552
#endif
553
 
554
        return 0;
555
}
556
 
557
 
558
/* This is done as a separate step, because there are cases where
559
   information is first copied and later initialized.  This results in
560
   the wrong information being copied.  Someone at Sun was complaining about
561
   a bug in the handling of _COPY by SVr4, and this may in fact be what he
562
   was talking about.  Sigh. */
563
static int
564
_dl_do_copy (struct elf_resolve *tpnt, struct dyn_elf *scope,
565
             ELF_RELOC *rpnt, Elf32_Sym *symtab, char *strtab)
566
{
567
        int reloc_type;
568
        int symtab_index;
569
        unsigned long *reloc_addr;
570
        unsigned long symbol_addr;
571
        int goof = 0;
572
        char *symname;
573
 
574
        reloc_addr = (unsigned long *)(intptr_t) (tpnt->loadaddr + (unsigned long) rpnt->r_offset);
575
        reloc_type = ELF32_R_TYPE(rpnt->r_info);
576
        if (reloc_type != R_PPC_COPY)
577
                return 0;
578
        symtab_index = ELF32_R_SYM(rpnt->r_info);
579
        symbol_addr = 0;
580
        symname      = strtab + symtab[symtab_index].st_name;
581
 
582
        if (symtab_index) {
583
                symbol_addr = (unsigned long) _dl_find_hash(symname, scope, NULL, copyrel);
584
                if (!symbol_addr) goof++;
585
        }
586
        if (!goof) {
587
#if defined (__SUPPORT_LD_DEBUG__)
588
                if(_dl_debug_move)
589
                  _dl_dprintf(_dl_debug_file,"\n%s move %x bytes from %x to %x",
590
                             symname, symtab[symtab_index].st_size,
591
                             symbol_addr, symtab[symtab_index].st_value);
592
#endif
593
                        _dl_memcpy((char *) reloc_addr,
594
                                        (char *) symbol_addr, symtab[symtab_index].st_size);
595
        }
596
 
597
        return goof;
598
}
599
 
600
void _dl_parse_lazy_relocation_information(struct elf_resolve *tpnt,
601
        unsigned long rel_addr, unsigned long rel_size, int type)
602
{
603
        (void) type;
604
        (void)_dl_parse(tpnt, NULL, rel_addr, rel_size, _dl_do_lazy_reloc);
605
}
606
 
607
int _dl_parse_relocation_information(struct elf_resolve *tpnt,
608
        unsigned long rel_addr, unsigned long rel_size, int type)
609
{
610
        (void) type;
611
        return _dl_parse(tpnt, tpnt->symbol_scope, rel_addr, rel_size, _dl_do_reloc);
612
}
613
 
614
int _dl_parse_copy_information(struct dyn_elf *xpnt, unsigned long rel_addr,
615
        unsigned long rel_size, int type)
616
{
617
        (void) type;
618
        return _dl_parse(xpnt->dyn, xpnt->next, rel_addr, rel_size, _dl_do_copy);
619
}
620
 
621
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.