X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;ds=sidebyside;f=bfd%2Felf32-arc.c;h=11a1388acd6b59669f7ae46c1ab1a1e01f4146e7;hb=eec8bf7eab693186badfd5285cf713d3e22205e2;hp=c7ffc6a6f9df1d05fed79eba32ab83867af22ece;hpb=cc364be6ff45669150077387f22723de33d5f1b1;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elf32-arc.c b/bfd/elf32-arc.c index c7ffc6a6f9..11a1388acd 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elf32-arc.c @@ -1,5 +1,5 @@ /* ARC-specific support for 32-bit ELF - Copyright (C) 1994-2019 Free Software Foundation, Inc. + Copyright (C) 1994-2021 Free Software Foundation, Inc. Contributed by Cupertino Miranda (cmiranda@synopsys.com). This file is part of BFD, the Binary File Descriptor library. @@ -55,7 +55,7 @@ name_for_global_symbol (struct elf_link_hash_entry *h) Elf_Internal_Rela _rel; \ bfd_byte * _loc; \ \ - if (_htab->dynamic_sections_created == TRUE) \ + if (_htab->dynamic_sections_created) \ { \ BFD_ASSERT (_htab->srel##SECTION &&_htab->srel##SECTION->contents); \ _loc = _htab->srel##SECTION->contents \ @@ -81,11 +81,11 @@ reloc_type_to_name (unsigned int type) { switch (type) { - #include "elf/arc-reloc.def" +#include "elf/arc-reloc.def" - default: - return "UNKNOWN"; - break; + default: + return "UNKNOWN"; + break; } } @@ -96,58 +96,87 @@ reloc_type_to_name (unsigned int type) #define USE_REL 1 -static ATTRIBUTE_UNUSED bfd_boolean +/* Similar with bfd_get_32 but taking into account the + middle-endianess of the ARC CPUs. Only to be used in code + sections. */ + +static bfd_vma +bfd_get_32_me (bfd * abfd,const unsigned char * data) +{ + bfd_vma value = 0; + + if (bfd_big_endian (abfd)) + value = bfd_get_32 (abfd, data); + else + { + value = ((bfd_get_8 (abfd, data) & 255) << 16); + value |= ((bfd_get_8 (abfd, data + 1) & 255) << 24); + value |= (bfd_get_8 (abfd, data + 2) & 255); + value |= ((bfd_get_8 (abfd, data + 3) & 255) << 8); + } + + return value; +} + +static void +bfd_put_32_me (bfd *abfd, bfd_vma value,unsigned char *data) +{ + bfd_put_16 (abfd, (value & 0xffff0000) >> 16, data); + bfd_put_16 (abfd, value & 0xffff, data + 2); +} + +static ATTRIBUTE_UNUSED bool is_reloc_PC_relative (reloc_howto_type *howto) { - return (strstr (howto->name, "PC") != NULL) ? TRUE : FALSE; + return strstr (howto->name, "PC") != NULL; } -static bfd_boolean +static bool is_reloc_SDA_relative (reloc_howto_type *howto) { - return (strstr (howto->name, "SDA") != NULL) ? TRUE : FALSE; + return strstr (howto->name, "SDA") != NULL; } -static bfd_boolean +static bool is_reloc_for_GOT (reloc_howto_type * howto) { if (strstr (howto->name, "TLS") != NULL) - return FALSE; - return (strstr (howto->name, "GOT") != NULL) ? TRUE : FALSE; + return false; + return strstr (howto->name, "GOT") != NULL; } -static bfd_boolean +static bool is_reloc_for_PLT (reloc_howto_type * howto) { - return (strstr (howto->name, "PLT") != NULL) ? TRUE : FALSE; + return strstr (howto->name, "PLT") != NULL; } -static bfd_boolean +static bool is_reloc_for_TLS (reloc_howto_type *howto) { - return (strstr (howto->name, "TLS") != NULL) ? TRUE : FALSE; + return strstr (howto->name, "TLS") != NULL; } struct arc_relocation_data { - bfd_signed_vma reloc_offset; - bfd_signed_vma reloc_addend; - bfd_signed_vma got_offset_value; + bfd_signed_vma reloc_offset; + bfd_signed_vma reloc_addend; + bfd_signed_vma got_offset_value; - bfd_signed_vma sym_value; - asection * sym_section; + bfd_signed_vma sym_value; + asection *sym_section; reloc_howto_type *howto; - asection * input_section; + asection *input_section; - bfd_signed_vma sdata_begin_symbol_vma; - bfd_boolean sdata_begin_symbol_vma_set; - bfd_signed_vma got_symbol_vma; + bfd_signed_vma sdata_begin_symbol_vma; + bool sdata_begin_symbol_vma_set; + bfd_signed_vma got_symbol_vma; - bfd_boolean should_relocate; + bool should_relocate; - const char * symbol_name; + const char *symbol_name; }; /* ARC ELF linker hash entry. */ @@ -155,9 +184,6 @@ struct elf_arc_link_hash_entry { struct elf_link_hash_entry root; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - struct got_entry *got_ents; }; @@ -212,9 +238,9 @@ enum howto_list #undef ARC_RELOC_HOWTO #define ARC_RELOC_HOWTO(TYPE, VALUE, RSIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \ - [TYPE] = HOWTO (R_##TYPE, 0, RSIZE, BITSIZE, FALSE, 0, \ + [TYPE] = HOWTO (R_##TYPE, 0, RSIZE, BITSIZE, false, 0, \ complain_overflow_##OVERFLOW, arc_elf_reloc, \ - "R_" #TYPE, FALSE, 0, 0, FALSE), + "R_" #TYPE, false, 0, 0, false), static struct reloc_howto_struct elf_arc_howto_table[] = { @@ -225,15 +251,15 @@ static struct reloc_howto_struct elf_arc_howto_table[] = 0, // Rightshift. 2, // Size (0 = byte, 1 = short, 2 = long). 32, // Bitsize. - FALSE, // PC_relative. + false, // PC_relative. 0, // Bitpos. complain_overflow_bitfield, // Complain_on_overflow. bfd_elf_generic_reloc, // Special_function. "R_ARC_NONE", // Name. - TRUE, // Partial_inplace. + true, // Partial_inplace. 0, // Src_mask. 0, // Dst_mask. - FALSE), // PCrel_offset. + false), // PCrel_offset. */ }; #undef ARC_RELOC_HOWTO @@ -311,7 +337,6 @@ elf_arc_link_hash_newfunc (struct bfd_hash_entry *entry, table, string)); if (ret != NULL) { - ret->dyn_relocs = NULL; ret->got_ents = NULL; } @@ -366,17 +391,17 @@ static const struct arc_reloc_map arc_reloc_map[] = #undef ARC_RELOC_HOWTO -typedef ATTRIBUTE_UNUSED bfd_vma (*replace_func) (unsigned, int ATTRIBUTE_UNUSED); +typedef ATTRIBUTE_UNUSED unsigned (*replace_func) (unsigned, int ATTRIBUTE_UNUSED); #define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \ case TYPE: \ - func = (void *) RELOC_FUNCTION; \ + func = RELOC_FUNCTION; \ break; static replace_func get_replace_function (bfd *abfd, unsigned int r_type) { - void *func = NULL; + replace_func func = NULL; switch (r_type) { @@ -386,7 +411,7 @@ get_replace_function (bfd *abfd, unsigned int r_type) if (func == replace_bits24 && bfd_big_endian (abfd)) func = replace_bits24_be; - return (replace_func) func; + return func; } #undef ARC_RELOC_HOWTO @@ -406,16 +431,16 @@ arc_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, } /* Function to set the ELF flag bits. */ -static bfd_boolean +static bool arc_elf_set_private_flags (bfd *abfd, flagword flags) { elf_elfheader (abfd)->e_flags = flags; - elf_flags_init (abfd) = TRUE; - return TRUE; + elf_flags_init (abfd) = true; + return true; } /* Print private flags. */ -static bfd_boolean +static bool arc_elf_print_private_bfd_data (bfd *abfd, void * ptr) { FILE *file = (FILE *) ptr; @@ -453,23 +478,23 @@ arc_elf_print_private_bfd_data (bfd *abfd, void * ptr) } fputc ('\n', file); - return TRUE; + return true; } /* Copy backend specific data from one object module to another. */ -static bfd_boolean +static bool arc_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) { if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; + return true; BFD_ASSERT (!elf_flags_init (obfd) || elf_elfheader (obfd)->e_flags == elf_elfheader (ibfd)->e_flags); elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags; - elf_flags_init (obfd) = TRUE; + elf_flags_init (obfd) = true; /* Copy object attributes. */ _bfd_elf_copy_obj_attributes (ibfd, obfd); @@ -493,7 +518,7 @@ bfd_elf32_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, /* Set the howto pointer for an ARC ELF reloc. */ -static bfd_boolean +static bool arc_info_to_howto_rel (bfd * abfd, arelent * cache_ptr, Elf_Internal_Rela * dst) @@ -507,11 +532,11 @@ arc_info_to_howto_rel (bfd * abfd, _bfd_error_handler (_("%pB: unsupported relocation type %#x"), abfd, r_type); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } cache_ptr->howto = arc_elf_howto (r_type); - return TRUE; + return true; } /* Extract CPU features from an NTBS. */ @@ -556,14 +581,14 @@ arc_stralloc (char * s1, const char * s2) /* Merge ARC object attributes from IBFD into OBFD. Raise an error if there are conflicting attributes. */ -static bfd_boolean +static bool arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; obj_attribute *in_attr; obj_attribute *out_attr; int i; - bfd_boolean result = TRUE; + bool result = true; const char *sec_name = get_elf_backend_data (ibfd)->obj_attrs_section; char *tagname = NULL; @@ -571,13 +596,13 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) of accepting unknown attributes in the first input file - but is that a bug? */ if (ibfd->flags & BFD_LINKER_CREATED) - return TRUE; + return true; /* Skip any input that hasn't attribute section. This enables to link object files without attribute section with any others. */ if (bfd_get_section_by_name (ibfd, sec_name) == NULL) - return TRUE; + return true; if (!elf_known_obj_attributes_proc (obfd)[0].i) { @@ -590,7 +615,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) initialized. */ out_attr[0].i = 1; - return TRUE; + return true; } in_attr = elf_known_obj_attributes_proc (ibfd); @@ -638,7 +663,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) obfd, tagval[in_attr[i].i], tagval[out_attr[i].i]); - result = FALSE; + result = false; break; } else @@ -673,7 +698,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) (_("error: %pB: unable to merge ISA extension attributes " "%s"), obfd, bfd_feature_list[j].name); - result = FALSE; + result = false; break; } /* Second, if we have compatible features with the @@ -697,7 +722,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) (_("error: %pB: conflicting ISA extension attributes " "%s with %s"), obfd, p1, p2); - result = FALSE; + result = false; break; } /* Everithing is alright. */ @@ -736,7 +761,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) _bfd_error_handler (_("error: %pB: cannot mix rf16 with full register set %pB"), obfd, ibfd); - result = FALSE; + result = false; } break; @@ -766,7 +791,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) obfd, tagname, tagval[in_attr[i].i], tagval[out_attr[i].i]); - result = FALSE; + result = false; } tagname = NULL; break; @@ -791,7 +816,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) _bfd_error_handler (_("error: %pB: conflicting attributes %s"), obfd, tagname); - result = FALSE; + result = false; } break; @@ -819,7 +844,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) /* Merge Tag_compatibility attributes and any common GNU ones. */ if (!_bfd_elf_merge_object_attributes (ibfd, info)) - return FALSE; + return false; /* Check for any attributes not known on ARC. */ result &= _bfd_elf_merge_unknown_attribute_list (ibfd, obfd); @@ -830,7 +855,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) /* Merge backend specific data from an object file to the output object file when linking. */ -static bfd_boolean +static bool arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; @@ -842,11 +867,11 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* Check if we have the same endianess. */ if (! _bfd_generic_verify_endian_match (ibfd, info)) - return FALSE; + return false; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) - return TRUE; + return true; /* Collect ELF flags. */ in_flags = elf_elfheader (ibfd)->e_flags & EF_ARC_MACH_MSK; @@ -854,33 +879,33 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (!elf_flags_init (obfd)) /* First call, no flags set. */ { - elf_flags_init (obfd) = TRUE; + elf_flags_init (obfd) = true; out_flags = in_flags; } if (!arc_elf_merge_attributes (ibfd, info)) - return FALSE; + return false; /* Check to see if the input BFD actually contains any sections. Do not short-circuit dynamic objects; their section list may be emptied by elf_link_add_object_symbols. */ if (!(ibfd->flags & DYNAMIC)) { - bfd_boolean null_input_bfd = TRUE; - bfd_boolean only_data_sections = TRUE; + bool null_input_bfd = true; + bool only_data_sections = true; for (sec = ibfd->sections; sec != NULL; sec = sec->next) { - if ((bfd_get_section_flags (ibfd, sec) + if ((bfd_section_flags (sec) & (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) == (SEC_LOAD | SEC_CODE | SEC_HAS_CONTENTS)) - only_data_sections = FALSE; + only_data_sections = false; - null_input_bfd = FALSE; + null_input_bfd = false; } if (null_input_bfd || only_data_sections) - return TRUE; + return true; } /* Complain about various flag/architecture mismatches. */ @@ -897,7 +922,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) _bfd_error_handler (_("error: attempting to link %pB " "with a binary %pB of different architecture"), ibfd, obfd); - return FALSE; + return false; } else if ((in_flags != out_flags) /* If we have object attributes, then we already @@ -913,7 +938,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) (_("%pB: uses different e_flags (%#x) fields than " "previous modules (%#x)"), ibfd, in_flags, out_flags); - return FALSE; + return false; } /* MWDT doesnt set the eflags hence make sure we choose the eflags set by gcc. */ @@ -934,7 +959,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) return bfd_set_arch_mach (obfd, bfd_arch_arc, bfd_get_mach (ibfd)); } - return TRUE; + return true; } /* Return a best guess for the machine number based on the attributes. */ @@ -962,7 +987,7 @@ bfd_arc_get_mach_from_attributes (bfd * abfd) } /* Set the right machine number for an ARC ELF file. */ -static bfd_boolean +static bool arc_elf_object_p (bfd * abfd) { /* Make sure this is initialised, or you'll have the potential of passing @@ -976,22 +1001,22 @@ arc_elf_object_p (bfd * abfd) { switch (arch) { - case E_ARC_MACH_ARC600: - mach = bfd_mach_arc_arc600; - break; - case E_ARC_MACH_ARC601: - mach = bfd_mach_arc_arc601; - break; - case E_ARC_MACH_ARC700: - mach = bfd_mach_arc_arc700; - break; - case EF_ARC_CPU_ARCV2HS: - case EF_ARC_CPU_ARCV2EM: - mach = bfd_mach_arc_arcv2; - break; - default: - mach = bfd_arc_get_mach_from_attributes (abfd); - break; + case E_ARC_MACH_ARC600: + mach = bfd_mach_arc_arc600; + break; + case E_ARC_MACH_ARC601: + mach = bfd_mach_arc_arc601; + break; + case E_ARC_MACH_ARC700: + mach = bfd_mach_arc_arc700; + break; + case EF_ARC_CPU_ARCV2HS: + case EF_ARC_CPU_ARCV2EM: + mach = bfd_mach_arc_arcv2; + break; + default: + mach = bfd_arc_get_mach_from_attributes (abfd); + break; } } else @@ -1000,7 +1025,7 @@ arc_elf_object_p (bfd * abfd) { _bfd_error_handler (_("error: the ARC4 architecture is no longer supported")); - return FALSE; + return false; } else { @@ -1016,7 +1041,7 @@ arc_elf_object_p (bfd * abfd) /* The final processing done just before writing out an ARC ELF object file. This gets the ARC architecture right based on the machine number. */ -static bfd_boolean +static bool arc_elf_final_write_processing (bfd *abfd) { unsigned long emf; @@ -1071,7 +1096,8 @@ debug_arc_reloc (struct arc_relocation_data reloc_data) ARC_DEBUG (", output_section->vma = 0x%08x", ((unsigned int) reloc_data.sym_section->output_section->vma)); ARC_DEBUG ("\n"); - if (reloc_data.sym_section->owner && reloc_data.sym_section->owner->filename) + if (reloc_data.sym_section->owner + && reloc_data.sym_section->owner->filename) ARC_DEBUG (" file: %s\n", reloc_data.sym_section->owner->filename); } else @@ -1102,7 +1128,7 @@ debug_arc_reloc (struct arc_relocation_data reloc_data) #endif /* ARC_ENABLE_DEBUG */ static bfd_vma -middle_endian_convert (bfd_vma insn, bfd_boolean do_it) +middle_endian_convert (bfd_vma insn, bool do_it) { if (do_it) { @@ -1225,11 +1251,11 @@ arc_special_overflow_checks (const struct arc_relocation_data reloc_data, else \ ARC_DEBUG ("symbol_section->vma = NULL\n"); \ if (input_section->output_section != NULL) \ - ARC_DEBUG ("symbol_section->vma = %#lx\n", \ + ARC_DEBUG ("input_section->vma = %#lx\n", \ input_section->output_section->vma \ + input_section->output_offset); \ else \ - ARC_DEBUG ("symbol_section->vma = NULL\n"); \ + ARC_DEBUG ("input_section->vma = NULL\n"); \ ARC_DEBUG ("PCL = %#lx\n", P); \ ARC_DEBUG ("P = %#lx\n", P); \ ARC_DEBUG ("G = %#lx\n", G); \ @@ -1287,25 +1313,25 @@ arc_do_relocation (bfd_byte * contents, switch (reloc_data.howto->size) { - case 2: - insn = arc_bfd_get_32 (abfd, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - case 1: - insn = arc_bfd_get_16 (abfd, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - case 0: - insn = arc_bfd_get_8 (abfd, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - default: - insn = 0; - BFD_ASSERT (0); - break; + case 2: + insn = arc_bfd_get_32 (abfd, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; + case 1: + insn = arc_bfd_get_16 (abfd, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; + case 0: + insn = arc_bfd_get_8 (abfd, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; + default: + insn = 0; + BFD_ASSERT (0); + break; } orig_insn = insn; @@ -1314,9 +1340,9 @@ arc_do_relocation (bfd_byte * contents, { #include "elf/arc-reloc.def" - default: - BFD_ASSERT (0); - break; + default: + BFD_ASSERT (0); + break; } /* Check for relocation overflow. */ @@ -1343,25 +1369,25 @@ arc_do_relocation (bfd_byte * contents, /* Write updated instruction back to memory. */ switch (reloc_data.howto->size) { - case 2: - arc_bfd_put_32 (abfd, insn, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - case 1: + case 2: + arc_bfd_put_32 (abfd, insn, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; + case 1: arc_bfd_put_16 (abfd, insn, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - case 0: - arc_bfd_put_8 (abfd, insn, - contents + reloc_data.reloc_offset, - reloc_data.input_section); - break; - default: - ARC_DEBUG ("size = %d\n", reloc_data.howto->size); - BFD_ASSERT (0); + contents + reloc_data.reloc_offset, + reloc_data.input_section); break; + case 0: + arc_bfd_put_8 (abfd, insn, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; + default: + ARC_DEBUG ("size = %d\n", reloc_data.howto->size); + BFD_ASSERT (0); + break; } return bfd_reloc_ok; @@ -1397,7 +1423,7 @@ arc_do_relocation (bfd_byte * contents, local_section : is an array giving the section in the input file corresponding to the st_shndx field of each local symbol. */ -static bfd_boolean +static int elf_arc_relocate_section (bfd * output_bfd, struct bfd_link_info * info, bfd * input_bfd, @@ -1421,15 +1447,15 @@ elf_arc_relocate_section (bfd * output_bfd, relend = relocs + input_section->reloc_count; for (; rel < relend; wrel++, rel++) { - enum elf_arc_reloc_type r_type; - reloc_howto_type * howto; - unsigned long r_symndx; - struct elf_link_hash_entry * h; - Elf_Internal_Sym * sym; - asection * sec; - struct elf_link_hash_entry * h2; - const char * msg; - bfd_boolean unresolved_reloc = FALSE; + enum elf_arc_reloc_type r_type; + reloc_howto_type *howto; + unsigned long r_symndx; + struct elf_link_hash_entry *h; + Elf_Internal_Sym *sym; + asection *sec; + struct elf_link_hash_entry *h2; + const char *msg; + bool unresolved_reloc = false; struct arc_relocation_data reloc_data = { @@ -1441,9 +1467,9 @@ elf_arc_relocate_section (bfd * output_bfd, .howto = NULL, .input_section = NULL, .sdata_begin_symbol_vma = 0, - .sdata_begin_symbol_vma_set = FALSE, + .sdata_begin_symbol_vma_set = false, .got_symbol_vma = 0, - .should_relocate = FALSE + .should_relocate = false }; r_type = ELF32_R_TYPE (rel->r_info); @@ -1451,7 +1477,7 @@ elf_arc_relocate_section (bfd * output_bfd, if (r_type >= (int) R_ARC_max) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } howto = arc_elf_howto (r_type); @@ -1487,7 +1513,7 @@ elf_arc_relocate_section (bfd * output_bfd, } h2 = elf_link_hash_lookup (elf_hash_table (info), "__SDATA_BEGIN__", - FALSE, FALSE, TRUE); + false, false, true); if (!reloc_data.sdata_begin_symbol_vma_set && h2 != NULL && h2->root.type != bfd_link_hash_undefined @@ -1497,7 +1523,7 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.sdata_begin_symbol_vma = (h2->root.u.def.value + h2->root.u.def.section->output_section->vma); - reloc_data.sdata_begin_symbol_vma_set = TRUE; + reloc_data.sdata_begin_symbol_vma_set = true; } reloc_data.input_section = input_section; @@ -1517,7 +1543,7 @@ elf_arc_relocate_section (bfd * output_bfd, } else { - bfd_boolean warned, ignored; + bool warned, ignored; bfd_vma relocation ATTRIBUTE_UNUSED; RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel, @@ -1601,7 +1627,7 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.got_symbol_vma = htab->sgot->output_section->vma + htab->sgot->output_offset; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; } else /* Global symbol. */ { @@ -1635,7 +1661,7 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.sym_value = h->root.u.def.value; reloc_data.sym_section = h->root.u.def.section; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; if (is_reloc_for_GOT (howto) && !bfd_link_pic (info)) { @@ -1669,7 +1695,7 @@ elf_arc_relocate_section (bfd * output_bfd, { reloc_data.sym_value = h->root.u.def.value; reloc_data.sym_section = htab->sgot; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; } else if (is_reloc_for_PLT (howto) && h->plt.offset != (bfd_vma) -1) @@ -1677,7 +1703,7 @@ elf_arc_relocate_section (bfd * output_bfd, /* TODO: This is repeated up here. */ reloc_data.sym_value = h->plt.offset; reloc_data.sym_section = htab->splt; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; } else continue; @@ -1689,7 +1715,7 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.sym_value = h->root.u.def.value; reloc_data.sym_section = htab->sgot; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; } else if (is_reloc_for_PLT (howto)) { @@ -1698,16 +1724,16 @@ elf_arc_relocate_section (bfd * output_bfd, if (bfd_link_executable (info)) (*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, - rel->r_offset, TRUE); + rel->r_offset, true); reloc_data.sym_value = h->plt.offset; reloc_data.sym_section = htab->splt; - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; } else if (!bfd_link_pic (info) || bfd_link_executable (info)) (*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, - rel->r_offset, TRUE); + rel->r_offset, true); } BFD_ASSERT (htab->sgot != NULL || !is_reloc_for_GOT (howto)); @@ -1719,7 +1745,7 @@ elf_arc_relocate_section (bfd * output_bfd, if ((is_reloc_for_GOT (howto) || is_reloc_for_TLS (howto))) { - reloc_data.should_relocate = TRUE; + reloc_data.should_relocate = true; struct got_entry **list = get_got_entry_list_for_symbol (input_bfd, r_symndx, h); @@ -1756,6 +1782,7 @@ elf_arc_relocate_section (bfd * output_bfd, case R_ARC_PC32: case R_ARC_32_PCREL: if (bfd_link_pic (info) + && (input_section->flags & SEC_ALLOC) != 0 && (!IS_ARC_PCREL_TYPE (r_type) || (h != NULL && h->dynindx != -1 @@ -1764,11 +1791,11 @@ elf_arc_relocate_section (bfd * output_bfd, { Elf_Internal_Rela outrel; bfd_byte *loc; - bfd_boolean skip = FALSE; - bfd_boolean relocate = FALSE; + bool skip = false; + bool relocate = false; asection *sreloc = _bfd_elf_get_dynamic_reloc_section (input_bfd, input_section, - /*RELA*/ TRUE); + /*RELA*/ true); BFD_ASSERT (sreloc != NULL); @@ -1778,7 +1805,7 @@ elf_arc_relocate_section (bfd * output_bfd, rel->r_offset); if (outrel.r_offset == (bfd_vma) -1) - skip = TRUE; + skip = true; outrel.r_addend = rel->r_addend; outrel.r_offset += (input_section->output_section->vma @@ -1787,7 +1814,7 @@ elf_arc_relocate_section (bfd * output_bfd, if (skip) { memset (&outrel, 0, sizeof outrel); - relocate = FALSE; + relocate = false; } else if (h != NULL && h->dynindx != -1 @@ -1798,9 +1825,9 @@ elf_arc_relocate_section (bfd * output_bfd, { BFD_ASSERT (h != NULL); if ((input_section->flags & SEC_ALLOC) != 0) - relocate = FALSE; + relocate = false; else - relocate = TRUE; + relocate = true; BFD_ASSERT (h->dynindx != -1); outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); @@ -1817,7 +1844,7 @@ elf_arc_relocate_section (bfd * output_bfd, dynamic symbol table, and it's a regular symbol not defined in a shared object, then treat the symbol as local, resolve it now. */ - relocate = TRUE; + relocate = true; /* outrel.r_addend = 0; */ outrel.r_info = ELF32_R_INFO (0, R_ARC_RELATIVE); } @@ -1844,7 +1871,7 @@ elf_arc_relocate_section (bfd * output_bfd, _bfd_error_handler ("error: linker symbol __SDATA_BEGIN__ not found"); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } DEBUG_ARC_RELOC (reloc_data); @@ -1857,7 +1884,7 @@ elf_arc_relocate_section (bfd * output_bfd, _bfd_error_handler (_("GOT and PLT relocations cannot be fixed with a non dynamic linker")); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } msg = NULL; @@ -1874,7 +1901,7 @@ elf_arc_relocate_section (bfd * output_bfd, case bfd_reloc_undefined: (*info->callbacks->undefined_symbol) - (info, reloc_data.symbol_name, input_bfd, input_section, rel->r_offset, TRUE); + (info, reloc_data.symbol_name, input_bfd, input_section, rel->r_offset, true); break; case bfd_reloc_other: @@ -1905,17 +1932,18 @@ elf_arc_relocate_section (bfd * output_bfd, if (msg) _bfd_error_handler (msg, input_bfd, input_section, reloc_data.symbol_name); - return FALSE; + return false; } - return TRUE; + return true; } #define elf_arc_hash_table(p) \ - (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \ - == ARC_ELF_DATA ? ((struct elf_arc_link_hash_table *) ((p)->hash)) : NULL) + ((is_elf_hash_table ((p)->hash) \ + && elf_hash_table_id (elf_hash_table (p)) == ARC_ELF_DATA) \ + ? (struct elf_arc_link_hash_table *) (p)->hash : NULL) -static bfd_boolean +static bool elf_arc_check_relocs (bfd * abfd, struct bfd_link_info * info, asection * sec, @@ -1930,7 +1958,7 @@ elf_arc_check_relocs (bfd * abfd, struct elf_link_hash_table * htab = elf_hash_table (info); if (bfd_link_relocatable (info)) - return TRUE; + return true; if (htab->dynobj == NULL) htab->dynobj = abfd; @@ -1952,7 +1980,7 @@ elf_arc_check_relocs (bfd * abfd, if (r_type >= (int) R_ARC_max) { bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } howto = arc_elf_howto (r_type); @@ -1998,7 +2026,7 @@ elf_arc_check_relocs (bfd * abfd, arc_elf_howto (r_type)->name, name); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } /* In some cases we are not setting the 'non_got_ref' @@ -2020,14 +2048,14 @@ elf_arc_check_relocs (bfd * abfd, if (info->dynamic && ! htab->dynamic_sections_created && ! _bfd_elf_link_create_dynamic_sections (abfd, info)) - return FALSE; + return false; sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj, 2, abfd, /*rela*/ - TRUE); + true); if (sreloc == NULL) - return FALSE; + return false; } sreloc->size += sizeof (Elf32_External_Rela); @@ -2066,10 +2094,10 @@ elf_arc_check_relocs (bfd * abfd, arc_elf_howto (r_type)->name, name); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } if (! _bfd_elf_create_got_section (dynobj, info)) - return FALSE; + return false; arc_fill_got_info_for_reloc ( arc_got_entry_type_for_reloc (howto), @@ -2079,12 +2107,12 @@ elf_arc_check_relocs (bfd * abfd, } } - return TRUE; + return true; } #define ELF_DYNAMIC_INTERPRETER "/sbin/ld-uClibc.so" -static struct plt_version_t * +static const struct plt_version_t * arc_get_plt_version (struct bfd_link_info *info) { int i; @@ -2118,7 +2146,7 @@ add_symbol_to_plt (struct bfd_link_info *info) struct elf_link_hash_table *htab = elf_hash_table (info); bfd_vma ret; - struct plt_version_t *plt_data = arc_get_plt_version (info); + const struct plt_version_t *plt_data = arc_get_plt_version (info); /* If this is the first .plt entry, make room for the special first entry. */ @@ -2198,7 +2226,7 @@ relocate_plt_for_symbol (bfd *output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h) { - struct plt_version_t *plt_data = arc_get_plt_version (info); + const struct plt_version_t *plt_data = arc_get_plt_version (info); struct elf_link_hash_table *htab = elf_hash_table (info); bfd_vma plt_index = (h->plt.offset - plt_data->entry_size) @@ -2264,7 +2292,7 @@ static void relocate_plt_for_entry (bfd *abfd, struct bfd_link_info *info) { - struct plt_version_t *plt_data = arc_get_plt_version (info); + const struct plt_version_t *plt_data = arc_get_plt_version (info); struct elf_link_hash_table *htab = elf_hash_table (info); { @@ -2287,7 +2315,7 @@ relocate_plt_for_entry (bfd *abfd, have to change the definition to something the rest of the link can understand. */ -static bfd_boolean +static bool elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_link_hash_entry *h) { @@ -2307,13 +2335,13 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, a procedure linkage table, and we can just do a PC32 reloc instead. */ BFD_ASSERT (h->needs_plt); - return TRUE; + return true; } /* Make sure this symbol is output as a dynamic symbol. */ if (h->dynindx == -1 && !h->forced_local && !bfd_elf_link_record_dynamic_symbol (info, h)) - return FALSE; + return false; if (bfd_link_pic (info) || WILL_CALL_FINISH_DYNAMIC_SYMBOL (1, 0, h)) @@ -2332,7 +2360,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, h->plt.offset = (bfd_vma) -1; h->needs_plt = 0; } - return TRUE; + return true; } /* If this is a weak symbol, and there is a real definition, the @@ -2344,7 +2372,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, BFD_ASSERT (def->root.type == bfd_link_hash_defined); h->root.u.def.section = def->root.u.def.section; h->root.u.def.value = def->root.u.def.value; - return TRUE; + return true; } /* This is a reference to a symbol defined by a dynamic object which @@ -2355,18 +2383,18 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ if (!bfd_link_executable (info)) - return TRUE; + return true; /* If there are no non-GOT references, we do not need a copy relocation. */ if (!h->non_got_ref) - return TRUE; + return true; /* If -z nocopyreloc was given, we won't generate them either. */ if (info->nocopyreloc) { h->non_got_ref = 0; - return TRUE; + return true; } /* We must allocate the symbol in our .dynbss section, which will @@ -2380,7 +2408,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, same memory location for the variable. */ if (htab == NULL) - return FALSE; + return false; /* We must generate a R_ARC_COPY reloc to tell the dynamic linker to copy the initial value out of the dynamic object and into the @@ -2411,7 +2439,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, sym : Returns : True/False as the return status. */ -static bfd_boolean +static bool elf_arc_finish_dynamic_symbol (bfd * output_bfd, struct bfd_link_info *info, struct elf_link_hash_entry *h, @@ -2446,7 +2474,7 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, struct elf_arc_link_hash_table *arc_htab = elf_arc_hash_table (info); if (arc_htab == NULL) - return FALSE; + return false; if (h->dynindx == -1 || (h->root.type != bfd_link_hash_defined @@ -2478,14 +2506,14 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, || strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0) sym->st_shndx = SHN_ABS; - return TRUE; + return true; } #define GET_SYMBOL_OR_SECTION(TAG, SYMBOL, SECTION) \ case TAG: \ if (SYMBOL != NULL) \ h = elf_link_hash_lookup (elf_hash_table (info), \ - SYMBOL, FALSE, FALSE, TRUE); \ + SYMBOL, false, false, true); \ else if (SECTION != NULL) \ s = bfd_get_linker_section (dynobj, SECTION); \ break; @@ -2496,7 +2524,7 @@ struct obfd_info_group { struct bfd_link_info *info; }; -static bfd_boolean +static bool arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh, void *data) { @@ -2519,7 +2547,7 @@ arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh, } } - return TRUE; + return true; } @@ -2531,7 +2559,7 @@ arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh, sym : Returns : True/False as the return status. */ -static bfd_boolean +static bool elf_arc_finish_dynamic_sections (bfd * output_bfd, struct bfd_link_info *info) { @@ -2549,7 +2577,7 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn internal_dyn; - bfd_boolean do_it = FALSE; + bool do_it = false; struct elf_link_hash_entry *h = NULL; asection *s = NULL; @@ -2591,7 +2619,7 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, library and does not apply to this one. */ internal_dyn.d_un.d_val = 0; } - do_it = TRUE; + do_it = true; } else if (s != NULL) /* With a section information. */ { @@ -2604,12 +2632,12 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, case DT_VERNEED: internal_dyn.d_un.d_ptr = (s->output_section->vma + s->output_offset); - do_it = TRUE; + do_it = true; break; case DT_PLTRELSZ: internal_dyn.d_un.d_val = s->size; - do_it = TRUE; + do_it = true; break; default: @@ -2637,7 +2665,7 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, { struct elf_link_hash_entry *h; h = elf_link_hash_lookup (elf_hash_table (info), "_GLOBAL_OFFSET_TABLE_", - FALSE, FALSE, TRUE); + false, false, true); if (h != NULL && h->root.type != bfd_link_hash_undefined && h->root.u.def.section != NULL) @@ -2662,25 +2690,24 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, bfd_hash_traverse (&info->hash->table, arc_create_forced_local_got_entries_for_tls, &group); - return TRUE; + return true; } #define ADD_DYNAMIC_SYMBOL(NAME, TAG) \ h = elf_link_hash_lookup (elf_hash_table (info), \ - NAME, FALSE, FALSE, FALSE); \ + NAME, false, false, false); \ if ((h != NULL && (h->ref_regular || h->def_regular))) \ if (! _bfd_elf_add_dynamic_entry (info, TAG, 0)) \ - return FALSE; + return false; /* Set the sizes of the dynamic sections. */ -static bfd_boolean +static bool elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { bfd *dynobj; asection *s; - bfd_boolean relocs_exist = FALSE; - bfd_boolean reltext_exist = FALSE; + bool relocs_exist = false; struct elf_link_hash_table *htab = elf_hash_table (info); dynobj = htab->dynobj; @@ -2732,32 +2759,10 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { /* Strip this section if we don't need it. */ } - else if (strncmp (s->name, ".rela", 5) == 0) + else if (startswith (s->name, ".rela")) { if (s->size != 0 && s != htab->srelplt) - { - if (!reltext_exist) - { - const char *name = s->name + 5; - bfd *ibfd; - for (ibfd = info->input_bfds; ibfd; ibfd = ibfd->link.next) - if (bfd_get_flavour (ibfd) == bfd_target_elf_flavour - && ibfd->flags & DYNAMIC) - { - asection *target = bfd_get_section_by_name (ibfd, name); - if (target != NULL - && elf_section_data (target)->sreloc == s - && ((target->output_section->flags - & (SEC_READONLY | SEC_ALLOC)) - == (SEC_READONLY | SEC_ALLOC))) - { - reltext_exist = TRUE; - break; - } - } - } - relocs_exist = TRUE; - } + relocs_exist = true; /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ @@ -2781,36 +2786,10 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, /* Allocate memory for the section contents. */ s->contents = bfd_zalloc (dynobj, s->size); if (s->contents == NULL) - return FALSE; + return false; } - if (htab->dynamic_sections_created) - { - /* TODO: Check if this is needed. */ - if (!bfd_link_pic (info)) - if (!_bfd_elf_add_dynamic_entry (info, DT_DEBUG, 0)) - return FALSE; - - if (htab->splt && (htab->splt->flags & SEC_EXCLUDE) == 0) - if (!_bfd_elf_add_dynamic_entry (info, DT_PLTGOT, 0) - || !_bfd_elf_add_dynamic_entry (info, DT_PLTRELSZ, 0) - || !_bfd_elf_add_dynamic_entry (info, DT_PLTREL, DT_RELA) - || !_bfd_elf_add_dynamic_entry (info, DT_JMPREL, 0)) - return FALSE; - - if (relocs_exist) - if (!_bfd_elf_add_dynamic_entry (info, DT_RELA, 0) - || !_bfd_elf_add_dynamic_entry (info, DT_RELASZ, 0) - || !_bfd_elf_add_dynamic_entry (info, DT_RELAENT, - sizeof (Elf32_External_Rela))) - return FALSE; - - if (reltext_exist) - if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0)) - return FALSE; - } - - return TRUE; + return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs_exist); } @@ -2878,7 +2857,7 @@ const struct elf_size_info arc_elf32_size_info = function relies on offsets inside elf_prstatus structure in Linux to be stable. */ -static bfd_boolean +static bool elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; @@ -2887,7 +2866,7 @@ elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) switch (note->descsz) { default: - return FALSE; + return false; case 236: /* sizeof (struct elf_prstatus) on Linux/arc. */ /* pr_cursig */ @@ -2922,7 +2901,7 @@ elf32_arc_obj_attrs_arg_type (int tag) /* Attribute numbers >=14 can be safely ignored. */ -static bfd_boolean +static bool elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) { if ((tag & 127) < (Tag_ARC_ISA_mpy_option + 1)) @@ -2931,14 +2910,14 @@ elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) (_("%pB: unknown mandatory ARC object attribute %d"), abfd, tag); bfd_set_error (bfd_error_bad_value); - return FALSE; + return false; } else { _bfd_error_handler (_("warning: %pB: unknown ARC object attribute %d"), abfd, tag); - return TRUE; + return true; } } @@ -2946,7 +2925,7 @@ elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) called when bfd_section_from_shdr finds a section with an unknown type. */ -static bfd_boolean +static bool elf32_arc_section_from_shdr (bfd *abfd, Elf_Internal_Shdr * hdr, const char *name, @@ -2959,13 +2938,159 @@ elf32_arc_section_from_shdr (bfd *abfd, break; default: - return FALSE; + return false; } if (!_bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex)) - return FALSE; + return false; + + return true; +} + +/* Relaxation hook. + + These are the current relaxing opportunities available: + + * R_ARC_GOTPC32 => R_ARC_PCREL. + +*/ + +static bool +arc_elf_relax_section (bfd *abfd, asection *sec, + struct bfd_link_info *link_info, bool *again) +{ + Elf_Internal_Shdr *symtab_hdr; + Elf_Internal_Rela *internal_relocs; + Elf_Internal_Rela *irel, *irelend; + bfd_byte *contents = NULL; + Elf_Internal_Sym *isymbuf = NULL; + + /* Assume nothing changes. */ + *again = false; + + /* We don't have to do anything for a relocatable link, if this + section does not have relocs, or if this is not a code + section. */ + if (bfd_link_relocatable (link_info) + || (sec->flags & SEC_RELOC) == 0 + || sec->reloc_count == 0 + || (sec->flags & SEC_CODE) == 0) + return true; + + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + + /* Get a copy of the native relocations. */ + internal_relocs = _bfd_elf_link_read_relocs (abfd, sec, NULL, NULL, + link_info->keep_memory); + if (internal_relocs == NULL) + goto error_return; + + /* Walk through them looking for relaxing opportunities. */ + irelend = internal_relocs + sec->reloc_count; + for (irel = internal_relocs; irel < irelend; irel++) + { + /* If this isn't something that can be relaxed, then ignore + this reloc. */ + if (ELF32_R_TYPE (irel->r_info) != (int) R_ARC_GOTPC32) + continue; + + /* Get the section contents if we haven't done so already. */ + if (contents == NULL) + { + /* Get cached copy if it exists. */ + if (elf_section_data (sec)->this_hdr.contents != NULL) + contents = elf_section_data (sec)->this_hdr.contents; + /* Go get them off disk. */ + else if (!bfd_malloc_and_get_section (abfd, sec, &contents)) + goto error_return; + } + + /* Read this BFD's local symbols if we haven't done so already. */ + if (isymbuf == NULL && symtab_hdr->sh_info != 0) + { + isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents; + if (isymbuf == NULL) + isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr, + symtab_hdr->sh_info, 0, + NULL, NULL, NULL); + if (isymbuf == NULL) + goto error_return; + } + + struct elf_link_hash_entry *htop = NULL; + + if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info) + { + /* An external symbol. */ + unsigned int indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; + htop = elf_sym_hashes (abfd)[indx]; + } + + if (ELF32_R_TYPE (irel->r_info) == (int) R_ARC_GOTPC32 + && SYMBOL_REFERENCES_LOCAL (link_info, htop)) + { + unsigned int code; + + /* Get the opcode. */ + code = bfd_get_32_me (abfd, contents + irel->r_offset - 4); + + /* Note that we've changed the relocs, section contents, etc. */ + elf_section_data (sec)->relocs = internal_relocs; + elf_section_data (sec)->this_hdr.contents = contents; + symtab_hdr->contents = (unsigned char *) isymbuf; + + /* Fix the relocation's type. */ + irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_ARC_PC32); + + /* ld rA,[pcl,symbol@tgot] -> add rA,pcl,symbol@pcl. */ + /* 0010 0bbb aa11 0ZZX DBBB 1111 10AA AAAA. + 111 00 000 0111 xx xxxx*/ + code &= ~0x27307F80; + BFD_ASSERT (code <= 62UL); + code |= 0x27007F80; + + /* Write back the new instruction. */ + bfd_put_32_me (abfd, code, contents + irel->r_offset - 4); + + /* The size isn't changed, don't redo. */ + *again = false; + } + } + + if (isymbuf != NULL + && symtab_hdr->contents != (unsigned char *) isymbuf) + { + if (!link_info->keep_memory) + free (isymbuf); + else + /* Cache the symbols for elf_link_input_bfd. */ + symtab_hdr->contents = (unsigned char *) isymbuf; + } + + if (contents != NULL + && elf_section_data (sec)->this_hdr.contents != contents) + { + if (!link_info->keep_memory) + free (contents); + else + /* Cache the section contents for elf_link_input_bfd. */ + elf_section_data (sec)->this_hdr.contents = contents; + } + + if (elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); + + return true; + + error_return: + if (symtab_hdr->contents != (unsigned char *) isymbuf) + free (isymbuf); + if (elf_section_data (sec)->this_hdr.contents != contents) + free (contents); + if (elf_section_data (sec)->relocs != internal_relocs) + free (internal_relocs); - return TRUE; + return false; } #define TARGET_LITTLE_SYM arc_elf32_le_vec @@ -2985,6 +3110,7 @@ elf32_arc_section_from_shdr (bfd *abfd, #define bfd_elf32_bfd_set_private_flags arc_elf_set_private_flags #define bfd_elf32_bfd_print_private_bfd_data arc_elf_print_private_bfd_data #define bfd_elf32_bfd_copy_private_bfd_data arc_elf_copy_private_bfd_data +#define bfd_elf32_bfd_relax_section arc_elf_relax_section #define elf_info_to_howto_rel arc_info_to_howto_rel #define elf_backend_object_p arc_elf_object_p