38 |
#include <elf.h> |
#include <elf.h> |
39 |
|
|
40 |
#include "gclincl.h" |
#include "gclincl.h" |
41 |
#ifdef HAVE_LIBBFD |
/* #ifdef HAVE_LIBBFD */ |
42 |
#include <bfd.h> |
/* #include <bfd.h> */ |
43 |
#endif |
/* #endif */ |
44 |
|
|
45 |
#ifdef STAND |
#ifdef STAND |
46 |
#include "include.h" |
#include "include.h" |
446 |
} |
} |
447 |
|
|
448 |
|
|
449 |
#ifdef HAVE_LIBBFD |
/* #ifdef HAVE_LIBBFD */ |
450 |
|
|
451 |
typedef struct { |
/* typedef struct { */ |
452 |
unsigned int type; |
/* unsigned int type; */ |
453 |
reloc_howto_type *h; |
/* reloc_howto_type *h; */ |
454 |
} mtbl; |
/* } mtbl; */ |
455 |
|
|
456 |
static void |
/* static void */ |
457 |
do_bfd_reloc(unsigned int oc,unsigned int val, |
/* do_bfd_reloc(unsigned int oc,unsigned int val, */ |
458 |
unsigned int *where) { |
/* unsigned int *where) { */ |
459 |
|
|
460 |
static bfd *dum; |
/* static bfd *dum; */ |
461 |
static reloc_howto_type * m[BFD_RELOC_UNUSED]; |
/* static reloc_howto_type * m[BFD_RELOC_UNUSED]; */ |
462 |
reloc_howto_type *h; |
/* reloc_howto_type *h; */ |
463 |
|
|
464 |
if (!m[0]) { |
/* if (!m[0]) { */ |
465 |
|
|
466 |
extern int in_bfd_init; |
/* extern int in_bfd_init; */ |
467 |
|
|
468 |
bfd_reloc_code_real_type t; |
/* bfd_reloc_code_real_type t; */ |
469 |
|
|
470 |
in_bfd_init=1; |
/* in_bfd_init=1; */ |
471 |
|
|
472 |
bfd_init(); |
/* bfd_init(); */ |
473 |
|
|
474 |
if (!(dum=bfd_openr("/dev/null",NULL))) |
/* if (!(dum=bfd_openr("/dev/null",NULL))) */ |
475 |
FEerror("Cannot open dummy bfd\n"); |
/* FEerror("Cannot open dummy bfd\n"); */ |
476 |
|
|
477 |
for (t=BFD_RELOC_UNUSED;t>_dummy_first_bfd_reloc_code_real;t--) |
/* for (t=BFD_RELOC_UNUSED;t>_dummy_first_bfd_reloc_code_real;t--) */ |
478 |
if ((h=bfd_reloc_type_lookup(dum,t))) |
/* if ((h=bfd_reloc_type_lookup(dum,t))) */ |
479 |
m[h->type]=h; |
/* m[h->type]=h; */ |
480 |
|
|
481 |
in_bfd_init=0; |
/* in_bfd_init=0; */ |
|
|
|
|
} |
|
482 |
|
|
483 |
if (oc>=BFD_RELOC_UNUSED || !m[oc]) |
/* } */ |
|
FEerror("Cannot lookup type %u\n",oc); |
|
|
h=m[oc]; |
|
|
|
|
|
if (h->pc_relative) |
|
|
val-=(unsigned int)where; |
|
|
|
|
|
val>>=h->rightshift; |
|
|
val<<=h->bitpos; |
|
|
/* *where = ( (*where & ~h->dst_mask) | */ |
|
|
/* (((*where & h->src_mask) + val) & h->dst_mask)); */ |
|
|
|
|
|
#define DOIT(x) \ |
|
|
x = ( (x & ~h->dst_mask) | (((x & h->src_mask) + val) & h->dst_mask)) |
|
|
|
|
|
switch (h->size) { |
|
|
case 0: |
|
|
{ |
|
|
char x = bfd_get_8 (dum, (char *) where); |
|
|
DOIT (x); |
|
|
bfd_put_8 (dum, x, (unsigned char *) where); |
|
|
} |
|
|
break; |
|
484 |
|
|
485 |
case 1: |
/* if (oc>=BFD_RELOC_UNUSED || !m[oc]) */ |
486 |
{ |
/* FEerror("Cannot lookup type %u\n",oc); */ |
487 |
short x = bfd_get_16 (dum, (bfd_byte *) where); |
/* h=m[oc]; */ |
488 |
DOIT (x); |
|
489 |
bfd_put_16 (dum, (bfd_vma) x, (unsigned char *) where); |
/* if (h->pc_relative) */ |
490 |
} |
/* val-=(unsigned int)where; */ |
491 |
break; |
|
492 |
case 2: |
/* val>>=h->rightshift; */ |
493 |
{ |
/* val<<=h->bitpos; */ |
494 |
long x = bfd_get_32 (dum, (bfd_byte *) where); |
|
495 |
DOIT (x); |
/* #define DOIT(x) \ */ |
496 |
bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); |
/* x = ( (x & ~h->dst_mask) | (((x & h->src_mask) + val) & h->dst_mask)) */ |
497 |
} |
|
498 |
break; |
/* switch (h->size) { */ |
499 |
case -2: |
/* case 0: */ |
500 |
{ |
/* { */ |
501 |
long x = bfd_get_32 (dum, (bfd_byte *) where); |
/* char x = bfd_get_8 (dum, (char *) where); */ |
502 |
val = -val; |
/* DOIT (x); */ |
503 |
DOIT (x); |
/* bfd_put_8 (dum, x, (unsigned char *) where); */ |
504 |
bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); |
/* } */ |
505 |
} |
/* break; */ |
506 |
break; |
|
507 |
|
/* case 1: */ |
508 |
|
/* { */ |
509 |
|
/* short x = bfd_get_16 (dum, (bfd_byte *) where); */ |
510 |
|
/* DOIT (x); */ |
511 |
|
/* bfd_put_16 (dum, (bfd_vma) x, (unsigned char *) where); */ |
512 |
|
/* } */ |
513 |
|
/* break; */ |
514 |
|
/* case 2: */ |
515 |
|
/* { */ |
516 |
|
/* long x = bfd_get_32 (dum, (bfd_byte *) where); */ |
517 |
|
/* DOIT (x); */ |
518 |
|
/* bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); */ |
519 |
|
/* } */ |
520 |
|
/* break; */ |
521 |
|
/* case -2: */ |
522 |
|
/* { */ |
523 |
|
/* long x = bfd_get_32 (dum, (bfd_byte *) where); */ |
524 |
|
/* val = -val; */ |
525 |
|
/* DOIT (x); */ |
526 |
|
/* bfd_put_32 (dum, (bfd_vma) x, (bfd_byte *) where); */ |
527 |
|
/* } */ |
528 |
|
/* break; */ |
529 |
|
|
530 |
case -1: |
/* case -1: */ |
531 |
{ |
/* { */ |
532 |
long x = bfd_get_16 (dum, (bfd_byte *) where); |
/* long x = bfd_get_16 (dum, (bfd_byte *) where); */ |
533 |
val = -val; |
/* val = -val; */ |
534 |
DOIT (x); |
/* DOIT (x); */ |
535 |
bfd_put_16 (dum, (bfd_vma) x, (bfd_byte *) where); |
/* bfd_put_16 (dum, (bfd_vma) x, (bfd_byte *) where); */ |
536 |
} |
/* } */ |
537 |
break; |
/* break; */ |
538 |
|
|
539 |
case 3: |
/* case 3: */ |
540 |
/* Do nothing */ |
/* break; */ |
|
break; |
|
541 |
|
|
542 |
case 4: |
/* case 4: */ |
543 |
#ifdef BFD64 |
/* #ifdef BFD64 */ |
544 |
{ |
/* { */ |
545 |
bfd_vma x = bfd_get_64 (dum, (bfd_byte *) where); |
/* bfd_vma x = bfd_get_64 (dum, (bfd_byte *) where); */ |
546 |
DOIT (x); |
/* DOIT (x); */ |
547 |
bfd_put_64 (dum, x, (bfd_byte *) where); |
/* bfd_put_64 (dum, x, (bfd_byte *) where); */ |
548 |
} |
/* } */ |
549 |
#else |
/* #else */ |
550 |
FEerror("Bad howto size %u\n",h->size); |
/* FEerror("Bad howto size %u\n",h->size); */ |
551 |
/* abort (); */ |
/* #endif */ |
552 |
#endif |
/* break; */ |
553 |
break; |
/* default: */ |
554 |
default: |
/* FEerror("Bad howto size %u\n",h->size); */ |
555 |
FEerror("Bad howto size %u\n",h->size); |
/* break; */ |
556 |
break; |
/* } */ |
|
} |
|
557 |
|
|
558 |
} |
/* } */ |
559 |
|
|
560 |
#endif /* HAVE_LIBBFD */ |
/* #endif HAVE_LIBBFD */ |
561 |
|
|
562 |
static void |
static void |
563 |
relocate(symbol_table,reloc_info,sh_type) |
relocate(symbol_table,reloc_info,sh_type) |
589 |
#define ADD_VAL(where, mask, val) \ |
#define ADD_VAL(where, mask, val) \ |
590 |
*(unsigned int *)where += ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
*(unsigned int *)where += ((val & mask) | ((*(unsigned int *)where) & ~mask)) |
591 |
|
|
592 |
#ifdef HAVE_LIBBFD |
/* #ifdef HAVE_LIBBFD */ |
593 |
do_bfd_reloc(ELF32_R_TYPE(reloc_info->r_info),s+a,(unsigned int *)where); |
/* do_bfd_reloc(ELF32_R_TYPE(reloc_info->r_info),s+a,(unsigned int *)where); */ |
594 |
#else |
/* #else */ |
595 |
switch(ELF32_R_TYPE(reloc_info->r_info)){ |
switch(ELF32_R_TYPE(reloc_info->r_info)){ |
596 |
#if (defined(__svr4__) || defined(__linux__)) && defined(__i386__) |
#if (defined(__svr4__) || defined(__linux__)) && defined(__i386__) |
597 |
case R_386_NONE: |
case R_386_NONE: |
681 |
printf("(non supported relocation type %d)\n", |
printf("(non supported relocation type %d)\n", |
682 |
ELF32_R_TYPE(reloc_info->r_info)); |
ELF32_R_TYPE(reloc_info->r_info)); |
683 |
} |
} |
684 |
#endif /* HAVE_LIBBFD */ |
/* #endif HAVE_LIBBFD */ |
685 |
} |
} |
686 |
} |
} |
687 |
|
|