From a52ae715e4cce477b3f304e89b1ad9d2bf86e5fc Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Sun, 11 Feb 2001 23:11:40 +0000 Subject: [PATCH] Apply several patches from Maciej W. Rozycki --- bfd/ChangeLog | 33 ++++++++++++++++ bfd/elf32-mips.c | 113 ++++++++++++++++++++++++++++++++++++----------------- opcodes/ChangeLog | 7 ++++ opcodes/mips-dis.c | 6 +-- 4 files changed, 120 insertions(+), 39 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 05740c1f10..a96c3dac05 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,36 @@ +2001-02-11 Maciej W. Rozycki + + * elf32-mips.c (mips_elf_create_dynamic_relocation): Undo patch + from 2000-10-13. Do not add the symbol's value for R_MIPS_REL32 + relocations against dynsym symbols. + + * elf32-mips.c (elf_mips_howto_table): Fix the comment on + the R_MIPS_26 relocation. + (mips_elf_calculate_relocation): Use (p + 4) instead of p for + the R_MIPS_26 relocation. + (mips_elf_perform_relocation): Fix the comment on the R_MIPS16_26 + relocation. + * elf64-mips.c (mips_elf64_howto_table_rel): Fix the comment on + the R_MIPS_26 relocation. + (mips_elf64_howto_table_rela): Likewise. + + * elf32-mips.c (struct mips_elf_link_hash_entry): Added no_fn_stub + member to mark symbols that have non-CALL relocations against + them. + (mips_elf_link_hash_newfunc): Initialize no_fn_stub. + (mips_elf_calculate_relocation): Handle R_MIPS_CALL16 like + R_MIPS_GOT16. + (_bfd_mips_elf_check_relocs): Set no_fn_stub for a symbol if a + non-CALL relocation against it is encountered. + (_bfd_mips_elf_copy_indirect_symbol): Merge no_fn_stub as well. + (_bfd_mips_elf_adjust_dynamic_symbol): Only create a stub if + no_fn_stub is not set. + + * elf32-mips.c (mips_elf_output_extsym): Get the output section + information from the real symbol for indirect ones. + Check no_fn_stub to find out if a symbol has a function stub + indeed. + 2001-02-11 Michael Sokolov * Makefile.am (stamp-lib): ranlib the libbfd.a in the build directory. diff --git a/bfd/elf32-mips.c b/bfd/elf32-mips.c index 5bb1e94c2e..7eb8aa2daf 100644 --- a/bfd/elf32-mips.c +++ b/bfd/elf32-mips.c @@ -80,6 +80,12 @@ struct mips_elf_link_hash_entry section) against this symbol. */ unsigned int min_dyn_reloc_index; + /* We must not create a stub for a symbol that has relocations + related to taking the function's address, i.e. any but + R_MIPS_CALL*16 ones -- see "MIPS ABI Supplement, 3rd Edition", + p. 4-20. */ + boolean no_fn_stub; + /* If there is a stub that 32 bit functions should use to call this 16 bit function, this points to the section containing the stub. */ asection *fn_stub; @@ -193,7 +199,7 @@ static bfd_vma mips_elf_got16_entry static boolean mips_elf_create_dynamic_relocation PARAMS ((bfd *, struct bfd_link_info *, const Elf_Internal_Rela *, struct mips_elf_link_hash_entry *, asection *, - bfd_vma, bfd_vma *, asection *, boolean local_p)); + bfd_vma, bfd_vma *, asection *)); static void mips_elf_allocate_dynamic_relocations PARAMS ((bfd *, unsigned int)); static boolean mips_elf_stub_section_p @@ -531,7 +537,7 @@ static reloc_howto_type elf_mips_howto_table[] = complain_overflow_dont, /* complain_on_overflow */ /* This needs complex overflow detection, because the upper four - bits must match the PC. */ + bits must match the PC + 4. */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_26", /* name */ true, /* partial_inplace */ @@ -3955,6 +3961,7 @@ mips_elf_link_hash_newfunc (entry, table, string) ret->esym.ifd = -2; ret->possibly_dynamic_relocs = 0; ret->min_dyn_reloc_index = 0; + ret->no_fn_stub = false; ret->fn_stub = NULL; ret->need_fn_stub = false; ret->call_stub = NULL; @@ -4330,24 +4337,36 @@ mips_elf_output_extsym (h, data) } else if ((h->root.elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { - /* Set type and value for a symbol with a function stub. */ - h->esym.asym.st = stProc; - sec = h->root.root.u.def.section; - if (sec == NULL) - h->esym.asym.value = 0; - else + struct mips_elf_link_hash_entry *hd = h; + boolean no_fn_stub = h->no_fn_stub; + + while (hd->root.root.type == bfd_link_hash_indirect) { - output_section = sec->output_section; - if (output_section != NULL) - h->esym.asym.value = (h->root.plt.offset - + sec->output_offset - + output_section->vma); - else - h->esym.asym.value = 0; + hd = (struct mips_elf_link_hash_entry *)h->root.root.u.i.link; + no_fn_stub = no_fn_stub || hd->no_fn_stub; } + + if (!no_fn_stub) + { + /* Set type and value for a symbol with a function stub. */ + h->esym.asym.st = stProc; + sec = hd->root.root.u.def.section; + if (sec == NULL) + h->esym.asym.value = 0; + else + { + output_section = sec->output_section; + if (output_section != NULL) + h->esym.asym.value = (hd->root.plt.offset + + sec->output_offset + + output_section->vma); + else + h->esym.asym.value = 0; + } #if 0 /* FIXME? */ - h->esym.ifd = 0; + h->esym.ifd = 0; #endif + } } if (! bfd_ecoff_debug_one_external (einfo->abfd, einfo->debug, einfo->swap, @@ -5748,7 +5767,7 @@ mips_elf_next_relocation (r_type, relocation, relend) static boolean mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec, - symbol, addendp, input_section, local_p) + symbol, addendp, input_section) bfd *output_bfd; struct bfd_link_info *info; const Elf_Internal_Rela *rel; @@ -5757,7 +5776,6 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec, bfd_vma symbol; bfd_vma *addendp; asection *input_section; - boolean local_p; { Elf_Internal_Rel outrel; boolean skip; @@ -5842,15 +5860,16 @@ mips_elf_create_dynamic_relocation (output_bfd, info, rel, h, sec, /* The relocation we're building is section-relative. Therefore, the original addend must be adjusted by the section offset. */ - *addendp += symbol - sec->output_section->vma; + *addendp += section_offset; /* Now, the relocation is just against the section. */ symbol = sec->output_section->vma; } - /* If the relocation is against a local symbol was previously an - absolute relocation, we must adjust it by the value we give - it in the dynamic symbol table. */ - if (local_p && r_type != R_MIPS_REL32) + /* If the relocation was previously an absolute relocation and + this symbol will not be referred to by the relocation, we must + adjust it by the value we give it in the dynamic symbol table. + Otherwise leave the job up to the dynamic linker. */ + if (!indx && r_type != R_MIPS_REL32) *addendp += symbol; /* The relocation is always an REL32 relocation because we don't @@ -6225,7 +6244,7 @@ mips_elf_calculate_relocation (abfd, symbol + addend, sgot->contents + g); } } - else if (r_type == R_MIPS_GOT16) + else if (r_type == R_MIPS_GOT16 || r_type == R_MIPS_CALL16) /* There's no need to create a local GOT entry here; the calculation for a local GOT16 entry does not involve G. */ break; @@ -6288,7 +6307,7 @@ mips_elf_calculate_relocation (abfd, sec, symbol, &value, - input_section, local_p)) + input_section)) return false; } else @@ -6320,14 +6339,14 @@ mips_elf_calculate_relocation (abfd, break; case R_MIPS16_26: - /* The calculation for R_MIPS_26 is just the same as for an + /* The calculation for R_MIPS16_26 is just the same as for an R_MIPS_26. It's only the storage of the relocated field into the output file that's different. That's handled in mips_elf_perform_relocation. So, we just fall through to the R_MIPS_26 case here. */ case R_MIPS_26: if (local_p) - value = (((addend << 2) | (p & 0xf0000000)) + symbol) >> 2; + value = (((addend << 2) | ((p + 4) & 0xf0000000)) + symbol) >> 2; else value = (mips_elf_sign_extend (addend << 2, 28) + symbol) >> 2; value &= howto->dst_mask; @@ -6393,6 +6412,7 @@ mips_elf_calculate_relocation (abfd, break; case R_MIPS_GOT16: + case R_MIPS_CALL16: if (local_p) { boolean forced; @@ -6415,7 +6435,6 @@ mips_elf_calculate_relocation (abfd, /* Fall through. */ - case R_MIPS_CALL16: case R_MIPS_GOT_DISP: value = g; overflowed_p = mips_elf_overflow_p (value, 16); @@ -6620,9 +6639,9 @@ mips_elf_perform_relocation (info, howto, relocation, value, ((sub1 << 16) | sub2)). When producing a relocateable object file, the calculation is - (((A < 2) | (P & 0xf0000000) + S) >> 2) + (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2) When producing a fully linked file, the calculation is - let R = (((A < 2) | (P & 0xf0000000) + S) >> 2) + let R = (((A < 2) | ((P + 4) & 0xf0000000) + S) >> 2) ((R & 0x1f0000) << 5) | ((R & 0x3e00000) >> 5) | (R & 0xffff) */ if (!info->relocateable) @@ -7728,10 +7747,10 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs) /* We may need a local GOT entry for this relocation. We don't count R_MIPS_GOT_PAGE because we can estimate the maximum number of pages needed by looking at the size of - the segment. Similar comments apply to R_MIPS_GOT16. We - don't count R_MIPS_GOT_HI16, or R_MIPS_CALL_HI16 because - these are always followed by an R_MIPS_GOT_LO16 or - R_MIPS_CALL_LO16. + the segment. Similar comments apply to R_MIPS_GOT16 and + R_MIPS_CALL16. We don't count R_MIPS_GOT_HI16, or + R_MIPS_CALL_HI16 because these are always followed by an + R_MIPS_GOT_LO16 or R_MIPS_CALL_LO16. This estimation is very conservative since we can merge duplicate entries in the GOT. In order to be less @@ -7863,6 +7882,25 @@ _bfd_mips_elf_check_relocs (abfd, info, sec, relocs) break; } + /* We must not create a stub for a symbol that has relocations + related to taking the function's address. */ + switch (r_type) + { + default: + if (h != NULL) + { + struct mips_elf_link_hash_entry *mh; + + mh = (struct mips_elf_link_hash_entry *) h; + mh->no_fn_stub = true; + } + break; + case R_MIPS_CALL16: + case R_MIPS_CALL_HI16: + case R_MIPS_CALL_LO16: + break; + } + /* If this reloc is not a 16 bit call, and it has a global symbol, then we will need the fn_stub if there is one. References from a stub section do not count. */ @@ -7998,6 +8036,8 @@ _bfd_mips_elf_copy_indirect_symbol (dir, ind) || (indmips->min_dyn_reloc_index != 0 && indmips->min_dyn_reloc_index < dirmips->min_dyn_reloc_index)) dirmips->min_dyn_reloc_index = indmips->min_dyn_reloc_index; + if (indmips->no_fn_stub) + dirmips->no_fn_stub = true; } /* Adjust a symbol defined by a dynamic object and referenced by a @@ -8038,8 +8078,9 @@ _bfd_mips_elf_adjust_dynamic_symbol (info, h) mips_elf_allocate_dynamic_relocations (dynobj, hmips->possibly_dynamic_relocs); - /* For a function, create a stub, if needed. */ - if ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) + /* For a function, create a stub, if allowed. */ + if (! hmips->no_fn_stub + && (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0) { if (! elf_hash_table (info)->dynamic_sections_created) return true; diff --git a/opcodes/ChangeLog b/opcodes/ChangeLog index 6c93aa7347..dfca2e92cf 100644 --- a/opcodes/ChangeLog +++ b/opcodes/ChangeLog @@ -1,3 +1,10 @@ +2001-02-11 Maciej W. Rozycki + + * mips-dis.c (print_insn_arg): Use top four bits of the address of + the following instruction not of the jump itself for the jump + target. + (print_mips16_insn_arg): Likewise. + 2001-02-11 Michael Sokolov * Makefile.am (stamp-lib): ranlib the libopcodes.a in the build diff --git a/opcodes/mips-dis.c b/opcodes/mips-dis.c index a75dc89d9f..849f9f2003 100644 --- a/opcodes/mips-dis.c +++ b/opcodes/mips-dis.c @@ -137,7 +137,7 @@ print_insn_arg (d, l, pc, info) case 'a': (*info->print_address_func) - (((pc & ~ (bfd_vma) 0x0fffffff) + ((((pc + 4) & ~ (bfd_vma) 0x0fffffff) | (((l >> OP_SH_TARGET) & OP_MASK_TARGET) << 2)), info); break; @@ -1038,9 +1038,9 @@ print_mips16_insn_arg (type, op, l, use_extend, extend, memaddr, info) if (! use_extend) extend = 0; l = ((l & 0x1f) << 23) | ((l & 0x3e0) << 13) | (extend << 2); - (*info->print_address_func) ((memaddr & 0xf0000000) | l, info); + (*info->print_address_func) (((memaddr + 4) & 0xf0000000) | l, info); info->insn_type = dis_jsr; - info->target = (memaddr & 0xf0000000) | l; + info->target = ((memaddr + 4) & 0xf0000000) | l; info->branch_delay_insns = 1; break; -- 2.11.0