diff options
-rw-r--r-- | bfd/ChangeLog | 32 | ||||
-rw-r--r-- | bfd/elf32-hppa.c | 299 | ||||
-rw-r--r-- | bfd/targets.c | 6 |
3 files changed, 200 insertions, 137 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 1f60d3e..c5b3fc9 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,35 @@ +Tue Oct 26 10:16:54 1993 Ken Raeburn (raeburn@cygnus.com) + + From Jeff Law and Pete Hoogenboom at Utah: + + * elf32-hppa.h (hppa_elf_stub_finish): Add prototype. + (ELF32_HPPA_R_ARG_RELOC): Renamed without the ELF32 prefix + and moved into libhppa.h. All references changed. + (ELF32_HPPA_R_CONSTANT, ELF32_HPPA_R_ADDEND): Likewise. + (get_opcode and opcode defines): Move into libhppa.h + * elf32-hppa.c (hppa_elf_insn2fmt): Rename and move info + libhppa.h. + * libhppa.h (HPPA_R_*): Moved here. Reformatted slightly to make + for easier reading. + (get_opcode): Moved here. FIXME! this really should be a C function + inside the opcode library! + (bfd_hppa_insn2fmt): Likewise. + + * targets.c (target_vector): Enable elf32-hppa vector. + + * elf32-hppa.c (hppa_elf_get_section_contents): Add new comments + and clarify existing comments. Do not use DEFUN to declare this + function. Fix numerous indention problems. Correctly handle cases + where symbol extension section may need to be read from disk, + read from memory, or built then read from memory. + + * elf32-hppa.h: Reformat with gnu-indent and hand fix numerous + formatting and indention problems gnu-indent can not handle. + Clarify some comments about relocation types. Comment basic + relocation "classes". Group PARAM declarations together. + (HPPA_SXT_{NULL, SYMNDX, RG_RELOC}): Make members of a new + enumerated type rather than #defines. + Tue Oct 26 02:40:46 1993 Stu Grossman (grossman at cygnus.com) * som.c (hppa_object_setup): Set SEC_CODE for .text section so diff --git a/bfd/elf32-hppa.c b/bfd/elf32-hppa.c index 268773e..68c85fd 100644 --- a/bfd/elf32-hppa.c +++ b/bfd/elf32-hppa.c @@ -196,6 +196,7 @@ static reloc_howto_type elf_hppa_howto_table[ELF_HOWTO_TABLE_SIZE] = static symext_chainS *symext_rootP; static symext_chainS *symext_lastP; +static boolean symext_chain_built; static unsigned long DEFUN (hppa_elf_rebuild_insn, (abfd, insn, value, r_type, r_field, r_format), @@ -296,7 +297,7 @@ DEFUN (hppa_elf_relocate_insn, case STH: case STW: case STWM: - constant_value = ELF32_HPPA_R_CONSTANT (r_addend); + constant_value = HPPA_R_CONSTANT (r_addend); BFD_ASSERT (r_format == 14); if (pcrel) @@ -310,7 +311,7 @@ DEFUN (hppa_elf_relocate_insn, case ADDI: /* case ADDIO: */ BFD_ASSERT (r_format == 11); - constant_value = ((insn & 0x1) << 10) | ((insn & 0xffe) >> 1); + constant_value = HPPA_R_CONSTANT(r_addend); sym_value = hppa_field_adjust (sym_value, constant_value, r_field); return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format); @@ -318,15 +319,14 @@ DEFUN (hppa_elf_relocate_insn, case ADDIL: BFD_ASSERT (r_format == 21); - constant_value = assemble_21 (insn); - constant_value += ELF32_HPPA_R_CONSTANT (r_addend); + constant_value = HPPA_R_CONSTANT (r_addend); sym_value = hppa_field_adjust (sym_value, constant_value, r_field); return hppa_elf_rebuild_insn (abfd, insn, sym_value, r_type, r_field, r_format); case BL: case BE: case BLE: - arg_reloc = ELF32_HPPA_R_ARG_RELOC (r_addend); + arg_reloc = HPPA_R_ARG_RELOC (r_addend); BFD_ASSERT (r_format == 17); @@ -352,8 +352,7 @@ DEFUN (hppa_elf_relocate_insn, if (opcode == 0) { BFD_ASSERT (r_format == 32); - constant_value = insn; - constant_value += ELF32_HPPA_R_CONSTANT (r_addend); + constant_value = HPPA_R_CONSTANT (r_addend); return hppa_field_adjust (sym_value, constant_value, r_field); } @@ -1170,75 +1169,6 @@ hppa_elf_gen_reloc_type (abfd, base_type, format, field) #undef final_type -/* 12.4.4. Derive format from instruction - - Given a machine instruction, this function determines its format. - The format can be determined solely from looking at the first six - bits (the major opcode) of the instruction. Several major opcodes - map to the same format. Opcodes which do not map to a known format - should probably be reported as an error. */ - -unsigned char -hppa_elf_insn2fmt (type, insn) - elf32_hppa_reloc_type type; - unsigned long insn; -{ - unsigned char fmt = 0; /* XXX: is this a proper default? */ - unsigned char op = get_opcode (insn); - - if (type == R_HPPA_NONE) - fmt = 0; - else - { - switch (op) - { - case ADDI: - case ADDIT: - case SUBI: - fmt = 11; - break; - case MOVB: - case MOVIB: - case COMBT: - case COMBF: - case COMIBT: - case COMIBF: - case ADDBT: - case ADDBF: - case ADDIBT: - case ADDIBF: - case BVB: - case BB: - fmt = 12; - break; - case LDO: - case LDB: - case LDH: - case LDW: - case LDWM: - case STB: - case STH: - case STW: - case STWM: - fmt = 14; - break; - case BL: - case BE: - case BLE: - fmt = 17; - break; - case LDIL: - case ADDIL: - fmt = 21; - break; - default: - fmt = 32; - break; - } - - } - return fmt; -} /* this function is in charge of performing all the HP PA relocations */ static long global_value; @@ -1609,10 +1539,30 @@ DEFUN (hppa_elf_reloc, (abfd, reloc_entry, symbol_in, data, input_section, outpu case R_HPPA_STUB_CALL_17: /* yes, a branch to a long branch stub. Change instruction to a BLE */ /* or BLE,N */ - if ( *(unsigned *)hit_data & 2 ) + if ( insn & 2 ) insn = BLE_N_XXX_0_0; else - insn = BLE_XXX_0_0; + { + unsigned long old_delay_slot_insn = bfd_get_32 (abfd, hit_data + 4); + unsigned rtn_reg = (insn & 0x03e00000) >> 21; + + if (get_opcode(old_delay_slot_insn) == LDO) + { + unsigned ldo_src_reg = (old_delay_slot_insn & 0x03e00000) >> 21; + unsigned ldo_target_reg = (old_delay_slot_insn & 0x001f0000) >> 16; + + if (ldo_target_reg == rtn_reg) + { + unsigned long new_delay_slot_insn = old_delay_slot_insn; + + BFD_ASSERT(ldo_src_reg == ldo_target_reg); + new_delay_slot_insn &= 0xfc00ffff; + 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; @@ -2494,7 +2444,7 @@ hppa_elf_build_arg_reloc_stub (abfd, output_bfd, reloc_entry, stub_types) /* generate the ending common section for all stubs */ /* XXX: can we assume this is a save return? */ - NEW_INSTRUCTION (stub_entry, BV_N_0RP); + NEW_INSTRUCTION (stub_entry, BV_N_0_RP); } return stub_sym; @@ -2633,6 +2583,7 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) asection *output_text_section = bfd_get_section_by_name (output_bfd, ".text"); char stub_sym_name[128]; int milli = false; + int dyncall = false; elf32_hppa_stub_name_list *stub_entry; if (!stub_sec) @@ -2762,14 +2713,25 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) if ( ((*data & 0x03e00000) >> 21) == 31 ) milli = true; + if ( strcmp(symbol->name,"$$dyncall") == 0 ) + dyncall = 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, LDSID_31_1); + NEW_INSTRUCTION(stub_entry, MTSP_1_SR0); + + if ( !dyncall ) { - NEW_INSTRUCTION(stub_entry, COPY_31_2); - + if ( !milli ) + { + NEW_INSTRUCTION(stub_entry, COPY_31_2); + } + else + { + NEW_INSTRUCTION(stub_entry, COPY_31_1); + } + NEW_INSTRUCTION(stub_entry, LDIL_XXX_31); hppa_elf_stub_reloc (stub_desc, abfd, /* the output bfd */ @@ -2778,39 +2740,45 @@ hppa_elf_build_long_branch_stub (abfd, output_bfd, reloc_entry, symbol, data) 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); + + if ( !milli ) + { + 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); + } + else + { + NEW_INSTRUCTION(stub_entry,BE_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); + NEW_INSTRUCTION(stub_entry, COPY_1_31); + } /* 3. Branch back to the original location. */ - /* (accomplished with the COPY_31_2 instruction) */ + /* (for non-millicode calls, accomplished with the COPY_31_2 instruction) */ + /* (for millicode calls, return location is already in r2) */ } else { - NEW_INSTRUCTION(stub_entry, STW_31_M24SP); - NEW_INSTRUCTION(stub_entry, LDIL_XXX_RP); + 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,BLE_XXX_0_RP); + + 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); - 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); } } @@ -2832,8 +2800,6 @@ hppa_elf_long_branch_needed_p (abfd, asec, reloc_entry, symbol, insn) #define too_far(val,num_bits) ((int)(val) > (1<<(num_bits))-1) || ((int)(val) < (-1<<(num_bits))) - BFD_ASSERT(fmt == hppa_elf_insn2fmt(reloc_entry->howto->type,insn)); - switch (op) { case BL: @@ -2903,7 +2869,7 @@ hppa_elf_stub_check (abfd, output_bfd, input_section, reloc_entry, symbol, hit_d 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); + symext_entryS caller_ar = (symext_entryS) HPPA_R_ARG_RELOC (reloc_entry->addend); if (hppa_elf_arg_reloc_needed_p (abfd, reloc_entry, stub_types, caller_ar)) { /* generate a stub */ @@ -3009,7 +2975,7 @@ hppa_look_for_stubs_in_section (stub_bfd, abfd, output_bfd, asec, syms, new_sym_ 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); + symext_entryS caller_ar = (symext_entryS) HPPA_R_ARG_RELOC (rle->addend); if (hppa_elf_arg_reloc_needed_p (abfd, rle, stub_types, caller_ar)) { @@ -3141,47 +3107,91 @@ DEFUN (hppa_elf_set_section_contents, (abfd, section, location, offset, count), offset, count); } +/* Get the contents of the given section. + + This is special for PA ELF because some sections (such as linker stubs) + may reside in memory rather than on disk, or in the case of the symbol + extension section, the contents may need to be generated from other + information contained in the BFD. */ + boolean -DEFUN (hppa_elf_get_section_contents, (abfd, section, location, offset, count), - bfd * abfd AND - sec_ptr section AND - PTR location AND - file_ptr offset AND - bfd_size_type count) +hppa_elf_get_section_contents (abfd, section, location, offset, count) + bfd *abfd; + sec_ptr section; + PTR location; + file_ptr offset; + bfd_size_type count; { - /* if this is the linker stub section, then we have the */ - /* section contents in memory rather than on disk. */ + /* If this is the linker stub section, then its contents are contained + in memory rather than on disk. FIXME. Is that always right? What + about the case where a final executable is read in and a user tries + to get the contents of this section? In that case the contents would + be on disk like everything else. */ if (strcmp (section->name, ".hppa_linker_stubs") == 0) { elf32_hppa_stub_description *stub_desc = find_stubs (abfd, section); - + if (count == 0) return true; - if ((bfd_size_type) (offset + count) > section->_raw_size) - return (false); /* on error */ - if ((bfd_size_type) (offset + count) > stub_desc->real_size) - return (false); /* on error */ - + + /* Sanity check our arguments. */ + if ((bfd_size_type) (offset + count) > section->_raw_size + || (bfd_size_type) (offset + count) > stub_desc->real_size) + return (false); + memcpy (location, stub_desc->stub_contents + offset, count); return (true); } - /* if this is the symbol extension section, then we have the */ - /* section contents in memory rather than on disk. */ + + /* The symbol extension section also needs special handling. Its + contents might be on the disk, in memory, or still need to + be generated. */ else if (strcmp (section->name, ".hppa_symextn") == 0) { + /* If this is the first time through and there are no output + sections, then read the contents of the symbol extension section + from disk. */ + if (! symext_chain_built + || ((section->output_section == NULL) + && (abfd->direction == read_direction))) + { + return bfd_generic_get_section_contents (abfd, section, location, + offset, count); + } + + /* If this is the first time through, and there are output sections, + then build the symbol extension section based on other information + contained in the BFD. */ + else if (! symext_chain_built) + { + int i; + int *symtab_map = elf_sym_extra(section->output_section->owner); + + for (i = 0; i < section->output_section->owner->symcount; i++ ) + { + elf_hppa_tc_symbol(section->output_section->owner, + section->output_section->owner->outsymbols[i], + symtab_map[i]); + } + symext_chain_built++; + elf_hppa_tc_make_sections (section->output_section->owner, NULL); + } if (count == 0) return true; - if ((bfd_size_type) (offset + count) > section->_raw_size) - return (false); /* on error */ - if ((bfd_size_type) (offset + count) > symextn_contents_real_size) - return (false); /* on error */ - - memcpy (location, symextn_contents + offset, count); + + /* Sanity check our arguments. */ + if ((bfd_size_type) (offset + count) > section->_raw_size + || (bfd_size_type) (offset + count) > symextn_contents_real_size) + return (false); + + memcpy (location, + ((char *)symextn_contents + section->output_offset + 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 @@ -3433,16 +3443,28 @@ DEFUN (elf32_hppa_backend_fake_sections, (abfd, secthdr, asect), return true; } + /* @@ Should this be CPU specific?? KR */ + if (!strcmp (asect->name, ".stabstr")) + { + secthdr->sh_type = SHT_STRTAB; + secthdr->sh_flags = 0; + secthdr->sh_info = 0; + secthdr->sh_link = 0; + secthdr->sh_entsize = 0; + return true; + } + return false; } #define elf_backend_fake_sections elf32_hppa_backend_fake_sections static boolean -DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect), +DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect, retval), bfd *abfd AND Elf32_Internal_Shdr *hdr AND - asection *asect) + asection *asect AND + int *retval) { if ( hdr->sh_type == SHT_HPPA_SYMEXTN ) @@ -3456,6 +3478,17 @@ DEFUN (elf32_hppa_backend_section_from_bfd_section, (abfd, hdr, asect), } } } + else if ( hdr->sh_type == SHT_STRTAB ) + { + if (hdr->rawdata) + { + if (((struct sec *) (hdr->rawdata)) == asect) + { + BFD_ASSERT ( strcmp (asect->name, ".stabstr") == 0); + return true; + } + } + } return false; } diff --git a/bfd/targets.c b/bfd/targets.c index 1027f5a..91d361d 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -421,17 +421,15 @@ bfd_target *target_vector[] = { &b_out_vec_little_host, #if 0 /* No one seems to use this. */ &bfd_elf32_big_generic_vec, - &bfd_elf32_bigmips_vec, #endif -#if 0 + &bfd_elf32_bigmips_vec, &bfd_elf32_hppa_vec, -#endif &bfd_elf32_i386_vec, &bfd_elf32_i860_vec, #if 0 /* No one seems to use this. */ &bfd_elf32_little_generic_vec, - &bfd_elf32_littlemips_vec, #endif + &bfd_elf32_littlemips_vec, &bfd_elf32_m68k_vec, &bfd_elf32_m88k_vec, &bfd_elf32_sparc_vec, |