summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog7
-rw-r--r--bfd/coff-rs6000.c26
-rw-r--r--bfd/coff64-rs6000.c116
-rw-r--r--bfd/libxcoff.h10
4 files changed, 142 insertions, 17 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index ed2814779f0..a837ebec983 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,10 @@
+2002-05-10 Tom Rix <trix@redhat.com>
+
+ * coff64-rs6000.c (xcoff64_reloc_type_br): New function for
+ xcoff64_ppc_relocate_section.
+ * coff-rs6000.c : Extern common xcoff_reloc_type functions.
+ * libxcoff.h: Common xcoff_reloc_type function declaration.
+
2002-05-10 Alan Modra <amodra@bigpond.net.au>
* elf32-i386.c (elf_i386_relocate_section): Remove overflow checks
diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c
index b1db78fe25c..10ef5dfd777 100644
--- a/bfd/coff-rs6000.c
+++ b/bfd/coff-rs6000.c
@@ -155,15 +155,7 @@ static boolean do_copy PARAMS((bfd *, bfd *));
static boolean do_shared_object_padding PARAMS ((bfd *, bfd *, ufile_ptr *, int));
/* Relocation functions */
-static boolean xcoff_reloc_type_noop PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_fail PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_pos PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_neg PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_rel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_toc PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_ba PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
static boolean xcoff_reloc_type_br PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
-static boolean xcoff_reloc_type_crel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
static boolean xcoff_complain_overflow_dont_func
PARAMS ((XCOFF_COMPLAIN_FUNCTION_ARGS));
@@ -2726,7 +2718,7 @@ xcoff_swap_ldrel_out (abfd, src, d)
}
-static boolean
+boolean
xcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2743,7 +2735,7 @@ xcoff_reloc_type_noop (input_bfd, input_section, output_bfd, rel, sym, howto,
return true;
}
-static boolean
+boolean
xcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd;
@@ -2764,7 +2756,7 @@ xcoff_reloc_type_fail (input_bfd, input_section, output_bfd, rel, sym, howto,
return false;
}
-static boolean
+boolean
xcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2782,7 +2774,7 @@ xcoff_reloc_type_pos (input_bfd, input_section, output_bfd, rel, sym, howto,
return true;
}
-static boolean
+boolean
xcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2800,7 +2792,7 @@ xcoff_reloc_type_neg (input_bfd, input_section, output_bfd, rel, sym, howto,
return true;
}
-static boolean
+boolean
xcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2824,7 +2816,8 @@ xcoff_reloc_type_rel (input_bfd, input_section, output_bfd, rel, sym, howto,
input_section->output_offset);
return true;
}
-static boolean
+
+boolean
xcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd;
@@ -2866,7 +2859,8 @@ xcoff_reloc_type_toc (input_bfd, input_section, output_bfd, rel, sym, howto,
(sym->n_value - xcoff_data (input_bfd)->toc));
return true;
}
-static boolean
+
+boolean
xcoff_reloc_type_ba (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
@@ -2967,7 +2961,7 @@ xcoff_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
return true;
}
-static boolean
+boolean
xcoff_reloc_type_crel (input_bfd, input_section, output_bfd, rel, sym, howto,
val, addend, relocation, contents)
bfd *input_bfd ATTRIBUTE_UNUSED;
diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c
index b1bc2f58af9..931a914cbf6 100644
--- a/bfd/coff64-rs6000.c
+++ b/bfd/coff64-rs6000.c
@@ -152,6 +152,42 @@ static boolean xcoff64_generate_rtinit
PARAMS ((bfd *, const char *, const char *, boolean));
static boolean xcoff64_bad_format_hook PARAMS ((bfd *, PTR ));
+/* Relocation functions */
+static boolean xcoff64_reloc_type_br PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+
+boolean (*xcoff64_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
+ (XCOFF_RELOC_FUNCTION_ARGS) =
+{
+ xcoff_reloc_type_pos, /* R_POS (0x00) */
+ xcoff_reloc_type_neg, /* R_NEG (0x01) */
+ xcoff_reloc_type_rel, /* R_REL (0x02) */
+ xcoff_reloc_type_toc, /* R_TOC (0x03) */
+ xcoff_reloc_type_fail, /* R_RTB (0x04) */
+ xcoff_reloc_type_toc, /* R_GL (0x05) */
+ xcoff_reloc_type_toc, /* R_TCL (0x06) */
+ xcoff_reloc_type_fail, /* (0x07) */
+ xcoff_reloc_type_ba, /* R_BA (0x08) */
+ xcoff_reloc_type_fail, /* (0x09) */
+ xcoff64_reloc_type_br, /* R_BR (0x0a) */
+ xcoff_reloc_type_fail, /* (0x0b) */
+ xcoff_reloc_type_pos, /* R_RL (0x0c) */
+ xcoff_reloc_type_pos, /* R_RLA (0x0d) */
+ xcoff_reloc_type_fail, /* (0x0e) */
+ xcoff_reloc_type_noop, /* R_REF (0x0f) */
+ xcoff_reloc_type_fail, /* (0x10) */
+ xcoff_reloc_type_fail, /* (0x11) */
+ xcoff_reloc_type_toc, /* R_TRL (0x12) */
+ xcoff_reloc_type_toc, /* R_TRLA (0x13) */
+ xcoff_reloc_type_fail, /* R_RRTBI (0x14) */
+ xcoff_reloc_type_fail, /* R_RRTBA (0x15) */
+ xcoff_reloc_type_ba, /* R_CAI (0x16) */
+ xcoff_reloc_type_crel, /* R_CREL (0x17) */
+ xcoff_reloc_type_ba, /* R_RBA (0x18) */
+ xcoff_reloc_type_ba, /* R_RBAC (0x19) */
+ xcoff64_reloc_type_br, /* R_RBR (0x1a) */
+ xcoff_reloc_type_ba, /* R_RBRC (0x1b) */
+};
+
/* coffcode.h needs these to be defined. */
/* Internalcoff.h and coffcode.h modify themselves based on these flags. */
#define XCOFF64
@@ -1030,6 +1066,84 @@ xcoff64_write_object_contents (abfd)
return true;
}
+static boolean
+xcoff64_reloc_type_br (input_bfd, input_section, output_bfd, rel, sym, howto,
+ val, addend, relocation, contents)
+ bfd *input_bfd;
+ asection *input_section;
+ bfd *output_bfd ATTRIBUTE_UNUSED;
+ struct internal_reloc *rel;
+ struct internal_syment *sym ATTRIBUTE_UNUSED;
+ struct reloc_howto_struct *howto;
+ bfd_vma val;
+ bfd_vma addend;
+ bfd_vma *relocation;
+ bfd_byte *contents;
+{
+ struct xcoff_link_hash_entry *h;
+
+ if (0 > rel->r_symndx)
+ return false;
+
+ h = obj_xcoff_sym_hashes (input_bfd)[rel->r_symndx];
+
+ /* If we see an R_BR or R_RBR reloc which is jumping to global
+ linkage code, and it is followed by an appropriate cror nop
+ instruction, we replace the cror with ld r2,40(r1). This
+ restores the TOC after the glink code. Contrariwise, if the
+ call is followed by a ld r2,40(r1), but the call is not
+ going to global linkage code, we can replace the load with a
+ cror. */
+ if (NULL != h
+ && bfd_link_hash_defined == h->root.type
+ && (rel->r_vaddr - input_section->vma + 8 <=
+ input_section->_cooked_size))
+ {
+ bfd_byte *pnext;
+ unsigned long next;
+
+ pnext = contents + (rel->r_vaddr - input_section->vma) + 4;
+ next = bfd_get_32 (input_bfd, pnext);
+
+ /* The _ptrgl function is magic. It is used by the AIX compiler to call
+ a function through a pointer. */
+ if (h->smclas == XMC_GL || strcmp (h->root.root.string, "._ptrgl") == 0)
+ {
+ if (next == 0x4def7b82 /* cror 15,15,15 */
+ || next == 0x4ffffb82 /* cror 31,31,31 */
+ || next == 0x60000000) /* ori r0,r0,0 */
+ bfd_put_32 (input_bfd, 0xe8410028, pnext); /* ld r2,40(r1) */
+ }
+ else
+ {
+ if (next == 0xe8410028) /* ld r2,40(r1) */
+ bfd_put_32 (input_bfd, 0x60000000, pnext); /* ori r0,r0,0 */
+ }
+ }
+ else if (NULL != h && bfd_link_hash_undefined == h->root.type)
+ {
+ /* Normally, this relocation is against a defined symbol. In the
+ case where this is a partial link and the output section offset
+ is greater than 2^25, the linker will return an invalid error
+ message that the relocation has been truncated. Yes it has been
+ truncated but no it not important. For this case, disable the
+ overflow checking. */
+ howto->complain_on_overflow = complain_overflow_dont;
+ }
+
+ howto->pc_relative = true;
+ howto->src_mask &= ~3;
+ howto->dst_mask = howto->src_mask;
+
+ /* A PC relative reloc includes the section address. */
+ addend += input_section->vma;
+
+ *relocation = val + addend;
+ *relocation -= (input_section->output_section->vma +
+ input_section->output_offset);
+ return true;
+}
+
/* This is the relocation function for the PowerPC64.
See xcoff_ppc_relocation_section for more information. */
@@ -1146,7 +1260,7 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd,
}
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
- || (false == xcoff_calculate_relocation[rel->r_type]
+ || (false == xcoff64_calculate_relocation[rel->r_type]
(input_bfd, input_section, output_bfd, rel, sym, &howto, val,
addend, &relocation, contents)))
return false;
diff --git a/bfd/libxcoff.h b/bfd/libxcoff.h
index 5e16fb2b601..7463eeffecf 100644
--- a/bfd/libxcoff.h
+++ b/bfd/libxcoff.h
@@ -222,4 +222,14 @@ extern boolean (*xcoff_calculate_relocation[XCOFF_MAX_CALCULATE_RELOCATION])
extern boolean (*xcoff_complain_overflow[XCOFF_MAX_COMPLAIN_OVERFLOW])
(XCOFF_COMPLAIN_FUNCTION_ARGS);
+/* Relocation functions */
+boolean xcoff_reloc_type_noop PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_fail PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_pos PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_neg PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_rel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_toc PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_ba PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+boolean xcoff_reloc_type_crel PARAMS ((XCOFF_RELOC_FUNCTION_ARGS));
+
#endif /* LIBXCOFF_H */