diff options
Diffstat (limited to 'bfd/elf32-xtensa.c')
-rw-r--r-- | bfd/elf32-xtensa.c | 49 |
1 files changed, 37 insertions, 12 deletions
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c index 4d1b384..888a801 100644 --- a/bfd/elf32-xtensa.c +++ b/bfd/elf32-xtensa.c @@ -2672,6 +2672,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, if (info->relocatable) { + bfd_vma dest_addr; + asection * sym_sec = get_elf_r_symndx_section (input_bfd, r_symndx); + /* This is a relocatable link. 1) If the reloc is against a section symbol, adjust according to the output section. @@ -2688,6 +2691,9 @@ elf_xtensa_relocate_section (bfd *output_bfd, return FALSE; } + dest_addr = sym_sec->output_section->vma + sym_sec->output_offset + + get_elf_r_symndx_offset (input_bfd, r_symndx) + rel->r_addend; + if (r_type == R_XTENSA_ASM_SIMPLIFY) { error_message = NULL; @@ -2724,25 +2730,41 @@ elf_xtensa_relocate_section (bfd *output_bfd, to work around problems with DWARF in relocatable links with some previous version of BFD. Now we can't easily get rid of the hack without breaking backward compatibility.... */ - if (rel->r_addend) + r = bfd_reloc_ok; + howto = &elf_howto_table[r_type]; + if (howto->partial_inplace && rel->r_addend) + { + r = elf_xtensa_do_reloc (howto, input_bfd, input_section, + rel->r_addend, contents, + rel->r_offset, FALSE, + &error_message); + rel->r_addend = 0; + } + else { - howto = &elf_howto_table[r_type]; - if (howto->partial_inplace) + /* Put the correct bits in the target instruction, even + though the relocation will still be present in the output + file. This makes disassembly clearer, as well as + allowing loadable kernel modules to work without needing + relocations on anything other than calls and l32r's. */ + + /* If it is not in the same section, there is nothing we can do. */ + if (r_type >= R_XTENSA_SLOT0_OP && r_type <= R_XTENSA_SLOT14_OP && + sym_sec->output_section == input_section->output_section) { r = elf_xtensa_do_reloc (howto, input_bfd, input_section, - rel->r_addend, contents, + dest_addr, contents, rel->r_offset, FALSE, &error_message); - if (r != bfd_reloc_ok) - { - if (!((*info->callbacks->reloc_dangerous) - (info, error_message, input_bfd, input_section, - rel->r_offset))) - return FALSE; - } - rel->r_addend = 0; } } + if (r != bfd_reloc_ok) + { + if (!((*info->callbacks->reloc_dangerous) + (info, error_message, input_bfd, input_section, + rel->r_offset))) + return FALSE; + } /* Done with work for relocatable link; continue with next reloc. */ continue; @@ -8848,6 +8870,9 @@ relax_section (bfd *abfd, asection *sec, struct bfd_link_info *link_info) internal_relocs = retrieve_internal_relocs (abfd, sec, link_info->keep_memory); + if (!internal_relocs && !relax_info->action_list.head) + return TRUE; + contents = retrieve_contents (abfd, sec, link_info->keep_memory); if (contents == NULL && sec_size != 0) { |