summaryrefslogtreecommitdiff
path: root/bfd/coff64-rs6000.c
diff options
context:
space:
mode:
Diffstat (limited to 'bfd/coff64-rs6000.c')
-rw-r--r--bfd/coff64-rs6000.c123
1 files changed, 93 insertions, 30 deletions
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index fbd35dd3c41..b1bc2f58af9 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -96,6 +96,8 @@ static void _bfd_xcoff64_swap_aux_in
PARAMS ((bfd *, PTR, int, int, int, int, PTR));
static unsigned int _bfd_xcoff64_swap_aux_out
PARAMS ((bfd *, PTR, int, int, int, int, PTR));
+static void xcoff64_swap_reloc_in PARAMS ((bfd *, PTR, PTR));
+static unsigned int xcoff64_swap_reloc_out PARAMS ((bfd *, PTR, PTR));
extern boolean _bfd_xcoff_mkobject PARAMS ((bfd *));
extern boolean _bfd_xcoff_copy_private_bfd_data PARAMS ((bfd *, bfd *));
extern boolean _bfd_xcoff_is_local_label_name PARAMS ((bfd *, const char *));
@@ -199,7 +201,9 @@ extern int rs6000coff_core_file_failing_signal PARAMS ((bfd *abfd));
#define coff_SWAP_sym_out _bfd_xcoff64_swap_sym_out
#define coff_SWAP_aux_in _bfd_xcoff64_swap_aux_in
#define coff_SWAP_aux_out _bfd_xcoff64_swap_aux_out
-
+#define coff_swap_reloc_in xcoff64_swap_reloc_in
+#define coff_swap_reloc_out xcoff64_swap_reloc_out
+#define NO_COFF_RELOCS
#include "coffcode.h"
@@ -614,6 +618,40 @@ xcoff64_swap_ldsym_out (abfd, src, d)
bfd_put_32 (abfd, src->l_parm, dst->l_parm);
}
+static void
+xcoff64_swap_reloc_in (abfd, s, d)
+ bfd *abfd;
+ PTR s;
+ PTR d;
+{
+ struct external_reloc *src = (struct external_reloc *) s;
+ struct internal_reloc *dst = (struct internal_reloc *) d;
+
+ memset (dst, 0, sizeof (struct internal_reloc));
+
+ dst->r_vaddr = bfd_get_64 (abfd, src->r_vaddr);
+ dst->r_symndx = bfd_get_32 (abfd, src->r_symndx);
+ dst->r_size = bfd_get_8 (abfd, src->r_size);
+ dst->r_type = bfd_get_8 (abfd, src->r_type);
+}
+
+static unsigned int
+xcoff64_swap_reloc_out (abfd, s, d)
+ bfd *abfd;
+ PTR s;
+ PTR d;
+{
+ struct internal_reloc *src = (struct internal_reloc *) s;
+ struct external_reloc *dst = (struct external_reloc *) d;
+
+ bfd_put_64 (abfd, src->r_vaddr, dst->r_vaddr);
+ bfd_put_32 (abfd, src->r_symndx, dst->r_symndx);
+ bfd_put_8 (abfd, src->r_type, dst->r_type);
+ bfd_put_8 (abfd, src->r_size, dst->r_size);
+
+ return bfd_coff_relsz (abfd);
+}
+
/* Swap in the ldrel structure. */
static void
@@ -1203,7 +1241,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_POS", /* name */
+ "R_POS_64", /* name */
true, /* partial_inplace */
MINUS_ONE, /* src_mask */
MINUS_ONE, /* dst_mask */
@@ -1310,7 +1348,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_BA", /* name */
+ "R_BA_26", /* name */
true, /* partial_inplace */
0x3fffffc, /* src_mask */
0x3fffffc, /* dst_mask */
@@ -1514,7 +1552,7 @@ reloc_howto_type xcoff64_howto_table[] =
0, /* bitpos */
complain_overflow_signed, /* complain_on_overflow */
0, /* special_function */
- "R_RBR", /* name */
+ "R_RBR_26", /* name */
true, /* partial_inplace */
0xffff, /* src_mask */
0xffff, /* dst_mask */
@@ -1537,32 +1575,47 @@ reloc_howto_type xcoff64_howto_table[] =
HOWTO (R_POS, /* type */
0, /* rightshift */
- 4, /* size (0 = byte, 1 = short, 2 = long) */
- 64, /* bitsize */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 32, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_POS", /* name */
+ "R_POS_32", /* name */
true, /* partial_inplace */
- MINUS_ONE, /* src_mask */
- MINUS_ONE, /* dst_mask */
+ 0xffffffff, /* src_mask */
+ 0xffffffff, /* dst_mask */
false), /* pcrel_offset */
/* 16 bit Non modifiable absolute branch. */
HOWTO (R_BA, /* type */
0, /* rightshift */
- 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
16, /* bitsize */
false, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
0, /* special_function */
- "R_BA", /* name */
+ "R_BA_16", /* name */
true, /* partial_inplace */
0xfffc, /* src_mask */
0xfffc, /* dst_mask */
false), /* pcrel_offset */
+
+ /* Modifiable branch relative. */
+ HOWTO (R_RBR, /* type */
+ 0, /* rightshift */
+ 1, /* size (0 = byte, 1 = short, 2 = long) */
+ 16, /* bitsize */
+ false, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "R_RBR_16", /* name */
+ true, /* partial_inplace */
+ 0xffff, /* src_mask */
+ 0xffff, /* dst_mask */
+ false), /* pcrel_offset */
};
void
@@ -1570,15 +1623,27 @@ xcoff64_rtype2howto (relent, internal)
arelent *relent;
struct internal_reloc *internal;
{
- relent->howto = xcoff64_howto_table + internal->r_type;
-
- /* Check for relocs we don't know of. */
- if (internal->r_type
- >= sizeof (xcoff64_howto_table) / sizeof (xcoff64_howto_table[0]))
- abort ();
- if (internal->r_type != relent->howto->type)
+ if (internal->r_type > R_RBRC)
abort ();
+ /* Default howto layout works most of the time */
+ relent->howto = &xcoff64_howto_table[internal->r_type];
+
+ /* Special case some 16 bit reoloc */
+ if (15 == (internal->r_size & 0x3f))
+ {
+ if (R_BA == internal->r_type)
+ relent->howto = &xcoff64_howto_table[0x1d];
+ else if (R_RBR == internal->r_type)
+ relent->howto = &xcoff64_howto_table[0x1e];
+ }
+ /* Special case 32 bit */
+ else if (31 == (internal->r_size & 0x3f))
+ {
+ if (R_POS == internal->r_type)
+ relent->howto = &xcoff64_howto_table[0x1c];
+ }
+
/* The r_size field of an XCOFF reloc encodes the bitsize of the
relocation, as well as indicating whether it is signed or not.
Doublecheck that the relocation information gathered from the
@@ -1588,12 +1653,10 @@ xcoff64_rtype2howto (relent, internal)
&& (relent->howto->bitsize
!= ((unsigned int) internal->r_size & 0x3f) + 1))
abort ();
-#if 0
- if ((internal->r_size & 0x80) != 0
- ? (relent->howto->complain_on_overflow != complain_overflow_signed)
- : (relent->howto->complain_on_overflow != complain_overflow_bitfield))
- abort ();
-#endif
+
+ /* Put a meaningful value in addend */
+ relent->addend = (internal->r_size & 0x80) ? - internal->r_vaddr
+ : internal->r_vaddr;
}
reloc_howto_type *
@@ -1613,9 +1676,9 @@ xcoff64_reloc_type_lookup (abfd, code)
return &xcoff64_howto_table[3];
case BFD_RELOC_32:
case BFD_RELOC_CTOR:
- return &xcoff64_howto_table[0];
- case BFD_RELOC_64:
return &xcoff64_howto_table[0x1c];
+ case BFD_RELOC_64:
+ return &xcoff64_howto_table[0];
default:
return NULL;
}
@@ -2314,7 +2377,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
_bfd_xcoff64_swap_aux_out, /* _bfd_swap_aux_out */
_bfd_xcoff64_swap_sym_out, /* _bfd_swap_sym_out */
_bfd_xcoff64_swap_lineno_out, /* _bfd_swap_lineno_out */
- coff_swap_reloc_out, /* _bfd_swap_reloc_out */
+ xcoff64_swap_reloc_out, /* _bfd_swap_reloc_out */
coff_swap_filehdr_out, /* _bfd_swap_filehdr_out */
coff_swap_aouthdr_out, /* _bfd_swap_aouthdr_out */
coff_swap_scnhdr_out, /* _bfd_swap_scnhdr_out */
@@ -2334,7 +2397,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
coff_swap_filehdr_in, /* _bfd_coff_swap_filehdr_in */
coff_swap_aouthdr_in, /* _bfd_swap_aouthdr_in */
coff_swap_scnhdr_in, /* _bfd_swap_scnhdr_in */
- coff_swap_reloc_in, /* _bfd_reloc_in */
+ xcoff64_swap_reloc_in, /* _bfd_reloc_in */
xcoff64_bad_format_hook, /* _bfd_bad_format_hook */
coff_set_arch_mach_hook, /* _bfd_set_arch_mach_hook */
coff_mkobject_hook, /* _bfd_mkobject_hook */
@@ -2569,7 +2632,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
_bfd_xcoff64_swap_aux_out, /* _bfd_swap_aux_out */
_bfd_xcoff64_swap_sym_out, /* _bfd_swap_sym_out */
_bfd_xcoff64_swap_lineno_out, /* _bfd_swap_lineno_out */
- coff_swap_reloc_out, /* _bfd_swap_reloc_out */
+ xcoff64_swap_reloc_out, /* _bfd_swap_reloc_out */
coff_swap_filehdr_out, /* _bfd_swap_filehdr_out */
coff_swap_aouthdr_out, /* _bfd_swap_aouthdr_out */
coff_swap_scnhdr_out, /* _bfd_swap_scnhdr_out */
@@ -2589,7 +2652,7 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
coff_swap_filehdr_in, /* _bfd_coff_swap_filehdr_in */
coff_swap_aouthdr_in, /* _bfd_swap_aouthdr_in */
coff_swap_scnhdr_in, /* _bfd_swap_scnhdr_in */
- coff_swap_reloc_in, /* _bfd_reloc_in */
+ xcoff64_swap_reloc_in, /* _bfd_reloc_in */
xcoff64_bad_format_hook, /* _bfd_bad_format_hook */
coff_set_arch_mach_hook, /* _bfd_set_arch_mach_hook */
coff_mkobject_hook, /* _bfd_mkobject_hook */