diff options
-rw-r--r-- | bfd/elf32-hppa.c | 989 |
1 files changed, 559 insertions, 430 deletions
diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 99801bd..268773e 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -1655,21 +1655,23 @@ elf_hppa_reloc_type_lookup (arch, code) void DEFUN (elf_hppa_tc_symbol, (abfd, symbolP, sym_idx), bfd * abfd AND - elf32_symbol_type * symbolP AND + elf_symbol_type * symbolP AND int sym_idx) { symext_chainS *symextP; unsigned int arg_reloc; + /* Only functions can have argument relocations. */ if (!(symbolP->symbol.flags & BSF_FUNCTION)) return; - if (!((symbolP->symbol.flags & BSF_EXPORT) || - (symbolP->symbol.flags & BSF_GLOBAL))) - return; - arg_reloc = symbolP->tc_data.hppa_arg_reloc; + /* If there are no argument relocation bits, then no relocation is + necessary. Do not add this to the symextn section. */ + if (arg_reloc == 0) + return; + symextP = (symext_chainS *) bfd_alloc (abfd, sizeof (symext_chainS) * 2); symextP[0].entry = ELF32_HPPA_SX_WORD (HPPA_SXT_SYMNDX, sym_idx); @@ -1800,7 +1802,7 @@ elf32_hppa_get_sym_extn (abfd, sym, type) break; case HPPA_SXT_ARG_RELOC: { - elf32_symbol_type *esymP = (elf32_symbol_type *) sym; + elf_symbol_type *esymP = (elf_symbol_type *) sym; retval = (symext_entryS) esymP->tc_data.hppa_arg_reloc; break; @@ -1812,96 +1814,150 @@ elf32_hppa_get_sym_extn (abfd, sym, type) return retval; } - -typedef struct Elf32_hppa_Stub_description_struct +typedef struct elf32_hppa_stub_name_list_struct +{ + /* name of this stub */ + asymbol *sym; + /* stub description for this stub */ + struct elf32_hppa_stub_description_struct *stub_desc; + /* pointer into stub contents */ + int *stub_secp; + /* size of this stub */ + unsigned size; + /* next stub name entry */ + struct elf32_hppa_stub_name_list_struct *next; +} elf32_hppa_stub_name_list; + +typedef struct elf32_hppa_stub_description_struct { - bfd *this_bfd; /* bfd to which this stub */ - /* applies */ + struct elf32_hppa_stub_description_struct *next; + bfd *this_bfd; /* bfd to which this stub applies */ asection *stub_sec; /* stub section for this bfd */ - unsigned relocs_allocated_cnt; /* count of relocations for this stub section */ + unsigned relocs_allocated_cnt; /* count of relocations for this stub section */ unsigned real_size; unsigned allocated_size; int *stub_secp; /* pointer to the next available location in the buffer */ char *stub_contents; /* contents of the stubs for this bfd */ + elf32_hppa_stub_name_list *stub_listP; } +elf32_hppa_stub_description; -Elf32_hppa_Stub_description; - -typedef struct Elf32_hppa_Stub_list_struct - { - Elf32_hppa_Stub_description *stub; - struct Elf32_hppa_Stub_list_struct *next; - } Elf32_hppa_Stub_list; - -static Elf32_hppa_Stub_list *elf_hppa_stub_rootP; +static elf32_hppa_stub_description *elf_hppa_stub_rootP; /* Locate the stub section information for the given bfd. */ -static Elf32_hppa_Stub_description * +static elf32_hppa_stub_description * find_stubs (abfd, stub_sec) bfd *abfd; asection *stub_sec; { - Elf32_hppa_Stub_list *stubP; + elf32_hppa_stub_description *stubP; for (stubP = elf_hppa_stub_rootP; stubP; stubP = stubP->next) { - if (stubP->stub->this_bfd == abfd - && stubP->stub->stub_sec == stub_sec) - return stubP->stub; + if (stubP->this_bfd == abfd + && stubP->stub_sec == stub_sec) + return stubP; } - return (Elf32_hppa_Stub_description *) NULL; + return (elf32_hppa_stub_description *) NULL; } -static Elf32_hppa_Stub_description * +static elf32_hppa_stub_description * new_stub (abfd, stub_sec) bfd *abfd; asection *stub_sec; { - Elf32_hppa_Stub_description *stub = find_stubs (abfd, stub_sec); + elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec); if (stub) return stub; - stub = (Elf32_hppa_Stub_description *) bfd_zalloc (abfd, sizeof (Elf32_hppa_Stub_description)); - stub->this_bfd = abfd; - stub->stub_sec = stub_sec; - stub->real_size = 0; - stub->allocated_size = 0; - stub->stub_contents = NULL; - stub->stub_secp = NULL; + stub = (elf32_hppa_stub_description *) bfd_zalloc (abfd, sizeof (elf32_hppa_stub_description)); + if (stub) + { + stub->this_bfd = abfd; + stub->stub_sec = stub_sec; + stub->real_size = 0; + stub->allocated_size = 0; + stub->stub_contents = NULL; + stub->stub_secp = NULL; + + stub->next = elf_hppa_stub_rootP; + elf_hppa_stub_rootP = stub; + } + else + { + bfd_error = no_memory; + bfd_perror ("new_stub"); + } return stub; } -static void -add_stub (stub) - Elf32_hppa_Stub_description *stub; +/* Locate the stub by the given name. */ +static elf32_hppa_stub_name_list * +find_stub_by_name (abfd, stub_sec, name) + bfd *abfd; + asection *stub_sec; + char *name; +{ + elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec); + + if (stub) + { + elf32_hppa_stub_name_list *name_listP; + + for (name_listP = stub->stub_listP; name_listP; name_listP = name_listP->next) + { + if (!strcmp (name_listP->sym->name, name)) + return name_listP; + } + } + + return 0; +} + +/* Locate the stub by the given name. */ +static elf32_hppa_stub_name_list * +add_stub_by_name(abfd, stub_sec, sym) + bfd *abfd; + asection *stub_sec; + asymbol *sym; { - Elf32_hppa_Stub_list *new_entry; + elf32_hppa_stub_description *stub = find_stubs (abfd, stub_sec); + elf32_hppa_stub_name_list *stub_entry; - new_entry = (Elf32_hppa_Stub_list *) bfd_zalloc (stub->this_bfd, sizeof (Elf32_hppa_Stub_list)); + if (!stub) + stub = new_stub(abfd, stub_sec); - if (new_entry) + if (stub) { - new_entry->stub = stub; + stub_entry = (elf32_hppa_stub_name_list *) + bfd_zalloc (abfd, sizeof (elf32_hppa_stub_name_list)); - if (elf_hppa_stub_rootP) + if (stub_entry) { - new_entry->next = elf_hppa_stub_rootP; - elf_hppa_stub_rootP = new_entry; + stub_entry->size = 0; + stub_entry->sym = sym; + stub_entry->stub_desc = stub; + /* First byte of this stub is the pointer to + the next available location in the stub buffer. */ + stub_entry->stub_secp = stub->stub_secp; + if (stub->stub_listP) + stub_entry->next = stub->stub_listP; + else + stub_entry->next = NULL; + stub->stub_listP = stub_entry; + return stub_entry; } else { - new_entry->next = (Elf32_hppa_Stub_list *) NULL; - elf_hppa_stub_rootP = new_entry; + bfd_error = no_memory; + bfd_perror("add_stub_by_name"); } } - else - { - bfd_error = no_memory; - bfd_perror ("add_stub"); - } + + return (elf32_hppa_stub_name_list *)NULL; } #define ARGUMENTS 0 @@ -1962,19 +2018,19 @@ static CONST char mismatches[6][6] = }; static CONST char retval_mismatches[6][6] = -{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU CALLEE DBL01 CALLEE DBL23 */ +{ /* CALLEE NONE CALLEE GR CALLEE FR CALLEE FU CALLEE DBL01 CALLEE DBL23 */ /* CALLER NONE */ {NO_ARG_RELOC, NO_ARG_RELOC, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, NO_ARG_RELOC}, /* CALLER GR */ - {NO_ARG_RELOC, NO_ARG_RELOC, R_TO_FR, ARG_RELOC_ERR, R01_TO_FR, ARG_RELOC_ERR}, + {NO_ARG_RELOC, NO_ARG_RELOC, FR_TO_R, ARG_RELOC_ERR, FR_TO_R01, ARG_RELOC_ERR}, /* CALLER FR */ - {NO_ARG_RELOC, FR_TO_R, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR}, + {NO_ARG_RELOC, R_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR}, /* CALLER FU */ {ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR, ARG_RELOC_ERR}, /* CALLER DBL01 */ - {NO_ARG_RELOC, FR_TO_R01, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR}, + {NO_ARG_RELOC, R01_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, NO_ARG_RELOC, ARG_RELOC_ERR}, /* CALLER DBL23 */ - {NO_ARG_RELOC, FR_TO_R23, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC}, + {NO_ARG_RELOC, R23_TO_FR, NO_ARG_RELOC, ARG_RELOC_ERR, ARG_RELOC_ERR, NO_ARG_RELOC}, }; static int @@ -1996,13 +2052,16 @@ type_of_mismatch (caller_bits, callee_bits, type) #define EXTRACT_ARBITS(ar,which) ((ar) >> (8-(which*2))) & 3 -#define NEW_INSTRUCTION(desc,insn) \ - *((desc)->stub_secp)++ = (insn); \ - (desc)->real_size += sizeof(int); \ - bfd_set_section_size((desc)->this_bfd,(desc)->stub_sec,(desc)->real_size); +#define NEW_INSTRUCTION(entry,insn) \ + *((entry)->stub_desc->stub_secp)++ = (insn); \ + (entry)->stub_desc->real_size += sizeof(int); \ + (entry)->size += sizeof(int); \ + bfd_set_section_size((entry)->stub_desc->this_bfd, \ + (entry)->stub_desc->stub_sec, \ + (entry)->stub_desc->real_size); -#define CURRENT_STUB_OFFSET(desc) \ - ((int)(desc)->stub_secp - (int)(desc)->stub_contents - 4) +#define CURRENT_STUB_OFFSET(entry) \ + ((int)(entry)->stub_desc->stub_secp - (int)(entry)->stub_desc->stub_contents - 4) static boolean stubs_finished = false; @@ -2011,7 +2070,7 @@ hppa_elf_stub_finish (output_bfd) bfd *output_bfd; { extern bfd_error_vector_type bfd_error_vector; - Elf32_hppa_Stub_list *stub_list = elf_hppa_stub_rootP; + elf32_hppa_stub_description *stub_list = elf_hppa_stub_rootP; /* All the stubs have been built. Finish up building */ /* stub section. Apply relocations to the section. */ @@ -2020,14 +2079,14 @@ hppa_elf_stub_finish (output_bfd) for (; stub_list; stub_list = stub_list->next) { - if (stub_list->stub->real_size) + if (stub_list->real_size) { - bfd *stub_bfd = stub_list->stub->this_bfd; + bfd *stub_bfd = stub_list->this_bfd; asection *stub_sec = bfd_get_section_by_name (stub_bfd, ".hppa_linker_stubs"); bfd_size_type reloc_size; arelent **reloc_vector; - BFD_ASSERT (stub_sec == stub_list->stub->stub_sec); + BFD_ASSERT (stub_sec == stub_list->stub_sec); reloc_size = bfd_get_reloc_upper_bound (stub_bfd, stub_sec); reloc_vector = (arelent **) alloca (reloc_size); @@ -2050,7 +2109,7 @@ hppa_elf_stub_finish (output_bfd) bfd_reloc_status_type r = bfd_perform_relocation (stub_bfd, *parent, - stub_list->stub->stub_contents, + stub_list->stub_contents, stub_sec, 0); @@ -2078,9 +2137,9 @@ hppa_elf_stub_finish (output_bfd) bfd_set_section_contents (output_bfd, stub_sec, - stub_list->stub->stub_contents, + stub_list->stub_contents, 0, - stub_list->stub->real_size); + stub_list->real_size); free (reloc_vector); } @@ -2093,7 +2152,7 @@ hppa_elf_stub_branch_reloc (stub_desc, /* the bfd */ output_bfd, /* the output bfd */ target_sym, /* the target symbol */ offset) /* the offset within the stub buffer (pre-calculated) */ - Elf32_hppa_Stub_description *stub_desc; + elf32_hppa_stub_description *stub_desc; bfd *output_bfd; asymbol *target_sym; int offset; @@ -2141,7 +2200,7 @@ hppa_elf_stub_reloc (stub_desc, /* the bfd */ target_sym, /* the target symbol */ offset, /* the offset within the stub buffer (pre-calculated) */ type) -Elf32_hppa_Stub_description *stub_desc; +elf32_hppa_stub_description *stub_desc; bfd *output_bfd; asymbol *target_sym; int offset; @@ -2196,12 +2255,13 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types) int stub_types[5]; { asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs"); - Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec); + elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec); asymbol *stub_sym = NULL; asymbol *target_sym = reloc_entry->sym_ptr_ptr[0]; asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text"); int i; char stub_sym_name[128]; + elf32_hppa_stub_name_list *stub_entry; if (!stub_sec) { @@ -2214,16 +2274,12 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types) stub_sec->output_offset = 0; bfd_set_section_alignment (abfd, stub_sec, 2); stub_desc = new_stub (abfd, stub_sec); - add_stub (stub_desc); } /* make sure we have a stub descriptor structure */ if (!stub_desc) - { - stub_desc = new_stub (abfd, stub_sec); - add_stub (stub_desc); - } + stub_desc = new_stub (abfd, stub_sec); /* allocate some space to write the stub */ @@ -2241,204 +2297,221 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types) stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size); - /* create a symbol to point to this stub */ - stub_sym = bfd_make_empty_symbol (abfd); sprintf (stub_sym_name, - "_stub_%s_%02d_%02d_%02d_%02d_%02d\000", + "_stub_%s_%02d_%02d_%02d_%02d_%02d", reloc_entry->sym_ptr_ptr[0]->name, - stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]); - stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1); - strcpy ((char *) stub_sym->name, stub_sym_name); - stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; - stub_sym->section = stub_sec; - stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; + stub_types[0], stub_types[1], stub_types[2], stub_types[3], stub_types[4]); + stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name); - /* redirect the original relocation from the old symbol (a function) */ - /* to the stub (the stub calls the function). */ - /* XXX do we need to change the relocation type? */ - reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); - reloc_entry->sym_ptr_ptr[0] = stub_sym; + if (stub_entry) + { + stub_sym = stub_entry->sym; + /* redirect the original relocation from the old symbol (a function) */ + /* to the stub (the stub calls the function). */ + /* XXX do we need to change the relocation type? */ + reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + reloc_entry->sym_ptr_ptr[0] = stub_sym; + } + else + { + /* Stub does not already exist. Create a new stub. */ + /* Create a new symbol to point to this stub */ + stub_sym = bfd_make_empty_symbol (abfd); + stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1); + strcpy ((char *) stub_sym->name, stub_sym_name); + stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; + stub_sym->section = stub_sec; + stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; + stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym); + + /* redirect the original relocation from the old symbol (a function) */ + /* to the stub (the stub calls the function). */ + /* XXX do we need to change the relocation type? */ + reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + reloc_entry->sym_ptr_ptr[0] = stub_sym; + + /* generate the beginning common section for all stubs */ + + NEW_INSTRUCTION (stub_entry, ADDI_8_SP); + + /* generate the code to move the arguments around */ + for (i = ARG0; i < ARG3; i++) + { + if (stub_types[i] != NO_ARG_RELOC) + { + /* A stub is needed */ + switch (stub_types[i]) + { + case R_TO_FR: + switch (i) + { + case ARG0: + NEW_INSTRUCTION (stub_entry, STWS_ARG0_M8SP); + NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG0); + break; + case ARG1: + NEW_INSTRUCTION (stub_entry, STWS_ARG1_M8SP); + NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG1); + break; + case ARG2: + NEW_INSTRUCTION (stub_entry, STWS_ARG2_M8SP); + NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG2); + break; + case ARG3: + NEW_INSTRUCTION (stub_entry, STWS_ARG3_M8SP); + NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FARG3); + break; + } + continue; + + case R01_TO_FR: + switch (i) + { + case ARG0: + NEW_INSTRUCTION(stub_entry, STWS_ARG0_M4SP); + NEW_INSTRUCTION(stub_entry, STWS_ARG1_M8SP); + NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG1); + break; + default: + AR_WARN(stub_types[i],i); + break; + } + continue; + + case R23_TO_FR: + switch (i) + { + case ARG2: + NEW_INSTRUCTION(stub_entry, STWS_ARG2_M4SP); + NEW_INSTRUCTION(stub_entry, STWS_ARG3_M8SP); + NEW_INSTRUCTION(stub_entry, FLDDS_M8SP_FARG3); + break; + default: + AR_WARN(stub_types[i],i); + break; + } + continue; + + case FR_TO_R: + switch (i) + { + case ARG0: + NEW_INSTRUCTION (stub_entry, FSTWS_FARG0_M8SP); + NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG0); + break; + case ARG1: + NEW_INSTRUCTION (stub_entry, FSTWS_FARG1_M8SP); + NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG1); + break; + case ARG2: + NEW_INSTRUCTION (stub_entry, FSTWS_FARG2_M8SP); + NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG2); + break; + case ARG3: + NEW_INSTRUCTION (stub_entry, FSTWS_FARG3_M8SP); + NEW_INSTRUCTION (stub_entry, LDWS_M4SP_ARG3); + break; + } + continue; + + case FR_TO_R01: + switch (i) + { + case ARG0: + NEW_INSTRUCTION(stub_entry, FSTDS_FARG1_M8SP); + NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG0); + NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG1); + break; + default: + AR_WARN(stub_types[i],i); + break; + } + continue; + + case FR_TO_R23: + switch (i) + { + case ARG2: + NEW_INSTRUCTION(stub_entry, FSTDS_FARG3_M8SP); + NEW_INSTRUCTION(stub_entry, LDWS_M4SP_ARG2); + NEW_INSTRUCTION(stub_entry, LDWS_M8SP_ARG3); + break; + default: + AR_WARN(stub_types[i],i); + break; + } + continue; + + } + } + } - /* generate the beginning common section for all stubs */ + NEW_INSTRUCTION (stub_entry, ADDI_M8_SP); - NEW_INSTRUCTION (stub_desc, ADDI_8_SP); + /* generate the branch to the target routine */ + NEW_INSTRUCTION (stub_entry, STW_RP_M8SP); /* First, save the return address */ - /* generate the code to move the arguments around */ - for (i = ARG0; i < ARG3; i++) - { + /* Branch to the target function. */ + /* (Make it a long call, so we do not */ + /* have to worry about generating a */ + /* long call stub.) */ + NEW_INSTRUCTION(stub_entry, LDIL_XXX_31); + hppa_elf_stub_reloc (stub_entry->stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_L21); + NEW_INSTRUCTION(stub_entry,BLE_XXX_0_31); + hppa_elf_stub_reloc (stub_entry->stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_ABS_CALL_R17); + NEW_INSTRUCTION(stub_entry,COPY_31_2); + + /* generate the code to move the return value around */ + + NEW_INSTRUCTION (stub_entry, LDW_M8SP_RP); /* restore return address */ + + i = RETVAL; if (stub_types[i] != NO_ARG_RELOC) { /* A stub is needed */ switch (stub_types[i]) { case R_TO_FR: - switch (i) - { - case ARG0: - NEW_INSTRUCTION (stub_desc, STWS_ARG0_M8SP); - NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG0); - break; - case ARG1: - NEW_INSTRUCTION (stub_desc, STWS_ARG1_M8SP); - NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG1); - break; - case ARG2: - NEW_INSTRUCTION (stub_desc, STWS_ARG2_M8SP); - NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG2); - break; - case ARG3: - NEW_INSTRUCTION (stub_desc, STWS_ARG3_M8SP); - NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FARG3); - break; - } - continue; - - case R01_TO_FR: - switch (i) - { - case ARG0: - NEW_INSTRUCTION(stub_desc, STWS_ARG0_M4SP); - NEW_INSTRUCTION(stub_desc, STWS_ARG1_M8SP); - NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG1); - break; - default: - AR_WARN(stub_types[i],i); - break; - } - continue; - - case R23_TO_FR: - switch (i) - { - case ARG2: - NEW_INSTRUCTION(stub_desc, STWS_ARG2_M4SP); - NEW_INSTRUCTION(stub_desc, STWS_ARG3_M8SP); - NEW_INSTRUCTION(stub_desc, FLDDS_M8SP_FARG3); - break; - default: - AR_WARN(stub_types[i],i); - break; - } - continue; - + NEW_INSTRUCTION (stub_entry, STWS_RET0_M8SP); + NEW_INSTRUCTION (stub_entry, FLDWS_M8SP_FRET0); + break; + case FR_TO_R: - switch (i) - { - case ARG0: - NEW_INSTRUCTION (stub_desc, FSTWS_FARG0_M8SP); - NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG0); - break; - case ARG1: - NEW_INSTRUCTION (stub_desc, FSTWS_FARG1_M8SP); - NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG1); - break; - case ARG2: - NEW_INSTRUCTION (stub_desc, FSTWS_FARG2_M8SP); - NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG2); - break; - case ARG3: - NEW_INSTRUCTION (stub_desc, FSTWS_FARG3_M8SP); - NEW_INSTRUCTION (stub_desc, LDWS_M4SP_ARG3); - break; - } - continue; - - case FR_TO_R01: - switch (i) - { - case ARG0: - NEW_INSTRUCTION(stub_desc, FSTDS_FARG1_M8SP); - NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG0); - NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG1); - break; - default: - AR_WARN(stub_types[i],i); - break; - } - continue; - - case FR_TO_R23: - switch (i) - { - case ARG2: - NEW_INSTRUCTION(stub_desc, FSTDS_FARG3_M8SP); - NEW_INSTRUCTION(stub_desc, LDWS_M4SP_ARG2); - NEW_INSTRUCTION(stub_desc, LDWS_M8SP_ARG3); - break; - default: - AR_WARN(stub_types[i],i); - break; + NEW_INSTRUCTION (stub_entry, FSTWS_FRET0_M8SP); + NEW_INSTRUCTION (stub_entry, LDWS_M4SP_RET0); + break; } - continue; - - } - } - } - - NEW_INSTRUCTION (stub_desc, ADDI_M8_SP); - - /* generate the branch to the target routine */ - NEW_INSTRUCTION (stub_desc, STW_RP_M8SP); /* First, save the return address */ - - /* Branch to the target function. */ - /* (Make it a long call, so we do not */ - /* have to worry about generating a */ - /* long call stub.) */ - NEW_INSTRUCTION(stub_desc, LDIL_XXX_31); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_L21); - NEW_INSTRUCTION(stub_desc,BLE_XXX_0_31); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_ABS_CALL_R17); - NEW_INSTRUCTION(stub_desc,COPY_31_2); - - /* generate the code to move the return value around */ - i = RETVAL; - if (stub_types[i] != NO_ARG_RELOC) - { - /* A stub is needed */ - switch (stub_types[i]) - { - case R_TO_FR: - NEW_INSTRUCTION (stub_desc, STWS_RET0_M8SP); - NEW_INSTRUCTION (stub_desc, FLDWS_M8SP_FRET0); - break; - - case FR_TO_R: - NEW_INSTRUCTION (stub_desc, FSTWS_FRET0_M8SP); - NEW_INSTRUCTION (stub_desc, LDWS_M4SP_RET0); - break; } + + /* generate the ending common section for all stubs */ + + /* XXX: can we assume this is a save return? */ + NEW_INSTRUCTION (stub_entry, BV_N_0RP); } - /* generate the ending common section for all stubs */ - - NEW_INSTRUCTION (stub_desc, LDW_M8SP_RP); /* restore return address */ - - /* XXX: can we assume this is a save return? */ - NEW_INSTRUCTION (stub_desc, BV_N_0RP); - return stub_sym; } int -hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types) +hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar) bfd *abfd; arelent *reloc_entry; int stub_types[5]; + symext_entryS caller_ar; { /* If the symbol is still undefined, there is */ /* no way to know if a stub is required. */ if (reloc_entry->sym_ptr_ptr[0] && reloc_entry->sym_ptr_ptr[0]->section != &bfd_und_section) { - symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (reloc_entry->addend); symext_entryS callee_ar = elf32_hppa_get_sym_extn (abfd, reloc_entry->sym_ptr_ptr[0], HPPA_SXT_ARG_RELOC); @@ -2519,6 +2592,8 @@ hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types) || stub_types[4]) { #ifdef DETECT_STUBS + int i; + fprintf (stderr, "Stub needed for %s @ %s+0x%x: callee/caller ar=0x%x/0x%x ", reloc_entry->sym_ptr_ptr[0]->name, abfd->filename, reloc_entry->address, @@ -2552,13 +2627,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) unsigned *data; { asection *stub_sec = bfd_get_section_by_name (abfd, ".hppa_linker_stubs"); - Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, stub_sec); + elf32_hppa_stub_description *stub_desc = find_stubs (abfd, stub_sec); asymbol *stub_sym = NULL; asymbol *target_sym = reloc_entry->sym_ptr_ptr[0]; - asymbol *return_sym = NULL; asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text"); char stub_sym_name[128]; int milli = false; + elf32_hppa_stub_name_list *stub_entry; if (!stub_sec) { @@ -2625,14 +2700,10 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) bfd_set_section_alignment (abfd, stub_sec, 2); stub_desc = new_stub (abfd, stub_sec); - add_stub (stub_desc); } if (!stub_desc) - { - stub_desc = new_stub (abfd, stub_sec); - add_stub (stub_desc); - } + stub_desc = new_stub (abfd, stub_sec); /* allocate some space to write the stub */ @@ -2650,90 +2721,97 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) stub_desc->stub_secp = (int *) (stub_desc->stub_contents + stub_desc->real_size); - /* create a symbol to point to this stub */ - stub_sym = bfd_make_empty_symbol (abfd); - sprintf (stub_sym_name, - "_lb_stub_%s\000", reloc_entry->sym_ptr_ptr[0]->name); - stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1); - strcpy ((char *) stub_sym->name, stub_sym_name); - stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; - stub_sym->section = stub_sec; - stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; - - /* create a symbol to point to the return location */ - return_sym = bfd_make_empty_symbol (abfd); sprintf (stub_sym_name, - "_lb_rtn_%s\000", reloc_entry->sym_ptr_ptr[0]->name); - return_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1); - strcpy ((char *) return_sym->name, stub_sym_name); - return_sym->value = reloc_entry->address + 8; - return_sym->section = stub_sec; - return_sym->flags = BSF_LOCAL | BSF_FUNCTION; - - /* redirect the original relocation from the old symbol (a function) */ - /* to the stub (the stub calls the function). */ - /* XXX do we need to change the relocation type? */ - reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); - reloc_entry->sym_ptr_ptr[0] = stub_sym; - reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17); - - /* Build the stub */ - - /* A millicode call? */ - /* If so, the return address comes in on r31 rather than r2 (rp) so a */ - /* slightly different code sequence is needed. */ - if ( ((*data & 0x03e00000) >> 21) == 31 ) - milli = true; - - /* 1. initialization for the call. */ - - NEW_INSTRUCTION(stub_desc, LDSID_31_RP); - NEW_INSTRUCTION(stub_desc, MTSP_RP_SR0); - if ( !milli ) - { - NEW_INSTRUCTION(stub_desc, COPY_31_2); + "_lb_stub_%s", reloc_entry->sym_ptr_ptr[0]->name); + stub_entry = find_stub_by_name(abfd, stub_sec, stub_sym_name); - NEW_INSTRUCTION(stub_desc, LDIL_XXX_31); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_L21); - - /* 2. Make the call. */ - - NEW_INSTRUCTION(stub_desc,BE_N_XXX_0_31); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_ABS_CALL_R17); - /* 3. Branch back to the original location. */ - /* (accomplished with the COPY_31_2 instruction) */ + if (stub_entry) + { + stub_sym = stub_entry->sym; + /* redirect the original relocation from the old symbol (a function) */ + /* to the stub (the stub calls the function). */ + /* XXX do we need to change the relocation type? */ + reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + reloc_entry->sym_ptr_ptr[0] = stub_sym; + reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17); } else { - NEW_INSTRUCTION(stub_desc, STW_31_M24SP); - NEW_INSTRUCTION(stub_desc, LDIL_XXX_RP); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_L21); - - /* 2. Make the call. */ - - NEW_INSTRUCTION(stub_desc,BLE_XXX_0_RP); - hppa_elf_stub_reloc (stub_desc, - abfd, /* the output bfd */ - target_sym, /* the target symbol */ - CURRENT_STUB_OFFSET(stub_desc), /* offset in stub buffer */ - R_HPPA_ABS_CALL_R17); - NEW_INSTRUCTION(stub_desc,COPY_31_2); - - /* 3. Branch back to the original location. */ - NEW_INSTRUCTION(stub_desc, LDW_M24SP_RP); - NEW_INSTRUCTION(stub_desc, BV_N_0RP); + /* Stub does not already exist. Create a new stub. */ + /* create a symbol to point to this stub */ + stub_sym = bfd_make_empty_symbol (abfd); + stub_sym->name = bfd_zalloc (abfd, strlen (stub_sym_name) + 1); + strcpy ((char *) stub_sym->name, stub_sym_name); + stub_sym->value = (int) stub_desc->stub_secp - (int) stub_desc->stub_contents; + stub_sym->section = stub_sec; + stub_sym->flags = BSF_LOCAL | BSF_FUNCTION; + stub_entry = add_stub_by_name(abfd, stub_sec, stub_sym); + + /* redirect the original relocation from the old symbol (a function) */ + /* to the stub (the stub calls the function). */ + /* XXX do we need to change the relocation type? */ + reloc_entry->sym_ptr_ptr = (asymbol **) bfd_zalloc (stub_desc->this_bfd, sizeof (asymbol *)); + reloc_entry->sym_ptr_ptr[0] = stub_sym; + reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17); + + /* Build the stub */ + + /* A millicode call? */ + /* If so, the return address comes in on r31 rather than r2 (rp) so a */ + /* slightly different code sequence is needed. */ + if ( ((*data & 0x03e00000) >> 21) == 31 ) + milli = true; + + /* 1. initialization for the call. */ + + NEW_INSTRUCTION(stub_entry, LDSID_31_RP); + NEW_INSTRUCTION(stub_entry, MTSP_RP_SR0); + if ( !milli ) + { + NEW_INSTRUCTION(stub_entry, COPY_31_2); + + NEW_INSTRUCTION(stub_entry, LDIL_XXX_31); + hppa_elf_stub_reloc (stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_L21); + + /* 2. Make the call. */ + + NEW_INSTRUCTION(stub_entry,BE_N_XXX_0_31); + hppa_elf_stub_reloc (stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_ABS_CALL_R17); + /* 3. Branch back to the original location. */ + /* (accomplished with the COPY_31_2 instruction) */ + } + else + { + NEW_INSTRUCTION(stub_entry, STW_31_M24SP); + NEW_INSTRUCTION(stub_entry, LDIL_XXX_RP); + hppa_elf_stub_reloc (stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_L21); + + /* 2. Make the call. */ + + NEW_INSTRUCTION(stub_entry,BLE_XXX_0_RP); + hppa_elf_stub_reloc (stub_desc, + abfd, /* the output bfd */ + target_sym, /* the target symbol */ + CURRENT_STUB_OFFSET(stub_entry), /* offset in stub buffer */ + R_HPPA_ABS_CALL_R17); + NEW_INSTRUCTION(stub_entry,COPY_31_2); + + /* 3. Branch back to the original location. */ + NEW_INSTRUCTION(stub_entry, LDW_M24SP_RP); + NEW_INSTRUCTION(stub_entry, BV_N_0RP); + } } return stub_sym; @@ -2809,39 +2887,42 @@ hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_d case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ - case R_HPPA_PCREL_CALL_L21:/* L (Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_R11:/* R (Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_R14:/* R (Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_R17:/* R (Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ - if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types)) - { - /* generate a stub */ - return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, - stub_types); - } - if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry, symbol,*(unsigned *)hit_data)) - { - /* generate a stub */ - return hppa_elf_build_long_branch_stub (abfd, output_bfd, - reloc_entry, symbol, - (unsigned *)hit_data); - } + case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ + { + symext_entryS caller_ar = (symext_entryS) ELF32_HGPPA_R_ARG_RELOC (reloc_entry->addend); + if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar)) + { + /* generate a stub */ + return hppa_elf_build_arg_reloc_stub (abfd, output_bfd, + reloc_entry, stub_types); + } + if (hppa_elf_long_branch_needed_p (abfd, input_section, reloc_entry, + symbol, *(unsigned *)hit_data)) + { + /* generate a stub */ + return hppa_elf_build_long_branch_stub (abfd, output_bfd, + reloc_entry, symbol, + (unsigned *)hit_data); + } + } break; default: break; - } return reloc_entry->sym_ptr_ptr[0]; } @@ -2863,10 +2944,10 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_ int new_cnt = 0; int new_max = 0; - /* Relocations are in different places depending on whether this is */ - /* an output section or an input section. Also, the relocations are */ - /* in different forms. Sigh. */ - /* Luckily, we have bfd_canonicalize_reloc() to straighten this out for us. */ + /* Relocations are in different places depending on whether this is + an output section or an input section. Also, the relocations are + in different forms. Sigh. Luckily, we have + bfd_canonicalize_reloc() to straighten this out for us. */ /* if ( asec->orelocation || asec->relocation ) { */ if (asec->reloc_count > 0) @@ -2889,83 +2970,129 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_ switch (rle->howto->type) { - case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */ - case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */ - case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */ - case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */ - case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */ - case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */ - case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */ - case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */ - case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */ - case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */ - case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */ - case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */ - case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */ - case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */ - case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */ - case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */ - case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */ - case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */ - - case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */ - case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ - case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ - case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ - case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ - case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ - case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ - case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ - case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ - if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types)) - { - /* generate a stub */ - /* keep track of the new symbol */ + case R_HPPA_ABS_CALL_11: /* Symbol + Addend 11 */ + case R_HPPA_ABS_CALL_14: /* Symbol + Addend 14 */ + case R_HPPA_ABS_CALL_17: /* Symbol + Addend 17 */ + case R_HPPA_ABS_CALL_L21: /* L (Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_R11: /* R (Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_R14: /* R (Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_R17: /* R (Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LS21: /* LS(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RS11: /* RS(Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_RS14: /* RS(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RS17: /* RS(Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LD21: /* LD(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RD11: /* RD(Symbol, Addend) 11 */ + case R_HPPA_ABS_CALL_RD14: /* RD(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RD17: /* RD(Symbol, Addend) 17 */ + case R_HPPA_ABS_CALL_LR21: /* LR(Symbol, Addend) 21 */ + case R_HPPA_ABS_CALL_RR14: /* RR(Symbol, Addend) 14 */ + case R_HPPA_ABS_CALL_RR17: /* RR(Symbol, Addend) 17 */ + + case R_HPPA_PCREL_CALL_11: /* Symbol - PC + Addend 11 */ + case R_HPPA_PCREL_CALL_14: /* Symbol - PC + Addend 14 */ + case R_HPPA_PCREL_CALL_17: /* Symbol - PC + Addend 17 */ + case R_HPPA_PCREL_CALL_12: /* Symbol - PC + Addend 12 */ + case R_HPPA_PCREL_CALL_L21: /* L (Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_R11: /* R (Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_R14: /* R (Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_R17: /* R (Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LS21: /* LS(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RS11: /* RS(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RS14: /* RS(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RS17: /* RS(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LD21: /* LD(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RD11: /* RD(Symbol - PC, Addend) 11 */ + case R_HPPA_PCREL_CALL_RD14: /* RD(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RD17: /* RD(Symbol - PC, Addend) 17 */ + case R_HPPA_PCREL_CALL_LR21: /* LR(Symbol - PC, Addend) 21 */ + case R_HPPA_PCREL_CALL_RR14: /* RR(Symbol - PC, Addend) 14 */ + case R_HPPA_PCREL_CALL_RR17: /* RR(Symbol - PC, Addend) 17 */ + { + symext_entryS caller_ar = (symext_entryS) ELF32_HPPA_R_ARG_RELOC (rle->addend); + if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types, + caller_ar)) + { + /* generate a stub */ + /* keep track of the new symbol */ + asymbol *r; - asymbol *r; + if (new_cnt == new_max) + { + new_max += STUB_SYM_BUFFER_INC; + new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol)); + } + r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd, + rle, stub_types); + new_syms[new_cnt++] = *r; + } + /* We need to retrieve the section contents to check for + plabel stubs. */ + { + unsigned insn; - if (new_cnt == new_max) + bfd_get_section_contents (abfd, asec, &insn, rle->address, + sizeof(insn)); + if (hppa_elf_long_branch_needed_p (abfd, asec, rle, + rle->sym_ptr_ptr[0], + insn)) { - new_max += STUB_SYM_BUFFER_INC; - new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol)); + /* generate a stub */ + /* keep track of the new symbol */ + asymbol *r; + + if (new_cnt == new_max) + { + new_max += STUB_SYM_BUFFER_INC; + new_syms = (asymbol *) realloc (new_syms, (new_max * sizeof (asymbol))); + } + r = hppa_elf_build_long_branch_stub (stub_bfd, + output_bfd, + rle, + rle->sym_ptr_ptr[0], + &insn); + new_syms[new_cnt++] = *r; } - r = hppa_elf_build_arg_reloc_stub (stub_bfd, output_bfd, rle, - stub_types); - new_syms[new_cnt++] = *r; } - /* We need to retrieve the section contents to check for */ - /* long branch stubs. */ + } + break; + + /* Plabels are designed to allow code pointers to be + passed between spaces. These relocations correspond + to the P%, LP%, and RP% field selectors. */ + + case R_HPPA_PLABEL_32: /* F(Plabel(Symbol,Addend),0) 32 */ + case R_HPPA_PLABEL_11: /* F(Plabel(Symbol,Addend),0) 11 */ + case R_HPPA_PLABEL_14: /* F(Plabel(Symbol,Addend),0) 14 */ + case R_HPPA_PLABEL_L21: /* L(Plabel(Symbol,Addend),0) 21 */ + case R_HPPA_PLABEL_R11: /* R(Plabel(Symbol,Addend),0) 11 */ + case R_HPPA_PLABEL_R14: /* R(Plabel(Symbol,Addend),0) 14 */ + /* We need to retrieve the section contents to check for + long branch stubs. */ { - unsigned insn; + /* On a plabel relocation, assume the arguments of the + caller are set up in general registers. */ + /* 0x155 = ARGW0=CR,ARGW1=GR,ARGW2=GR,RETVAL=GR */ + symext_entryS caller_ar = (symext_entryS) 0x155; - bfd_get_section_contents(abfd, asec, &insn, rle->address, sizeof(insn)); - if (hppa_elf_long_branch_needed_p (abfd, asec, rle, rle->sym_ptr_ptr[0], insn)) + if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types, + caller_ar)) { - /* generate a stub */ + /* generate a plabel stub */ /* keep track of the new symbol */ - asymbol *r; if (new_cnt == new_max) { new_max += STUB_SYM_BUFFER_INC; - new_syms = (asymbol *) realloc (new_syms, new_max * sizeof (asymbol)); + new_syms = (asymbol *) realloc (new_syms, + (new_max + * sizeof (asymbol))); } - r = hppa_elf_build_long_branch_stub (stub_bfd, - output_bfd, - rle, - rle->sym_ptr_ptr[0], - &insn); + r = hppa_elf_build_arg_reloc_stub (stub_bfd, + output_bfd, + rle, + stub_types); new_syms[new_cnt++] = *r; } } @@ -3026,7 +3153,7 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count), /* section contents in memory rather than on disk. */ if (strcmp (section->name, ".hppa_linker_stubs") == 0) { - Elf32_hppa_Stub_description *stub_desc = find_stubs (abfd, section); + elf32_hppa_stub_description *stub_desc = find_stubs (abfd, section); if (count == 0) return true; @@ -3053,7 +3180,8 @@ DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count), return (true); } else - return bfd_generic_get_section_contents (abfd, section, location, offset, count); + return bfd_generic_get_section_contents (abfd, section, location, offset, + count); } static void @@ -3097,7 +3225,7 @@ static int elf32_hppa_symextn_map_size; static boolean DEFUN (elf32_hppa_backend_symbol_table_processing, (abfd, esyms,symcnt), bfd * abfd AND - elf32_symbol_type *esyms AND + elf_symbol_type *esyms AND int symcnt) { Elf32_Internal_Shdr *symextn_hdr = bfd_elf_find_section (abfd, SYMEXTN_SECTION_NAME); @@ -3340,5 +3468,6 @@ DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect), #define TARGET_BIG_SYM bfd_elf32_hppa_vec #define TARGET_BIG_NAME "elf32-hppa" #define ELF_ARCH bfd_arch_hppa +#define ELF_MAXPAGESIZE 0x1000 #include "elf32-target.h" |