From a36b6f1d05754890fe380571cff36c54fcc20065 Mon Sep 17 00:00:00 2001 From: Jeff Law Date: Tue, 14 Dec 1993 07:36:15 +0000 Subject: [PATCH] * elf32-hppa.c (hppa_elf_gen_reloc_type): Handle 'T' field selectors for PIC code. * som.c (hppa_som_gen_reloc_type): Handle 'T' field selectors. (som_write_fixups): Handle R_DLT_REL, R_FSEL, R_RSEL, R_LSEL relocations needed by PIC. --- bfd/ChangeLog | 9 ++++++ bfd/elf32-hppa.c | 95 +++++++++++++++++++++++++++++++++++++++++++++++++------- bfd/som.c | 46 ++++++++++++++++++++------- 3 files changed, 128 insertions(+), 22 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index c29f2fe..b045532 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,12 @@ +Mon Dec 13 23:34:48 1993 Jeffrey A. Law (law@snake.cs.utah.edu) + + * elf32-hppa.c (hppa_elf_gen_reloc_type): Handle 'T' field + selectors for PIC code. + + * som.c (hppa_som_gen_reloc_type): Handle 'T' field selectors. + (som_write_fixups): Handle R_DLT_REL, R_FSEL, R_RSEL, R_LSEL + relocations needed by PIC. + Tue Dec 7 15:47:51 1993 Stu Grossman (grossman at cygnus.com) * nlmcode.h: Fixes to avoid compiler warnings... diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index b677e4d..4f15c62 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -524,11 +524,15 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field) case e_rpsel: final_type = R_HPPA_PLABEL_R11; break; - case e_lpsel: case e_tsel: - case e_ltsel: + final_type = R_HPPA_DLT_11; + break; case e_rtsel: + final_type = R_HPPA_DLT_R11; + break; + case e_lpsel: + case e_ltsel: case e_lsel: case e_lrsel: case e_lssel: @@ -564,10 +568,15 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field) case e_rpsel: final_type = R_HPPA_PLABEL_R14; break; - case e_lpsel: case e_tsel: - case e_ltsel: + final_type = R_HPPA_DLT_14; + break; case e_rtsel: + final_type = R_HPPA_DLT_R14; + break; + + case e_lpsel: + case e_ltsel: case e_fsel: case e_lsel: @@ -626,6 +635,9 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field) case e_lpsel: final_type = R_HPPA_PLABEL_L21; break; + case e_ltsel: + final_type = R_HPPA_PLABEL_L21; + break; case e_rsel: case e_rssel: case e_rdsel: @@ -646,6 +658,9 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field) case e_psel: final_type = R_HPPA_PLABEL_32; break; + case e_tsel: + final_type == R_HPPA_DLT_32; + break; default: UNDEFINED; final_type = base_type; @@ -1561,7 +1576,16 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd) jump after the call returns (GCC optimization). */ if (insn & 2) - insn = BLE_N_XXX_0_0; + { + insn = BLE_N_XXX_0_0; + bfd_put_32 (abfd, insn, hit_data); + r_type = R_HPPA_ABS_CALL_17; + r_pcrel = 0; + insn = hppa_elf_relocate_insn (abfd, input_section, insn, + addr, symbol_in, sym_value, + r_addend, r_type, r_format, + r_field, r_pcrel); + } else { unsigned long old_delay_slot_insn = bfd_get_32 (abfd, hit_data + 4); @@ -1584,16 +1608,29 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd) new_delay_slot_insn |= ((31 << 21) | (31 << 16)); bfd_put_32 (abfd, new_delay_slot_insn, hit_data + 4); insn = BLE_XXX_0_0; - bfd_put_32 (abfd, insn, hit_data); r_type = R_HPPA_ABS_CALL_17; r_pcrel = 0; insn = hppa_elf_relocate_insn (abfd, input_section, insn, addr, symbol_in, sym_value, r_addend, r_type, r_format, r_field, r_pcrel); - bfd_put_32 (abfd, insn, hit_data + 4); + bfd_put_32 (abfd, insn, hit_data); return bfd_reloc_ok; } + else if (rtn_reg == 31) + { + /* The return register is r31, so this is a millicode + call. Do not perform any instruction reordering. */ + insn = BLE_XXX_0_0; + r_type = R_HPPA_ABS_CALL_17; + r_pcrel = 0; + insn = hppa_elf_relocate_insn (abfd, input_section, insn, + addr, symbol_in, sym_value, + r_addend, r_type, r_format, + r_field, r_pcrel); + bfd_put_32 (abfd, insn, hit_data); + return bfd_reloc_ok; + } else { /* Check to see if the delay slot instruction has a @@ -1619,6 +1656,20 @@ hppa_elf_reloc (abfd, reloc_entry, symbol_in, data, input_section, output_bfd) return bfd_reloc_ok; } } + else if (rtn_reg == 31) + { + /* The return register is r31, so this is a millicode call. + Perform no instruction reordering in this case. */ + insn = BLE_XXX_0_0; + r_type = R_HPPA_ABS_CALL_17; + r_pcrel = 0; + insn = hppa_elf_relocate_insn (abfd, input_section, insn, + addr, symbol_in, sym_value, + r_addend, r_type, r_format, + r_field, r_pcrel); + bfd_put_32 (abfd, insn, hit_data); + return bfd_reloc_ok; + } else { /* Check to see if the delay slot instruction has a @@ -2363,7 +2414,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, sizeof (asymbol *)); reloc_entry->sym_ptr_ptr[0] = stub_sym; if (reloc_entry->howto->type != R_HPPA_PLABEL_32 - && (get_opcode(insn) == BLE || get_opcode (insn) == BE)) + && (get_opcode(insn) == BLE + || get_opcode (insn) == BE + || get_opcode (insn) == BL)) reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17); } else @@ -2385,7 +2438,9 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, sizeof (asymbol *)); reloc_entry->sym_ptr_ptr[0] = stub_sym; if (reloc_entry->howto->type != R_HPPA_PLABEL_32 - && (get_opcode (insn) == BLE || get_opcode (insn) == BE)) + && (get_opcode (insn) == BLE + || get_opcode (insn) == BE + || get_opcode (insn) == BL)) reloc_entry->howto = bfd_reloc_type_lookup (abfd, R_HPPA_STUB_CALL_17); /* Generate common code for all stubs. */ @@ -2796,6 +2851,20 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) if (strcmp (symbol->name, "$$dyncall") == 0) dyncall = true; + + /* If we are creating a call from a stub to another stub, then + never do the instruction reordering. We can tell if we are + going to be calling one stub from another by the fact that + the symbol name has '_stub_' (arg. reloc. stub) or '_lb_stub_' + prepended to the name. Alternatively, the section of the + symbol will be '.hppa_linker_stubs'. */ + + if ((strncmp (symbol->name, "_stub_", 6) == 0) + || (strncmp (symbol->name, "_lb_stub_", 9) == 0)) + { + BFD_ASSERT (strcmp (symbol->section->name, ".hppa_linker_stubs") == 0); + rtn_adjust = false; + } /* Check to see if we modify the return pointer in the delay slot of the branch. */ @@ -2812,6 +2881,8 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) if (get_opcode (delay_insn) == LDO && (((delay_insn & 0x001f0000) >> 16) == rtn_reg)) rtn_adjust = false; + if (milli) + rtn_adjust = false; } } @@ -2896,12 +2967,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) /* 2. Make the call. */ if (!milli) { - NEW_INSTRUCTION (stub_entry, BE_N_XXX_0_31); + NEW_INSTRUCTION (stub_entry, BE_XXX_0_31); hppa_elf_stub_reloc (stub_desc, abfd, target_sym, CURRENT_STUB_OFFSET (stub_entry), R_HPPA_ABS_CALL_R17); + NEW_INSTRUCTION (stub_entry, COPY_2_31); } else { @@ -2931,12 +3003,13 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) CURRENT_STUB_OFFSET (stub_entry), R_HPPA_L21); - NEW_INSTRUCTION (stub_entry, BE_N_XXX_0_31); + NEW_INSTRUCTION (stub_entry, BE_XXX_0_31); hppa_elf_stub_reloc (stub_desc, abfd, target_sym, CURRENT_STUB_OFFSET (stub_entry), R_HPPA_ABS_CALL_R17); + NEW_INSTRUCTION (stub_entry, COPY_2_31); } } return stub_sym; diff --git a/bfd/som.c b/bfd/som.c index 08ef811..de23ef4 100644 --- a/bfd/som.c +++ b/bfd/som.c @@ -1356,11 +1356,18 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field) case e_psel: case e_lpsel: case e_rpsel: + final_types[0] = final_type; + final_types[1] = NULL; + final_types[2] = NULL; + *final_type = base_type; + break; + case e_tsel: case e_ltsel: case e_rtsel: - final_types[0] = final_type; - final_types[1] = NULL; + final_types[0] = (int *) bfd_alloc_by_size_t (abfd, sizeof (int)); + *final_types[0] = R_FSEL; + final_types[1] = final_type; final_types[2] = NULL; *final_type = base_type; break; @@ -1409,15 +1416,20 @@ hppa_som_gen_reloc_type (abfd, base_type, format, field) if (field == e_psel || field == e_lpsel || field == e_rpsel) - { - /* A PLABEL relocation that has a size of 32 bits must - be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */ - if (format == 32) - *final_type = R_DATA_PLABEL; - else - *final_type = R_CODE_PLABEL; - } - /* A relocatoin in the data space is always a full 32bits. */ + { + /* A PLABEL relocation that has a size of 32 bits must + be a R_DATA_PLABEL. All others are R_CODE_PLABELs. */ + if (format == 32) + *final_type = R_DATA_PLABEL; + else + *final_type = R_CODE_PLABEL; + } + /* PIC stuff. */ + else if (field == e_tsel + || field == e_ltsel + || field == e_rtsel) + *final_type = R_DLT_REL; + /* A relocation in the data space is always a full 32bits. */ else if (format == 32) *final_type = R_DATA_ONE_SYMBOL; @@ -2197,6 +2209,9 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) case R_S_MODE: case R_D_MODE: case R_R_MODE: + case R_FSEL: + case R_LSEL: + case R_RSEL: reloc_offset = bfd_reloc->address; break; @@ -2249,6 +2264,7 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) case R_DATA_ONE_SYMBOL: case R_DATA_PLABEL: case R_CODE_PLABEL: + case R_DLT_REL: /* Account for any addend. */ if (bfd_reloc->addend) p = som_reloc_addend (abfd, bfd_reloc->addend, p, @@ -2306,6 +2322,14 @@ som_write_fixups (abfd, current_offset, total_reloc_sizep) } break; + case R_FSEL: + case R_LSEL: + case R_RSEL: + bfd_put_8 (abfd, bfd_reloc->howto->type, p); + subspace_reloc_size += 1; + p += 1; + break; + /* Put a "R_RESERVED" relocation in the stream if we hit something we do not understand. The linker will complain loudly if this ever happens. */ -- 2.7.4