From f1f0d9ab14a55973f82d67fe1fa8195e80b325be Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Fri, 10 May 2002 21:20:16 +0000 Subject: [PATCH] XCOFF64 fixes. For setting arch/mach and for R_BR relocations. --- bfd/ChangeLog | 7 +++ bfd/coff-rs6000.c | 26 ++++------ bfd/coff64-rs6000.c | 116 +++++++++++++++++++++++++++++++++++++++++++- bfd/libxcoff.h | 10 ++++ ld/ChangeLog | 11 +++++ ld/emultempl/aix.em | 45 +++++++++-------- ld/ldfile.c | 8 ++- ld/ldfile.h | 2 +- 8 files changed, 187 insertions(+), 38 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 + + * 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 * 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 */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 7aea9e92b25..a38bd69d845 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,14 @@ +2002-05-10 Tom Rix + + * emultempl/aix.em: (gld*_set_output_arch): New function. Use + architecture and machine information in the output bfd. + (gld*_before_parse): Remove old arch and machine code. + (choose_target): Rename to gld*_choose_target. + (rtld): Change type to int. + * ldfile.c (ldfile_try_open_bfd): Disable compatiblity check for + objects in XCOFF archives. + * ldfile.h: Update copyright date. + 2002-05-10 Jakub Jelinek * ldmain.c (main): Enable -z combreloc by default. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index 28f45c4ee35..90e104a0d30 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -53,11 +53,13 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "coff/internal.h" #include "coff/xcoff.h" +#include "libcoff.h" +#include "libxcoff.h" static void gld${EMULATION_NAME}_before_parse PARAMS ((void)); static int gld${EMULATION_NAME}_parse_args PARAMS ((int, char **)); static void gld${EMULATION_NAME}_after_open PARAMS ((void)); -static char *choose_target PARAMS ((int, char **)); +static char *gld${EMULATION_NAME}_choose_target PARAMS ((int, char **)); static void gld${EMULATION_NAME}_before_allocation PARAMS ((void)); static void gld${EMULATION_NAME}_read_file PARAMS ((const char *, boolean)); static void gld${EMULATION_NAME}_free PARAMS ((PTR)); @@ -68,7 +70,9 @@ static char *gld${EMULATION_NAME}_get_script PARAMS ((int *isfile)); static boolean gld${EMULATION_NAME}_unrecognized_file PARAMS ((lang_input_statement_type *)); static void gld${EMULATION_NAME}_create_output_section_statements - PARAMS((void)); + PARAMS ((void)); +static void gld${EMULATION_NAME}_set_output_arch PARAMS ((void)); + static int is_syscall PARAMS ((char *, unsigned int *)); static int change_symbol_mode PARAMS ((char *)); @@ -132,7 +136,7 @@ static unsigned int syscall_mask = 0x77; static lang_input_statement_type *initfini_file; /* Whether to do run time linking */ -static boolean rtld; +static int rtld; /* Explicit command line library path, -blibpath */ static char *command_line_blibpath = NULL; @@ -142,17 +146,7 @@ static char *command_line_blibpath = NULL; static void gld${EMULATION_NAME}_before_parse () { -#ifndef TARGET_ /* I.e., if not generic. */ - const bfd_arch_info_type *arch = bfd_scan_arch ("${OUTPUT_ARCH}"); - if (arch) - { - ldfile_output_architecture = arch->arch; - ldfile_output_machine = arch->mach; - ldfile_output_machine_name = arch->printable_name; - } - else - ldfile_output_architecture = bfd_arch_${ARCH}; -#endif /* not TARGET_ */ + config.has_shared = true; /* The link_info.[init|fini]_functions are initialized in ld/lexsup.c. @@ -687,7 +681,8 @@ gld${EMULATION_NAME}_before_allocation () if (!bfd_xcoff_size_dynamic_sections (output_bfd, &link_info, libpath, entry_symbol, file_align, maxstack, maxdata, gc && !unix_ld ? true : false, - modtype, textro ? true : false, unix_ld, special_sections, rtld)) + modtype, textro ? true : false, unix_ld, special_sections, + rtld ? true : false)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); /* Look through the special sections, and put them in the right @@ -806,7 +801,7 @@ gld${EMULATION_NAME}_before_allocation () } static char * -choose_target (argc, argv) +gld${EMULATION_NAME}_choose_target (argc, argv) int argc; char **argv; { @@ -1304,7 +1299,7 @@ fi cat >>e${EMULATION_NAME}.c <the_bfd, bfd_archive))) { einfo (_("%P: skipping incompatible %s when searching for %s\n"), attempt, entry->local_sym_name); diff --git a/ld/ldfile.h b/ld/ldfile.h index ce822e7dee7..777932591a4 100644 --- a/ld/ldfile.h +++ b/ld/ldfile.h @@ -1,5 +1,5 @@ /* ldfile.h - - Copyright 1991, 1992, 1993, 1994, 1995, 2000 + Copyright 1991, 1992, 1993, 1994, 1995, 2000, 2002 Free Software Foundation, Inc. This file is part of GLD, the Gnu Linker. -- 2.30.2