From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by sourceware.org (Postfix) with ESMTPS id 067503857C44 for ; Tue, 19 Sep 2023 08:13:15 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 067503857C44 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-2b9c907bc68so89089481fa.2 for ; Tue, 19 Sep 2023 01:13:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1695111193; x=1695715993; darn=sourceware.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hIamclsbCGuLRSMWvEPD3yprMFzeN09QgQ7XieFQPjg=; b=C1rpolvFU2YNw8DSABgY0IrLdgEr9UIcmEy1304gdhH9HsX6+LBk8DMJbSXl3ejuaN e62TcDlXuowmp3qFyZLQHXaC9nzMdF565s+PuNIw8SCOFb4S2inyBg0Aw4gov5VWk/e5 tGIR2UHWTKoxv9aZlcYMb34obTnk+F5CfUtmvJQg+jz1UQbJheZ880+BoKQTzXKcFoXZ cHbdCJKj45K9GsRIWGlIY8Jko9TcoQegN2RTfQAnLtf+AgTvq260LKtPEF1KxCxQl5pV sWdoNbnKJzxOosBEB7iaZsO0Thyr95hPSTOQ86V3FLkwnlT2ap/m/iVqKaz2kZ6WUJOL mW1g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695111193; x=1695715993; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hIamclsbCGuLRSMWvEPD3yprMFzeN09QgQ7XieFQPjg=; b=cNP7eQFNihgKyTLf5DJAgtJbB/tfTa9DMifxy5vAYrwpiqzLcbCLQfQpVZkOpqELOo E3KNdNd7dFNEeH5arSMP/XJ94gFaqECf1FaeY49YJL9r2inO9u8oc4Am3phkKU4DJFRx O1JWZ6XYdnGjpO1NYO1bCnKlEsWPLxLu3OMiAMzolN8eVhVQiKMDjjSfmomdC7RUUiW/ SA3b0MnsglkitXCI2PU/6rYbt7g62KFfiDgG/stqUNrc3rkTefMZ4SA4iUeDPzX2hi3c w7g9O3RfA0p60H5TflTSW38BGV4xuQavMzzoTgRFCL36Wu1Aul6tZyDoR/lm/0GWrYqF lPdw== X-Gm-Message-State: AOJu0YzCw8pxHKDnp/U/YLwPY0gd0NOtaonF3ctuJPC6Fd2fGJI2wls/ rWOpvF56lewtb7NMKQjzlQHQ1UWF8FY= X-Google-Smtp-Source: AGHT+IEEwt3j0teCeKaIVqSVTVtnppOacvE0QdJz0H++fxK6m3DAQZ89+Hj4QnVib21D3yKXKZKSag== X-Received: by 2002:a2e:b164:0:b0:2bc:e46d:f4d0 with SMTP id a4-20020a2eb164000000b002bce46df4d0mr10228146ljm.2.1695111189694; Tue, 19 Sep 2023 01:13:09 -0700 (PDT) Received: from fatty.nomansland ([193.187.151.25]) by smtp.gmail.com with ESMTPSA id qx15-20020a170906fccf00b009a5f1d15644sm7359213ejb.119.2023.09.19.01.13.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 19 Sep 2023 01:13:09 -0700 (PDT) From: Claudiu Zissulescu To: binutils@sourceware.org Cc: Claudiu Zissulescu Subject: [PATCH 3/7] arc: Add new ARCv3 ISA to BFD. Date: Tue, 19 Sep 2023 11:12:46 +0300 Message-Id: <20230919081250.2496254-4-claziss@gmail.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230919081250.2496254-1-claziss@gmail.com> References: <20230919081250.2496254-1-claziss@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.6 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_FROM,GIT_PATCH_0,KAM_STOCKGEN,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: From: Claudiu Zissulescu The new Synopsys's ARCv3 ISA is capable to run either 64-bit or 32-bit ISA. The new 32-bit ISA is not compatible with the old Synopsys ARCv1/ARCv2 ISA, however, it retains a lot of common concepts. Thus, this patch is reusing the old ARC BFD backend and adds the necessary bits for the new architecture in a similar way as it is done for RISCV backend. bfd/ xxxx-xx-xx Claudiu Zissulescu * bfd/Makefile.am: Add ARC64 files. * bfd/Makefile.in: Regerate. * bfd/arc-got.h (TCB_SIZE): Depends on the target architecture. (GOT_ENTRY_SIZE): New define. (write_in_got): Likewise. (read_from_got): Likewise. (align_power): Likewise. (arc_got_entry_type_for_reloc): Use RELA_SIZE and GOT_ENTRY_SIZE. (arc_fill_got_info_for_reloc): Update formating. (relocate_fix_got_relocs_for_got_info): Likewise. (arc_static_sym_data): Deleted structure. (get_static_sym_data): Deleted function. (relocate_fix_got_relocs_for_got_info): Use symbol static data. (create_got_dynrelocs_for_single_entry): Update formating. (create_got_dynrelocs_for_got_info): Likewise. * bfd/arc-plt.c: New file. * bfd/arc-plt.def: Add ARC64 PLT entry. * bfd/arc-plt.h: Clean it up, move functionality to arc-plt.c file. * bfd/archures.c: Add ARC64 target. * bfd/config.bfd: Likewise. * bfd/configure.ac: Likewise. * bfd/bfd-in2.h: Regenerate. * bfd/configure: Likewise. * bfd/libbfd.h: Likewise. * bfd/cpu-arc.c: Clean it up. * bfd/cpu-arc64.c: New file. * bfd/elf32-arc.c: Renamed to elfnn-arc.c. * bfd/elfnn-arc.c: New file. * bfd/reloc.c: Add new ARC64 relocs. * bfd/targets.c: Add ARC64 target. Signed-off-by: Claudiu Zissulescu --- bfd/Makefile.am | 23 +- bfd/Makefile.in | 27 +- bfd/arc-got.h | 253 +++-- bfd/arc-plt.c | 121 +++ bfd/arc-plt.def | 127 ++- bfd/arc-plt.h | 93 +- bfd/archures.c | 5 + bfd/bfd-in2.h | 25 + bfd/config.bfd | 20 +- bfd/configure | 6 +- bfd/configure.ac | 6 +- bfd/cpu-arc.c | 79 +- bfd/cpu-arc64.c | 75 ++ bfd/{elf32-arc.c => elfnn-arc.c} | 1486 +++++++++++++++++++----------- bfd/libbfd.h | 22 + bfd/reloc.c | 44 + bfd/targets.c | 6 + 17 files changed, 1593 insertions(+), 825 deletions(-) create mode 100644 bfd/arc-plt.c create mode 100644 bfd/cpu-arc64.c rename bfd/{elf32-arc.c => elfnn-arc.c} (68%) diff --git a/bfd/Makefile.am b/bfd/Makefile.am index 378c13198d6..d8b1cdfeb19 100644 --- a/bfd/Makefile.am +++ b/bfd/Makefile.am @@ -99,6 +99,7 @@ ALL_MACHINES = \ cpu-alpha.lo \ cpu-amdgcn.lo \ cpu-arc.lo \ + cpu-arc64.lo \ cpu-arm.lo \ cpu-avr.lo \ cpu-bfin.lo \ @@ -183,6 +184,7 @@ ALL_MACHINES_CFILES = \ cpu-alpha.c \ cpu-amdgcn.c \ cpu-arc.c \ + cpu-arc64.c \ cpu-arm.c \ cpu-avr.c \ cpu-bfin.c \ @@ -265,6 +267,7 @@ ALL_MACHINES_CFILES = \ # The .o files needed by all of the 32 bit vectors that are configured into # target_vector in targets.c if configured with --enable-targets=all. BFD32_BACKENDS = \ + arc-plt.lo \ aout-cris.lo \ aout-ns32k.lo \ aout32.lo \ @@ -400,6 +403,7 @@ BFD32_BACKENDS = \ xtensa-modules.lo BFD32_BACKENDS_CFILES = \ + arc-plt.c \ aout-cris.c \ aout-ns32k.c \ aout32.c \ @@ -432,7 +436,6 @@ BFD32_BACKENDS_CFILES = \ elf-vxworks.c \ elf.c \ elf32-am33lin.c \ - elf32-arc.c \ elf32-arm.c \ elf32-avr.c \ elf32-bfin.c \ @@ -545,6 +548,7 @@ BFD64_BACKENDS = \ coff-x86_64.lo \ coff64-rs6000.lo \ elf32-aarch64.lo \ + elf32-arc64.lo \ elf32-ia64.lo \ elf32-kvx.lo \ elf32-loongarch.lo \ @@ -553,6 +557,7 @@ BFD64_BACKENDS = \ elf32-score.lo \ elf32-score7.lo \ elf64-aarch64.lo \ + elf64-arc64.lo \ elf64-alpha.lo \ elf64-amdgcn.lo \ elf64-bpf.lo \ @@ -687,6 +692,7 @@ SOURCE_CFILES = \ BUILD_CFILES = \ elf32-aarch64.c elf64-aarch64.c \ + elf32-arc.c elf64-arc64.c elf32-arc64.c\ elf32-kvx.c elf64-kvx.c \ elf32-ia64.c elf64-ia64.c \ elf32-loongarch.c elf64-loongarch.c \ @@ -849,6 +855,21 @@ elf64-aarch64.c : elfnn-aarch64.c $(AM_V_at)echo "#line 1 \"$<\"" > $@ $(AM_V_GEN)$(SED) -e s/NN/64/g < $< >> $@ +elf32-arc.c : elfnn-arc.c + rm -f elf32-arc.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/32/g -e s/AA//g < $< >> $@ + +elf64-arc64.c : elfnn-arc.c + rm -f elf64-arc64.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/64/g -e s/AA/64/g < $< >> $@ + +elf32-arc64.c : elfnn-arc.c + rm -f elf32-arc64.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/32/g -e s/AA/64/g < $< >> $@ + elf32-ia64.c : elfnn-ia64.c $(AM_V_at)echo "#line 1 \"$<\"" > $@ $(AM_V_GEN)$(SED) -e s/NN/32/g < $< >> $@ diff --git a/bfd/Makefile.in b/bfd/Makefile.in index 8d09f6fa4af..4c396334a0e 100644 --- a/bfd/Makefile.in +++ b/bfd/Makefile.in @@ -554,6 +554,7 @@ ALL_MACHINES = \ cpu-alpha.lo \ cpu-amdgcn.lo \ cpu-arc.lo \ + cpu-arc64.lo \ cpu-arm.lo \ cpu-avr.lo \ cpu-bfin.lo \ @@ -638,6 +639,7 @@ ALL_MACHINES_CFILES = \ cpu-alpha.c \ cpu-amdgcn.c \ cpu-arc.c \ + cpu-arc64.c \ cpu-arm.c \ cpu-avr.c \ cpu-bfin.c \ @@ -721,6 +723,7 @@ ALL_MACHINES_CFILES = \ # The .o files needed by all of the 32 bit vectors that are configured into # target_vector in targets.c if configured with --enable-targets=all. BFD32_BACKENDS = \ + arc-plt.lo \ aout-cris.lo \ aout-ns32k.lo \ aout32.lo \ @@ -856,6 +859,7 @@ BFD32_BACKENDS = \ xtensa-modules.lo BFD32_BACKENDS_CFILES = \ + arc-plt.c \ aout-cris.c \ aout-ns32k.c \ aout32.c \ @@ -888,7 +892,6 @@ BFD32_BACKENDS_CFILES = \ elf-vxworks.c \ elf.c \ elf32-am33lin.c \ - elf32-arc.c \ elf32-arm.c \ elf32-avr.c \ elf32-bfin.c \ @@ -1002,6 +1005,7 @@ BFD64_BACKENDS = \ coff-x86_64.lo \ coff64-rs6000.lo \ elf32-aarch64.lo \ + elf32-arc64.lo \ elf32-ia64.lo \ elf32-kvx.lo \ elf32-loongarch.lo \ @@ -1010,6 +1014,7 @@ BFD64_BACKENDS = \ elf32-score.lo \ elf32-score7.lo \ elf64-aarch64.lo \ + elf64-arc64.lo \ elf64-alpha.lo \ elf64-amdgcn.lo \ elf64-bpf.lo \ @@ -1143,6 +1148,7 @@ SOURCE_CFILES = \ BUILD_CFILES = \ elf32-aarch64.c elf64-aarch64.c \ + elf32-arc.c elf32-arc64.c elf64-arc64.c \ elf32-kvx.c elf64-kvx.c \ elf32-ia64.c elf64-ia64.c \ elf32-loongarch.c elf64-loongarch.c \ @@ -1435,6 +1441,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aout-ns32k.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aout32.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/aout64.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arc-plt.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archive64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/archures.Plo@am__quote@ @@ -1468,6 +1475,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-alpha.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-amdgcn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arc64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-arm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-avr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cpu-bfin.Plo@am__quote@ @@ -1564,6 +1572,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-aarch64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-am33lin.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-arc.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-arc64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-arm.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-avr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf32-bfin.Plo@am__quote@ @@ -1633,6 +1642,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-aarch64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-alpha.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-amdgcn.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-arc64.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-bpf.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-gen.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/elf64-hppa.Plo@am__quote@ @@ -2351,6 +2361,21 @@ elf64-aarch64.c : elfnn-aarch64.c $(AM_V_at)echo "#line 1 \"$<\"" > $@ $(AM_V_GEN)$(SED) -e s/NN/64/g < $< >> $@ +elf32-arc.c : elfnn-arc.c + rm -f elf32-arc.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/32/g -e s/AA//g < $< >> $@ + +elf64-arc64.c : elfnn-arc.c + rm -f elf64-arc64.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/64/g -e s/AA/64/g < $< >> $@ + +elf32-arc64.c : elfnn-arc.c + rm -f elf32-arc64.c + $(AM_V_at)echo "#line 1 \"$(srcdir)/elfnn-arc.c\"" > $@ + $(AM_V_GEN)$(SED) -e s/NN/32/g -e s/AA/64/g < $< >> $@ + elf32-ia64.c : elfnn-ia64.c $(AM_V_at)echo "#line 1 \"$<\"" > $@ $(AM_V_GEN)$(SED) -e s/NN/32/g < $< >> $@ diff --git a/bfd/arc-got.h b/bfd/arc-got.h index dfa3f5b4fe0..456a2be7d29 100644 --- a/bfd/arc-got.h +++ b/bfd/arc-got.h @@ -22,9 +22,25 @@ #ifndef ARC_GOT_H #define ARC_GOT_H +/* Thread Control Block (TCB) contains at offset zero a pointer to the + dynamic thread vector dtvt for the thread. */ +#if ARCH_SIZE == 32 #define TCB_SIZE (8) - -#define align_power(addr, align) \ +#else +#define TCB_SIZE (16) +#endif + +#if ARCH_SIZE == 32 +#define GOT_ENTRY_SIZE 4 +#define write_in_got(A, B, C) bfd_put_32 (A, B, C) +#define read_from_got(A, B) bfd_get_32 (A, B) +#else +#define GOT_ENTRY_SIZE 8 +#define write_in_got(A, B, C) bfd_put_64 (A, B, C) +#define read_from_got(A, B) bfd_get_64 (A, B) +#endif + +#define align_power(addr, align) \ (((addr) + ((bfd_vma) 1 << (align)) - 1) & (-((bfd_vma) 1 << (align)))) enum tls_type_e @@ -201,7 +217,7 @@ arc_got_entry_type_for_reloc (reloc_howto_type *howto) { \ if (COND_FOR_RELOC) \ { \ - htab->srel##SECNAME->size += sizeof (Elf32_External_Rela); \ + htab->srel##SECNAME->size += RELA_SIZE; \ ARC_DEBUG ("arc_info: Added reloc space in " \ #SECNAME " section at " __FILE__ \ ":%d for symbol %s\n", \ @@ -211,7 +227,7 @@ arc_got_entry_type_for_reloc (reloc_howto_type *howto) if (H->dynindx == -1 && !H->forced_local) \ if (! bfd_elf_link_record_dynamic_symbol (info, H)) \ return false; \ - htab->s##SECNAME->size += 4; \ + htab->s##SECNAME->size += GOT_ENTRY_SIZE; \ } \ static bool @@ -230,13 +246,13 @@ arc_fill_got_info_for_reloc (enum tls_type_e type, case GOT_NORMAL: { bfd_vma offset - = ADD_SYMBOL_REF_SEC_AND_RELOC (got, bfd_link_pic (info) - || h != NULL, h); + = ADD_SYMBOL_REF_SEC_AND_RELOC (got, + bfd_link_pic (info) || h != NULL, + h); new_got_entry_to_list (list, type, offset, TLS_GOT_NONE); } break; - case GOT_TLS_GD: { bfd_vma offset @@ -262,59 +278,16 @@ arc_fill_got_info_for_reloc (enum tls_type_e type, return true; } -struct arc_static_sym_data { - bfd_vma sym_value; - const char *symbol_name; -}; - -static struct arc_static_sym_data -get_static_sym_data (unsigned long r_symndx, - Elf_Internal_Sym *local_syms, - asection **local_sections, - struct elf_link_hash_entry *h, - struct arc_relocation_data *reloc_data) -{ - static const char local_name[] = "(local)"; - struct arc_static_sym_data ret = { 0, NULL }; - - if (h != NULL) - { - BFD_ASSERT (h->root.type != bfd_link_hash_undefweak - && h->root.type != bfd_link_hash_undefined); - /* TODO: This should not be here. */ - reloc_data->sym_value = h->root.u.def.value; - reloc_data->sym_section = h->root.u.def.section; - - ret.sym_value = h->root.u.def.value - + h->root.u.def.section->output_section->vma - + h->root.u.def.section->output_offset; - - ret.symbol_name = h->root.root.string; - } - else - { - Elf_Internal_Sym *sym = local_syms + r_symndx; - asection *sec = local_sections[r_symndx]; - - ret.sym_value = sym->st_value - + sec->output_section->vma - + sec->output_offset; - - ret.symbol_name = local_name; - } - return ret; -} - static bfd_vma -relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, - enum tls_type_e type, - struct bfd_link_info * info, - bfd * output_bfd, - unsigned long r_symndx, - Elf_Internal_Sym * local_syms, - asection ** local_sections, - struct elf_link_hash_entry * h, - struct arc_relocation_data * reloc_data) +relocate_fix_got_relocs_for_got_info (struct got_entry **list_p, + enum tls_type_e type, + struct bfd_link_info *info, + bfd *output_bfd, + unsigned long r_symndx, + Elf_Internal_Sym * local_syms, + asection **local_sections, + struct elf_link_hash_entry *h, + struct arc_relocation_data *reloc_data) { struct elf_link_hash_table *htab = elf_hash_table (info); struct got_entry *entry = NULL; @@ -332,91 +305,84 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, && SYMBOL_REFERENCES_LOCAL (info, h)))) { const char ATTRIBUTE_UNUSED *symbol_name; - asection *tls_sec = elf_hash_table (info)->tls_sec; + static const char *local_name = "(local)"; + bfd_vma sym_value = 0; + asection *sec = NULL; + + if (h != NULL) + { + reloc_data->sym_value = h->root.u.def.value; + reloc_data->sym_section = h->root.u.def.section; + + sec = h->root.u.def.section; + sym_value = h->root.u.def.value; + symbol_name = h->root.root.string; + } + else + { + Elf_Internal_Sym *sym = local_syms + r_symndx; + + sec = local_sections[r_symndx]; + sym_value = sym->st_value; + symbol_name = local_name; + } if (entry && !entry->processed) { + int tcb_size = 0; + switch (entry->type) { + case GOT_TLS_IE: + tcb_size = TCB_SIZE; + /* Fall through. */ case GOT_TLS_GD: { + asection *tls_sec = elf_hash_table (info)->tls_sec; + BFD_ASSERT (tls_sec && tls_sec->output_section); - bfd_vma sec_vma = tls_sec->output_section->vma; + bfd_vma tls_vma = tls_sec->output_section->vma; + + BFD_ASSERT (sec->output_section); + sym_value += sec->output_section->vma + sec->output_offset; - if (h == NULL || h->forced_local - || !elf_hash_table (info)->dynamic_sections_created) + if (h == NULL + || h->forced_local + || !elf_hash_table (info)->dynamic_sections_created) { - struct arc_static_sym_data tmp = - get_static_sym_data (r_symndx, local_syms, local_sections, - h, reloc_data); - - bfd_put_32 (output_bfd, - tmp.sym_value - sec_vma - + (elf_hash_table (info)->dynamic_sections_created - ? 0 - : (align_power (0, - tls_sec->alignment_power))), - htab->sgot->contents + entry->offset - + (entry->existing_entries == TLS_GOT_MOD_AND_OFF - ? 4 : 0)); - - ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx " - "@ %lx, for symbol %s\n", - (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : - "GOT_TLS_IE"), - (long) (sym_value - sec_vma), - (long) (htab->sgot->output_section->vma - + htab->sgot->output_offset - + entry->offset - + (entry->existing_entries == TLS_GOT_MOD_AND_OFF - ? 4 : 0)), - tmp.symbol_name); + write_in_got + (output_bfd, + /* S - TLS_REL + { round (TCB_SIZE, align), 0 } */ + sym_value - tls_vma + + (elf_hash_table (info)->dynamic_sections_created + ? 0 : (align_power (tcb_size, + tls_sec->alignment_power))), + htab->sgot->contents + entry->offset + + (entry->existing_entries == TLS_GOT_MOD_AND_OFF + ? GOT_ENTRY_SIZE : 0)); + + ARC_DEBUG + ("arc_info: FIXED -> %s value = %#lx " + "@ %lx, for symbol %s\n", + (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : + "GOT_TLS_IE"), + (long) (sym_value - tls_vma), + (long) (htab->sgot->output_section->vma + + htab->sgot->output_offset + + entry->offset + + (entry->existing_entries == TLS_GOT_MOD_AND_OFF + ? GOT_ENTRY_SIZE : 0)), + symbol_name); } } break; - case GOT_TLS_IE: - { - BFD_ASSERT (tls_sec && tls_sec->output_section); - bfd_vma ATTRIBUTE_UNUSED sec_vma - = tls_sec->output_section->vma; - - struct arc_static_sym_data tmp = - get_static_sym_data (r_symndx, local_syms, local_sections, - h, reloc_data); - - bfd_put_32 (output_bfd, - tmp.sym_value - sec_vma - + (elf_hash_table (info)->dynamic_sections_created - ? 0 - : (align_power (TCB_SIZE, - tls_sec->alignment_power))), - htab->sgot->contents + entry->offset - + (entry->existing_entries == TLS_GOT_MOD_AND_OFF - ? 4 : 0)); - - ARC_DEBUG ("arc_info: FIXED -> %s value = %#lx " - "@ %p, for symbol %s\n", - (entry->type == GOT_TLS_GD ? "GOT_TLS_GD" : - "GOT_TLS_IE"), - (long) (sym_value - sec_vma), - (long) (htab->sgot->output_section->vma - + htab->sgot->output_offset - + entry->offset - + (entry->existing_entries == TLS_GOT_MOD_AND_OFF - ? 4 : 0)), - tmp.symbol_name); - } - break; - case GOT_NORMAL: { - bfd_vma sec_vma - = reloc_data->sym_section->output_section->vma - + reloc_data->sym_section->output_offset; - - if (h != NULL - && h->root.type == bfd_link_hash_undefweak) + if (h != NULL && + (h->root.type == bfd_link_hash_undefweak + /* FIXME! catch the undefined situation in a test. */ + || h->root.type == bfd_link_hash_undefined)) ARC_DEBUG ("arc_info: PATCHED: NOT_PATCHED " "@ %#08lx for sym %s in got offset %#lx " "(is undefweak)\n", @@ -427,12 +393,16 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, (long) entry->offset); else { - bfd_put_32 (output_bfd, - reloc_data->sym_value + sec_vma, - htab->sgot->contents + entry->offset); + BFD_ASSERT (sec->output_section); + + sym_value += sec->output_section->vma + sec->output_offset; + + write_in_got (output_bfd, + sym_value, + htab->sgot->contents + entry->offset); ARC_DEBUG ("arc_info: PATCHED: %#08lx " "@ %#08lx for sym %s in got offset %#lx\n", - (long) (reloc_data->sym_value + sec_vma), + (long) sym_value, (long) (htab->sgot->output_section->vma + htab->sgot->output_offset + entry->offset), @@ -455,7 +425,7 @@ relocate_fix_got_relocs_for_got_info (struct got_entry ** list_p, static void create_got_dynrelocs_for_single_entry (struct got_entry *list, bfd *output_bfd, - struct bfd_link_info * info, + struct bfd_link_info *info, struct elf_link_hash_entry *h) { if (list == NULL) @@ -474,8 +444,8 @@ create_got_dynrelocs_for_single_entry (struct got_entry *list, ADD_RELA (output_bfd, got, got_offset, 0, R_ARC_RELATIVE, 0); } /* Do not fully understand the side effects of this condition. - The relocation space might still being reserved. Perhaps - I should clear its value. */ + The relocation space might still being reserved. Perhaps I + should clear its value. */ else if (h != NULL && h->dynindx != -1) { ADD_RELA (output_bfd, got, got_offset, h->dynindx, R_ARC_GLOB_DAT, 0); @@ -516,12 +486,12 @@ GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = 0x0\n", bfd_vma addend = 0; if (list->type == GOT_TLS_IE) { - addend = bfd_get_32 (output_bfd, - htab->sgot->contents + got_offset); + addend = read_from_got (output_bfd, + htab->sgot->contents + got_offset); } - ADD_RELA (output_bfd, got, - got_offset + (e == TLS_GOT_MOD_AND_OFF ? 4 : 0), + ADD_RELA (output_bfd, got, got_offset + + (e == TLS_GOT_MOD_AND_OFF ? GOT_ENTRY_SIZE : 0), dynindx, (list->type == GOT_TLS_IE ? R_ARC_TLS_TPOFF : R_ARC_TLS_DTPOFF), @@ -542,13 +512,14 @@ GOT_OFFSET = %#lx, GOT_VMA = %#lx, INDEX = %ld, ADDEND = %#lx\n", static void create_got_dynrelocs_for_got_info (struct got_entry **list_p, bfd *output_bfd, - struct bfd_link_info * info, + struct bfd_link_info *info, struct elf_link_hash_entry *h) { + struct got_entry *list = *list_p; + if (list_p == NULL) return; - struct got_entry *list = *list_p; /* Traverse the list of got entries for this symbol. */ while (list) { diff --git a/bfd/arc-plt.c b/bfd/arc-plt.c new file mode 100644 index 00000000000..8dd778b58d2 --- /dev/null +++ b/bfd/arc-plt.c @@ -0,0 +1,121 @@ +/* ARC-specific support for PLT relocations. + Copyright (C) 2023 Free Software Foundation, Inc. + Contributed by Cupertino Miranda (cmiranda@synopsys.com). + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "arc-plt.h" + +#define PLT_TYPE_START(NAME) \ + const insn_hword NAME##_plt_entry[] = { +#define PLT_TYPE_END(NAME) }; +#define PLT_ENTRY(...) __VA_ARGS__, +#define PLT_ELEM(...) +#define ENTRY_RELOC(...) +#define ELEM_RELOC(...) + +#include "arc-plt.def" + +#undef PLT_TYPE_START +#undef PLT_TYPE_END +#undef PLT_ENTRY +#undef PLT_ELEM +#undef ENTRY_RELOC +#undef ELEM_RELOC + +#define PLT_TYPE_START(NAME) \ + const struct plt_reloc NAME##_plt_entry_relocs[] = { +#define PLT_TYPE_END(NAME) \ + {0, 0, 0, LAST_RELOC, 0} \ + }; +#define PLT_ENTRY(...) +#define PLT_ELEM(...) +#define ENTRY_RELOC(...) { __VA_ARGS__ }, +#define ELEM_RELOC(...) + +#include "arc-plt.def" + +#undef PLT_TYPE_START +#undef PLT_TYPE_END +#undef PLT_ENTRY +#undef PLT_ELEM +#undef ENTRY_RELOC +#undef ELEM_RELOC + + +#define PLT_TYPE_START(NAME) \ + const insn_hword NAME##_plt_elem[] = { +#define PLT_TYPE_END(NAME) }; +#define PLT_ENTRY(...) +#define PLT_ELEM(...) __VA_ARGS__, +#define ENTRY_RELOC(...) +#define ELEM_RELOC(...) + +#include "arc-plt.def" + +#undef PLT_TYPE_START +#undef PLT_TYPE_END +#undef PLT_ENTRY +#undef PLT_ELEM +#undef ENTRY_RELOC +#undef ELEM_RELOC + +#define PLT_TYPE_START(NAME) \ + const struct plt_reloc NAME##_plt_elem_relocs[] = { +#define PLT_TYPE_END(NAME) \ + {0, 0, 0, LAST_RELOC, 0} \ + }; +#define PLT_ENTRY(...) +#define PLT_ELEM(...) +#define ENTRY_RELOC(...) +#define ELEM_RELOC(...) { __VA_ARGS__ }, + +#include "arc-plt.def" + +#undef PLT_TYPE_START +#undef PLT_TYPE_END +#undef PLT_ENTRY +#undef PLT_ELEM +#undef ENTRY_RELOC +#undef ELEM_RELOC + + +#define PLT_TYPE_START(NAME) \ + { \ + .entry = &NAME##_plt_entry, \ + .entry_size = sizeof (NAME##_plt_entry), \ + .elem = &NAME##_plt_elem, \ + .elem_size = sizeof (NAME##_plt_elem), \ + .entry_relocs = NAME##_plt_entry_relocs, \ + .elem_relocs = NAME##_plt_elem_relocs +#define PLT_TYPE_END(NAME) }, +#define PLT_ENTRY(...) +#define PLT_ELEM(...) +#define ENTRY_RELOC(...) +#define ELEM_RELOC(...) +struct plt_version_t plt_versions[PLT_MAX] = + { +#include "arc-plt.def" + }; + +#undef PLT_TYPE_START +#undef PLT_TYPE_END +#undef PLT_ENTRY +#undef PLT_ELEM +#undef ENTRY_RELOC +#undef ELEM_RELOC diff --git a/bfd/arc-plt.def b/bfd/arc-plt.def index 2b602c47639..a3b32f379f0 100644 --- a/bfd/arc-plt.def +++ b/bfd/arc-plt.def @@ -1,4 +1,4 @@ -/* Arc V2 Related PLT entries. +/* Arc V2/V3 Related PLT entries. Copyright (C) 2016-2023 Free Software Foundation, Inc. Contributed by Cupertino Miranda (cmiranda@synopsys.com). @@ -19,15 +19,72 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -PLT_TYPE_START (ELF_ARCV2_PIC) - PLT_ENTRY (0x2730, 0x7f8b, 0x0000, 0x0000) /* ld %r11, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+4 */ - PLT_ENTRY (0x2730, 0x7f8a, 0x0000, 0x0000) /* ld %r10, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+8 */ - PLT_ENTRY (0x2020, 0x0280) /* j [%r10] */ - PLT_ENTRY (0x0,0x0,0x0,0x0,0x0,0x0) /* padding */ - PLT_ELEM (0x2730, 0x7f8c, 0x0000, 0x0000) /* ld %r12, [%pc,func@got] */ - PLT_ELEM (0x2021, 0x0300) /* j.d [%r12] */ - PLT_ELEM (0x240a, 0x1fc0) /* mov %r12, %pcl */ +PLT_TYPE_START (ELF_ARCV3_PIC) +/* + -- at .got.plt + 0 should be the address of .dynamic + ldl r11, [pcl, 0] .got.plt + 8 + ldl r10, [pcl, 0] .got.plt + 16 + j [r10] + padding + + 2e: 2731 ff0b 0000 0000 ldl r11,[pcl,0@s32] ;2c + 32: R_ARC_GOTPC32 f_var + 36: 2731 ff0a 0000 0000 ldl r10,[pcl,0@s32] ;34 + 3a: R_ARC_GOTPC32 f_var + 3e: 2020 0280 j [r10] +*/ + +/* ldl %r11, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+4. */ + PLT_ENTRY (0x2731, 0xff0b, 0x0000, 0x0000) +/* ldl %r10, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+8. */ + PLT_ENTRY (0x2731, 0xff0a, 0x0000, 0x0000) +/* j [%r10]. */ + PLT_ENTRY (0x2020, 0x0280) +/* padding. */ + PLT_ENTRY (0x0, 0x0, 0x0, 0x0, 0x0,0x0) + +/* + ldl r12, [pcl, 0] -- at .got.plt + 0 should be the address of .dynamic + + 46: 2731 ff0c 0000 0000 ldl r12,[pcl,0@s32] ;44 + 4a: R_ARC_GOTPC32 f_var + 4e: 2021 0300 j.d [r12] + 52: 5c0a 1fc0 movl r12,pcl +*/ + +/* ld %r12, [%pc,func@got]. */ + PLT_ELEM (0x2731, 0xff0c, 0x0000, 0x0000) +/* j.d [%r12]. */ + PLT_ELEM (0x2021, 0x0300) +/* movl %r12, %pcl. */ + PLT_ELEM (0x5c0a, 0x1fc0) + + ENTRY_RELOC (4, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 8) + ENTRY_RELOC (12, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 16) + ENTRY_RELOC (20, 32, 0xFFFFFFFF, SGOT, 0) + + ELEM_RELOC (4, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 0) + +PLT_TYPE_END (ELF_ARCV3_PIC) + + +PLT_TYPE_START (ELF_ARCV2_PIC) +/* ld %r11, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+4. */ + PLT_ENTRY (0x2730, 0x7f8b, 0x0000, 0x0000) +/* ld %r10, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+8. */ + PLT_ENTRY (0x2730, 0x7f8a, 0x0000, 0x0000) +/* j [%r10]. */ + PLT_ENTRY (0x2020, 0x0280) +/* padding. */ + PLT_ENTRY (0x0,0x0,0x0,0x0,0x0,0x0) + + /* ld %r12, [%pc,func@got]. */ + PLT_ELEM (0x2730, 0x7f8c, 0x0000, 0x0000) +/* j.d [%r12]. */ + PLT_ELEM (0x2021, 0x0300) +/* mov %r12, %pcl. */ + PLT_ELEM (0x240a, 0x1fc0) ENTRY_RELOC (4, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 4) ENTRY_RELOC (12, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 8) @@ -38,14 +95,18 @@ PLT_TYPE_START (ELF_ARCV2_PIC) PLT_TYPE_END (ELF_ARCV2_PIC) PLT_TYPE_START (ELF_ARCV2_ABS) - PLT_ENTRY (0x1600,0x700b,0x0000,0x0000) /* ld %r11, [0] */ - PLT_ENTRY (0x1600,0x700a,0x0000,0x0000) /* ld %r10, [0] */ - PLT_ENTRY (0x2020,0x0280) /* j [%r10] */ - PLT_ENTRY (0x0,0x0,0x0,0x0,0x0,0x0) /* padding */ - - PLT_ELEM (0x2730, 0x7f8c, 0x0000, 0x0000) /* ld %r12, [%pcl,func@gotpc] */ - PLT_ELEM (0x2021,0x0300) /* j.d [%r12] */ - PLT_ELEM (0x240a,0x1fc0) /* mov %r12, %pcl */ +/* ld %r11, [0]. */ + PLT_ENTRY (0x1600,0x700b,0x0000,0x0000) +/* ld %r10, [0]. */ + PLT_ENTRY (0x1600,0x700a,0x0000,0x0000) +/* j [%r10]. */ + PLT_ENTRY (0x2020,0x0280) +/* padding. */ + PLT_ENTRY (0x0,0x0,0x0,0x0,0x0,0x0) + + PLT_ELEM (0x2730, 0x7f8c, 0x0000, 0x0000) /* ld %r12, [%pcl,func@gotpc]. */ + PLT_ELEM (0x2021,0x0300) /* j.d [%r12]. */ + PLT_ELEM (0x240a,0x1fc0) /* mov %r12, %pcl. */ ENTRY_RELOC (4, 32, 0xFFFFFFFF, SGOT | MIDDLE_ENDIAN, 4) ENTRY_RELOC (12, 32, 0xFFFFFFFF, SGOT | MIDDLE_ENDIAN, 8) @@ -59,14 +120,18 @@ PLT_TYPE_END (ELF_ARCV2_ABS) /* Non Arc V2 Related PLT entries. */ PLT_TYPE_START (ELF_ARC_PIC) - PLT_ENTRY (0x2730,0x7f8b,0x0000,0x0000) /* ld %r11, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+4 */ - PLT_ENTRY (0x2730,0x7f8a,0x0000,0x0000) /* ld %r10, [pcl,0] : 0 to be replaced by -DYNAMIC@GOTPC+8 */ - PLT_ENTRY (0x2020,0x0280) /* j [%r10] */ - PLT_ENTRY (0x0,0x0) /* padding */ - - PLT_ELEM (0x2730,0x7f8c,0x0000,0x0000) /* ld %r12, [%pc,func@got] */ - PLT_ELEM (0x7c20) /* j_s.d [%r12] */ - PLT_ELEM (0x74ef) /* mov_s %r12, %pcl */ +/* ld %r11, [pcl,0] : 0 to be replaced by _DYNAMIC@GOTPC+4. */ + PLT_ENTRY (0x2730,0x7f8b,0x0000,0x0000) +/* ld %r10, [pcl,0] : 0 to be replaced by -DYNAMIC@GOTPC+8. */ + PLT_ENTRY (0x2730,0x7f8a,0x0000,0x0000) +/* j [%r10]. */ + PLT_ENTRY (0x2020,0x0280) +/* padding. */ + PLT_ENTRY (0x0,0x0) + + PLT_ELEM (0x2730,0x7f8c,0x0000,0x0000) /* ld %r12, [%pc,func@got]. */ + PLT_ELEM (0x7c20) /* j_s.d [%r12]. */ + PLT_ELEM (0x74ef) /* mov_s %r12, %pcl. */ ENTRY_RELOC (4, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 4) ENTRY_RELOC (12, 32, 0xFFFFFFFF, SGOT | RELATIVE_INSN_32 | MIDDLE_ENDIAN, 8) @@ -77,13 +142,13 @@ PLT_TYPE_START (ELF_ARC_PIC) PLT_TYPE_END (ELF_ARC_PIC) PLT_TYPE_START (ELF_ARC_ABS) - PLT_ENTRY (0x1600,0x700b,0x0000,0x0000) /* ld %r11, [0] */ - PLT_ENTRY (0x1600,0x700a,0x0000,0x0000) /* ld %r10, [0] */ - PLT_ENTRY (0x2020,0x0280) /* j [%r10] */ - PLT_ENTRY (0x0,0x0) /* padding */ + PLT_ENTRY (0x1600,0x700b,0x0000,0x0000) /* ld %r11, [0]. */ + PLT_ENTRY (0x1600,0x700a,0x0000,0x0000) /* ld %r10, [0]. */ + PLT_ENTRY (0x2020,0x0280) /* j [%r10]. */ + PLT_ENTRY (0x0,0x0) /* padding. */ - PLT_ELEM (0x2730,0x7f8c,0x0000,0x0000) /* ld %r12, [%pc,func@gotpc] */ - PLT_ELEM (0x7c20,0x74ef) /* mov_s %r12, %pcl */ + PLT_ELEM (0x2730,0x7f8c,0x0000,0x0000) /* ld %r12, [%pc,func@gotpc]. */ + PLT_ELEM (0x7c20,0x74ef) /* mov_s %r12, %pcl. */ ENTRY_RELOC (4, 32, 0xFFFFFFFF, SGOT | MIDDLE_ENDIAN, 4) ENTRY_RELOC (12, 32, 0xFFFFFFFF, SGOT | MIDDLE_ENDIAN, 8) diff --git a/bfd/arc-plt.h b/bfd/arc-plt.h index e11b72eeadd..ad1b86fc9f8 100644 --- a/bfd/arc-plt.h +++ b/bfd/arc-plt.h @@ -22,6 +22,9 @@ #ifndef ARC_PLT_H #define ARC_PLT_H +#include "sysdep.h" +#include "bfd.h" + /* Instructions appear in memory as a sequence of half-words (16 bit); individual half-words are represented on the target in target byte order. We use 'unsigned short' on the host to represent the PLT templates, @@ -92,97 +95,20 @@ struct plt_version_t }; #define PLT_TYPE_START(NAME) \ - const insn_hword NAME##_plt_entry[] = { -#define PLT_TYPE_END(NAME) }; -#define PLT_ENTRY(...) __VA_ARGS__, -#define PLT_ELEM(...) -#define ENTRY_RELOC(...) -#define ELEM_RELOC(...) - -#include "arc-plt.def" - -#undef PLT_TYPE_START -#undef PLT_TYPE_END -#undef PLT_ENTRY -#undef PLT_ELEM -#undef ENTRY_RELOC -#undef ELEM_RELOC - -#define PLT_TYPE_START(NAME) \ - const struct plt_reloc NAME##_plt_entry_relocs[] = { -#define PLT_TYPE_END(NAME) \ - {0, 0, 0, LAST_RELOC, 0} \ - }; -#define PLT_ENTRY(...) -#define PLT_ELEM(...) -#define ENTRY_RELOC(...) { __VA_ARGS__ }, -#define ELEM_RELOC(...) + extern const insn_hword NAME##_plt_entry[]; \ + extern const struct plt_reloc NAME##_plt_entry_relocs[]; \ + extern const insn_hword NAME##_plt_elem[]; \ + extern const struct plt_reloc NAME##_plt_elem_relocs[]; -#include "arc-plt.def" -#undef PLT_TYPE_START -#undef PLT_TYPE_END -#undef PLT_ENTRY -#undef PLT_ELEM -#undef ENTRY_RELOC -#undef ELEM_RELOC - - -#define PLT_TYPE_START(NAME) \ - const insn_hword NAME##_plt_elem[] = { -#define PLT_TYPE_END(NAME) }; -#define PLT_ENTRY(...) -#define PLT_ELEM(...) __VA_ARGS__, -#define ENTRY_RELOC(...) -#define ELEM_RELOC(...) - -#include "arc-plt.def" - -#undef PLT_TYPE_START -#undef PLT_TYPE_END -#undef PLT_ENTRY -#undef PLT_ELEM -#undef ENTRY_RELOC -#undef ELEM_RELOC - -#define PLT_TYPE_START(NAME) \ - const struct plt_reloc NAME##_plt_elem_relocs[] = { -#define PLT_TYPE_END(NAME) \ - {0, 0, 0, LAST_RELOC, 0} \ - }; -#define PLT_ENTRY(...) -#define PLT_ELEM(...) -#define ENTRY_RELOC(...) -#define ELEM_RELOC(...) { __VA_ARGS__ }, - -#include "arc-plt.def" - -#undef PLT_TYPE_START -#undef PLT_TYPE_END -#undef PLT_ENTRY -#undef PLT_ELEM -#undef ENTRY_RELOC -#undef ELEM_RELOC - - -#define PLT_TYPE_START(NAME) \ - { \ - .entry = &NAME##_plt_entry, \ - .entry_size = sizeof (NAME##_plt_entry), \ - .elem = &NAME##_plt_elem, \ - .elem_size = sizeof (NAME##_plt_elem), \ - .entry_relocs = NAME##_plt_entry_relocs, \ - .elem_relocs = NAME##_plt_elem_relocs -#define PLT_TYPE_END(NAME) }, +#define PLT_TYPE_END(NAME) #define PLT_ENTRY(...) #define PLT_ELEM(...) #define ENTRY_RELOC(...) #define ELEM_RELOC(...) -const struct plt_version_t plt_versions[PLT_MAX] = { #include "arc-plt.def" -}; #undef PLT_TYPE_START #undef PLT_TYPE_END #undef PLT_ENTRY @@ -190,5 +116,6 @@ const struct plt_version_t plt_versions[PLT_MAX] = { #undef ENTRY_RELOC #undef ELEM_RELOC +extern struct plt_version_t plt_versions[PLT_MAX]; -#endif /* ARC_PLT_H */ +#endif diff --git a/bfd/archures.c b/bfd/archures.c index b59979e60ac..b0c1e3e70bd 100644 --- a/bfd/archures.c +++ b/bfd/archures.c @@ -361,6 +361,9 @@ DESCRIPTION .#define bfd_mach_arc_arc601 4 .#define bfd_mach_arc_arc700 3 .#define bfd_mach_arc_arcv2 5 +. bfd_arch_arc64, {* ARCv3 32/64 Cores. *} +.#define bfd_mach_arcv3_64 1 +.#define bfd_mach_arcv3_32 2 . bfd_arch_m32c, {* Renesas M16C/M32C. *} .#define bfd_mach_m16c 0x75 .#define bfd_mach_m32c 0x78 @@ -632,6 +635,7 @@ extern const bfd_arch_info_type bfd_aarch64_arch; extern const bfd_arch_info_type bfd_alpha_arch; extern const bfd_arch_info_type bfd_amdgcn_arch; extern const bfd_arch_info_type bfd_arc_arch; +extern const bfd_arch_info_type bfd_arc64_arch; extern const bfd_arch_info_type bfd_arm_arch; extern const bfd_arch_info_type bfd_avr_arch; extern const bfd_arch_info_type bfd_bfin_arch; @@ -721,6 +725,7 @@ static const bfd_arch_info_type * const bfd_archures_list[] = &bfd_alpha_arch, &bfd_amdgcn_arch, &bfd_arc_arch, + &bfd_arc64_arch, &bfd_arm_arch, &bfd_avr_arch, &bfd_bfin_arch, diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 1c4f75ae244..991344adf5c 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1617,6 +1617,9 @@ enum bfd_architecture #define bfd_mach_arc_arc601 4 #define bfd_mach_arc_arc700 3 #define bfd_mach_arc_arcv2 5 + bfd_arch_arc64, /* ARCv3 32/64 Cores. */ +#define bfd_mach_arcv3_64 1 +#define bfd_mach_arcv3_32 2 bfd_arch_m32c, /* Renesas M16C/M32C. */ #define bfd_mach_m16c 0x75 #define bfd_mach_m32c 0x78 @@ -4383,6 +4386,7 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARC_16, BFD_RELOC_ARC_24, BFD_RELOC_ARC_32, + BFD_RELOC_ARC_64, BFD_RELOC_ARC_N8, BFD_RELOC_ARC_N16, BFD_RELOC_ARC_N24, @@ -4447,6 +4451,27 @@ pc-relative or some form of GOT-indirect relocation. */ BFD_RELOC_ARC_S21H_PCREL_PLT, BFD_RELOC_ARC_NPS_CMEM16, BFD_RELOC_ARC_JLI_SECTOFF, + BFD_RELOC_ARC_S7H_PCREL, + BFD_RELOC_ARC_S8H_PCREL, + BFD_RELOC_ARC_S9H_PCREL, + BFD_RELOC_ARC_S10H_PCREL, + BFD_RELOC_ARC_S13H_PCREL, + BFD_RELOC_ARC_ALIGN, + BFD_RELOC_ARC_ADD8, + BFD_RELOC_ARC_ADD16, + BFD_RELOC_ARC_SUB8, + BFD_RELOC_ARC_SUB16, + BFD_RELOC_ARC_SUB32, + BFD_RELOC_ARC_LO32, + BFD_RELOC_ARC_HI32, + BFD_RELOC_ARC_LO32_ME, + BFD_RELOC_ARC_HI32_ME, + BFD_RELOC_ARC_N64, + BFD_RELOC_ARC_SDA_LDST3, + BFD_RELOC_ARC_NLO32, + BFD_RELOC_ARC_NLO32_ME, + BFD_RELOC_ARC_PCLO32_ME_2, + BFD_RELOC_ARC_PLT34, /* ADI Blackfin 16 bit immediate absolute reloc. */ BFD_RELOC_BFIN_16_IMM, diff --git a/bfd/config.bfd b/bfd/config.bfd index 08129e6a8cb..861a520a752 100644 --- a/bfd/config.bfd +++ b/bfd/config.bfd @@ -180,7 +180,8 @@ case "${targ_cpu}" in aarch64*) targ_archs="bfd_aarch64_arch bfd_arm_arch";; alpha*) targ_archs=bfd_alpha_arch ;; am33_2.0*) targ_archs=bfd_mn10300_arch ;; -arc*) targ_archs=bfd_arc_arch ;; +arc|arceb) targ_archs=bfd_arc_arch ;; +arc64|arc32) targ_archs=bfd_arc64_arch ;; arm*) targ_archs=bfd_arm_arch ;; amdgcn*) targ_archs=bfd_amdgcn_arch ;; bfin*) targ_archs=bfd_bfin_arch ;; @@ -353,16 +354,29 @@ case "${targ}" in targ_defvec=am33_elf32_linux_vec ;; - arc*eb-*-elf* | arc*eb-*-linux*) + arceb-*-elf* | arceb-*-linux*) targ_defvec=arc_elf32_be_vec targ_selvecs=arc_elf32_le_vec ;; - arc*-*-elf* | arc*-*-linux*) + arc-*-elf* | arc-*-linux*) targ_defvec=arc_elf32_le_vec targ_selvecs=arc_elf32_be_vec ;; +#ifdef BFD64 + arc64-*-*) + targ_defvec=arc64_elf64_le_vec + targ_selvecs=arc64_elf32_le_vec + want64=true + ;; + arc32-*-*) + targ_defvec=arc64_elf32_le_vec + targ_selvecs=arc64_elf64_le_vec + want64=true + ;; +#endif + arm-*-darwin*) targ_defvec=arm_mach_o_vec targ_selvecs="mach_o_le_vec mach_o_be_vec mach_o_fat_vec" diff --git a/bfd/configure b/bfd/configure index f0a07ff675f..f30ac5b25f4 100755 --- a/bfd/configure +++ b/bfd/configure @@ -13883,8 +13883,10 @@ do aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; aout_vec) tb="$tb host-aout.lo aout32.lo" ;; - arc_elf32_be_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;; - arc_elf32_le_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;; + arc_elf32_be_vec) tb="$tb arc-plt.lo elf32-arc.lo elf32.lo $elf" ;; + arc_elf32_le_vec) tb="$tb arc-plt.lo elf32-arc.lo elf32.lo $elf" ;; + arc64_elf64_le_vec) tb="$tb arc-plt.lo elf64-arc64.lo elf64.lo $elf"; target_size=64 ;; + arc64_elf32_le_vec) tb="$tb arc-plt.lo elf32-arc64.lo elf32.lo $elf"; target_size=64 ;; arm_elf32_be_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; arm_elf32_le_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; arm_elf32_fdpic_be_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; diff --git a/bfd/configure.ac b/bfd/configure.ac index d1e7e3a4bf3..64334743ce3 100644 --- a/bfd/configure.ac +++ b/bfd/configure.ac @@ -419,8 +419,10 @@ do aout0_be_vec) tb="$tb aout0.lo aout32.lo" ;; aout64_vec) tb="$tb demo64.lo aout64.lo"; target_size=64 ;; aout_vec) tb="$tb host-aout.lo aout32.lo" ;; - arc_elf32_be_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;; - arc_elf32_le_vec) tb="$tb elf32-arc.lo elf32.lo $elf" ;; + arc_elf32_be_vec) tb="$tb arc-plt.lo elf32-arc.lo elf32.lo $elf" ;; + arc_elf32_le_vec) tb="$tb arc-plt.lo elf32-arc.lo elf32.lo $elf" ;; + arc64_elf64_le_vec) tb="$tb arc-plt.lo elf64-arc64.lo elf64.lo $elf"; target_size=64 ;; + arc64_elf32_le_vec) tb="$tb arc-plt.lo elf32-arc64.lo elf32.lo $elf"; target_size=64 ;; arm_elf32_be_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; arm_elf32_le_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; arm_elf32_fdpic_be_vec) tb="$tb elf32-arm.lo elf32.lo elf-nacl.lo elf-vxworks.lo $elf" ;; diff --git a/bfd/cpu-arc.c b/bfd/cpu-arc.c index 390a69dc2a7..a5e0f80a0cc 100644 --- a/bfd/cpu-arc.c +++ b/bfd/cpu-arc.c @@ -26,51 +26,53 @@ static const bfd_arch_info_type * arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b); -#define ARC(mach, print_name, default_p, next) \ - { \ - 32, /* Bits in a word. */ \ - 32, /* Bits in an address. */ \ - 8, /* Bits in a byte. */ \ - bfd_arch_arc, \ - mach, \ - "arc", \ - print_name, \ - 4, /* Section alignment power. */ \ - default_p, \ - arc_compatible, \ - bfd_default_scan, \ - bfd_arch_default_fill, \ - next, \ - 0 /* Maximum offset of a reloc from the start of an insn. */ \ - } +#define ARC(BITS_WORD, BITS_ADDR, MACH, PRINT_NAME, DEFAULT_P, NEXT) \ +{ \ + BITS_WORD, /* 32 bits in a word. */ \ + BITS_ADDR, /* 32 bits in an address. */ \ + 8, /* 8 bits in a byte. */ \ + bfd_arch_arc, \ + MACH, \ + "arc", \ + PRINT_NAME, \ + 4, /* section alignment power. */ \ + DEFAULT_P, \ + arc_compatible, \ + bfd_default_scan, \ + bfd_arch_default_fill, \ + NEXT, \ + 0 /* Maximum offset of a reloc from the start of an insn. */ \ +} static const bfd_arch_info_type arch_info_struct[] = { - ARC (bfd_mach_arc_arc600, "A6" , false, &arch_info_struct[1]), - ARC (bfd_mach_arc_arc601, "ARC601", false, &arch_info_struct[2]), - ARC (bfd_mach_arc_arc700, "ARC700", false, &arch_info_struct[3]), - ARC (bfd_mach_arc_arc700, "A7", false, &arch_info_struct[4]), - ARC (bfd_mach_arc_arcv2, "ARCv2", false, &arch_info_struct[5]), - ARC (bfd_mach_arc_arcv2, "EM", false, &arch_info_struct[6]), - ARC (bfd_mach_arc_arcv2, "HS", false, NULL), + ARC (32, 32, bfd_mach_arc_arc600, "A6" , false, &arch_info_struct[1]), + ARC (32, 32, bfd_mach_arc_arc601, "ARC601", false, &arch_info_struct[2]), + ARC (32, 32, bfd_mach_arc_arc700, "ARC700", false, &arch_info_struct[3]), + ARC (32, 32, bfd_mach_arc_arc700, "A7", false, &arch_info_struct[4]), + ARC (32, 32, bfd_mach_arc_arcv2, "ARCv2", false, &arch_info_struct[5]), + ARC (32, 32, bfd_mach_arc_arcv2, "EM", false, &arch_info_struct[6]), + ARC (32, 32, bfd_mach_arc_arcv2, "HS", false, NULL), }; const bfd_arch_info_type bfd_arc_arch = - ARC (bfd_mach_arc_arc600, "ARC600", true, &arch_info_struct[0]); - -/* ARC-specific "compatible" function. The general rule is that if A and B are - compatible, then this function should return architecture that is more - "feature-rich", that is, can run both A and B. ARCv2, EM and HS all has - same mach number, so bfd_default_compatible assumes they are the same, and - returns an A. That causes issues with GDB, because GDB assumes that if - machines are compatible, then "compatible ()" always returns same machine - regardless of argument order. As a result GDB gets confused because, for - example, compatible (ARCv2, EM) returns ARCv2, but compatible (EM, ARCv2) - returns EM, hence GDB is not sure if they are compatible and prints a - warning. */ + ARC (32, 32, bfd_mach_arc_arc600, "ARC600", true, &arch_info_struct[0]); + +/* ARC-specific "compatible" function. The general rule is that if A + and B are compatible, then this function should return architecture + that is more "feature-rich", that is, can run both A and B. ARCv2, + EM and HS all has same mach number, so bfd_default_compatible + assumes they are the same, and returns an A. That causes issues + with GDB, because GDB assumes that if machines are compatible, then + "compatible ()" always returns same machine regardless of argument + order. As a result GDB gets confused because, for example, + compatible (ARCv2, EM) returns ARCv2, but compatible (EM, ARCv2) + returns EM, hence GDB is not sure if they are compatible and prints + a warning. */ static const bfd_arch_info_type * -arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) +arc_compatible (const bfd_arch_info_type *a ATTRIBUTE_UNUSED, + const bfd_arch_info_type *b ATTRIBUTE_UNUSED) { const bfd_arch_info_type * const em = &arch_info_struct[5]; const bfd_arch_info_type * const hs = &arch_info_struct[6]; @@ -84,9 +86,6 @@ arc_compatible (const bfd_arch_info_type *a, const bfd_arch_info_type *b) if (a->arch != b->arch) return NULL; - if (a->bits_per_word != b->bits_per_word) - return NULL; - /* ARCv2|EM and EM. */ if ((a->mach == bfd_mach_arc_arcv2 && b == em) || (b->mach == bfd_mach_arc_arcv2 && a == em)) diff --git a/bfd/cpu-arc64.c b/bfd/cpu-arc64.c new file mode 100644 index 00000000000..a1c3a2e23b9 --- /dev/null +++ b/bfd/cpu-arc64.c @@ -0,0 +1,75 @@ +/* BFD support for the ARC64 processor + Copyright (C) 2023 Free Software Foundation, Inc. + + This file is part of BFD, the Binary File Descriptor library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#include "sysdep.h" +#include "bfd.h" +#include "libbfd.h" + +/* ARC64-specific "compatible" function. The general rule is that if + A and B are compatible, then this function should return + architecture that is more "feature-rich", that is, can run both A + and B. */ + +static const bfd_arch_info_type * +compatible (const bfd_arch_info_type *a ATTRIBUTE_UNUSED, + const bfd_arch_info_type *b ATTRIBUTE_UNUSED) +{ + /* If a & b are for different architecture we can do nothing. */ + if (a->arch != b->arch) + return NULL; + + /* If a & b are for the same machine then all is well. */ + if (a->mach == b->mach) + return a; + + /* Otherwise if either a or b is the 'default' machine + then it can be polymorphed into the other. */ + if (a->the_default) + return b; + + if (b->the_default) + return a; + + return NULL; +} + +#define ARC64(WORDSIZE, MACH, PRINT_NAME, DEFAULT_P, NEXT) \ + { \ + WORDSIZE, /* 64/32 bits in a word. */ \ + WORDSIZE, /* 64/32 bits in an address. */ \ + 8, /* 8 bits in a byte. */ \ + bfd_arch_arc64, \ + MACH, \ + "arc64", \ + PRINT_NAME, \ + 4, /* section alignment power. */ \ + DEFAULT_P, \ + compatible, \ + bfd_default_scan, \ + bfd_arch_default_fill, \ + NEXT, \ + 0 /* Maximum offset of a reloc from the start of an insn. */ \ + } + +static const bfd_arch_info_type bfd_arc64_arch_32 = + ARC64 (32, bfd_mach_arcv3_32, "arc64:32", false, NULL); + +const bfd_arch_info_type bfd_arc64_arch = + ARC64 (64, bfd_mach_arcv3_64, "arc64:64", true, &bfd_arc64_arch_32); diff --git a/bfd/elf32-arc.c b/bfd/elfnn-arc.c similarity index 68% rename from bfd/elf32-arc.c rename to bfd/elfnn-arc.c index ac9970545c3..04fce7eb6e0 100644 --- a/bfd/elf32-arc.c +++ b/bfd/elfnn-arc.c @@ -27,13 +27,43 @@ #include "libiberty.h" #include "opcode/arc-func.h" #include "opcode/arc.h" + +#define RELA_SIZE sizeof(ElfNN_External_Rela) + #include "arc-plt.h" -#define FEATURE_LIST_NAME bfd_feature_list -#define CONFLICT_LIST bfd_conflict_list +#define FEATURE_LIST_NAME bfdNN_feature_list +#define CONFLICT_LIST bfdNN_conflict_list #include "opcode/arc-attrs.h" -/* #define ARC_ENABLE_DEBUG 1 */ +/* Possible ARC architectures. */ +#define ARC 0 +#define ARC32 1 +#define ARC64 2 + +/* Arc's architecture size. */ +#define ARCH_SIZE NN + +/* Arc's architecture type. */ +#define ARCH_TYPE ARCAA + +/* Arc's BFD backend. There are two different backends, one for + ARCv1/v2 and the second for the ARCv3/64/32. They are + incompatible. */ +#define ARC_BFD_ARCH bfd_arch_arcAA + +/* The name of the dynamic interpreter. This is put in the .interp + section. */ + +#define ELF64_DYNAMIC_INTERPRETER "/lib/ld.so.1" +#define ELF32_DYNAMIC_INTERPRETER "/sbin/ld-uClibc.so" + +#define LOG_FILE_ALIGN (ARCH_SIZE == 32 ? 2 : 3) + +/* Do not enable this unless you know what you are doing. + Code under this macro is not safe for production. + #define ARC_ENABLE_DEBUG 1 */ + #ifdef ARC_ENABLE_DEBUG static const char * name_for_global_symbol (struct elf_link_hash_entry *h) @@ -48,26 +78,27 @@ name_for_global_symbol (struct elf_link_hash_entry *h) #define ARC_DEBUG(...) #endif - #define ADD_RELA(BFD, SECTION, OFFSET, SYM_IDX, TYPE, ADDEND) \ { \ struct elf_link_hash_table *_htab = elf_hash_table (info); \ Elf_Internal_Rela _rel; \ bfd_byte * _loc; \ + const struct elf_backend_data *bed; \ + bed = get_elf_backend_data (BFD); \ \ if (_htab->dynamic_sections_created) \ { \ BFD_ASSERT (_htab->srel##SECTION &&_htab->srel##SECTION->contents); \ _loc = _htab->srel##SECTION->contents \ + ((_htab->srel##SECTION->reloc_count) \ - * sizeof (Elf32_External_Rela)); \ + * sizeof (ElfNN_External_Rela)); \ _htab->srel##SECTION->reloc_count++; \ _rel.r_addend = ADDEND; \ _rel.r_offset = (_htab->s##SECTION)->output_section->vma \ + (_htab->s##SECTION)->output_offset + OFFSET; \ BFD_ASSERT ((long) SYM_IDX != -1); \ - _rel.r_info = ELF32_R_INFO (SYM_IDX, TYPE); \ - bfd_elf32_swap_reloca_out (BFD, &_rel, _loc); \ + _rel.r_info = ELFNN_R_INFO (SYM_IDX, TYPE); \ + bed->s->swap_reloca_out (BFD, &_rel, _loc); \ } \ } @@ -195,9 +226,11 @@ struct elf_arc_link_hash_entry #define arc_bfd_get_8(A,B,C) bfd_get_8(A,B) #define arc_bfd_get_16(A,B,C) bfd_get_16(A,B) #define arc_bfd_get_32(A,B,C) bfd_get_32(A,B) +#define arc_bfd_get_64(A,B,C) bfd_get_64(A,B) #define arc_bfd_put_8(A,B,C,D) bfd_put_8(A,B,C) #define arc_bfd_put_16(A,B,C,D) bfd_put_16(A,B,C) #define arc_bfd_put_32(A,B,C,D) bfd_put_32(A,B,C) +#define arc_bfd_put_64(A,B,C,D) bfd_put_64(A,B,C) static bfd_reloc_status_type @@ -230,10 +263,10 @@ arc_elf_reloc (bfd *abfd ATTRIBUTE_UNUSED, TYPE = VALUE, enum howto_list -{ + { #include "elf/arc-reloc.def" - HOWTO_LIST_LAST -}; + HOWTO_LIST_LAST + }; #undef ARC_RELOC_HOWTO @@ -243,7 +276,7 @@ enum howto_list "R_" #TYPE, false, 0, 0, false), static struct reloc_howto_struct elf_arc_howto_table[] = -{ + { #include "elf/arc-reloc.def" /* Example of what is generated by the preprocessor. Currently kept as an example. @@ -282,17 +315,6 @@ arc_elf_howto_init (void) } #undef ARC_RELOC_HOWTO - -#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \ - [TYPE] = VALUE, - -const int howto_table_lookup[] = -{ -#include "elf/arc-reloc.def" -}; - -#undef ARC_RELOC_HOWTO - static reloc_howto_type * arc_elf_howto (unsigned int r_type) { @@ -327,7 +349,7 @@ elf_arc_link_hash_newfunc (struct bfd_hash_entry *entry, subclass. */ if (ret == NULL) ret = (struct elf_arc_link_hash_entry *) - bfd_hash_allocate (table, sizeof (struct elf_arc_link_hash_entry)); + bfd_hash_allocate (table, sizeof (struct elf_arc_link_hash_entry)); if (ret == NULL) return (struct bfd_hash_entry *) ret; @@ -356,8 +378,9 @@ static struct bfd_link_hash_table * arc_elf_link_hash_table_create (bfd *abfd) { struct elf_arc_link_hash_table *ret; + bfd_size_type amt = sizeof (struct elf_arc_link_hash_table); - ret = (struct elf_arc_link_hash_table *) bfd_zmalloc (sizeof (*ret)); + ret = (struct elf_arc_link_hash_table *) bfd_zmalloc (amt); if (ret == NULL) return NULL; @@ -379,24 +402,27 @@ arc_elf_link_hash_table_create (bfd *abfd) { BFD_RELOC_##TYPE, R_##TYPE }, static const struct arc_reloc_map arc_reloc_map[] = -{ + { #include "elf/arc-reloc.def" - {BFD_RELOC_NONE, R_ARC_NONE}, - {BFD_RELOC_8, R_ARC_8}, - {BFD_RELOC_16, R_ARC_16}, - {BFD_RELOC_24, R_ARC_24}, - {BFD_RELOC_32, R_ARC_32}, -}; + {BFD_RELOC_NONE, R_ARC_NONE}, + {BFD_RELOC_8, R_ARC_8}, + {BFD_RELOC_16, R_ARC_16}, + {BFD_RELOC_24, R_ARC_24}, + {BFD_RELOC_32, R_ARC_32}, + {BFD_RELOC_64, R_ARC_64}, + }; #undef ARC_RELOC_HOWTO -typedef ATTRIBUTE_UNUSED unsigned (*replace_func) (unsigned, int ATTRIBUTE_UNUSED); +typedef ATTRIBUTE_UNUSED +bfd_vma (*replace_func) (bfd_vma, bfd_vma ATTRIBUTE_UNUSED); -#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \ - case TYPE: \ - func = RELOC_FUNCTION; \ - break; +#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, \ + RELOC_FUNCTION, OVERFLOW, FORMULA) \ + case TYPE: \ + func = (void *) RELOC_FUNCTION; \ + break; static replace_func get_replace_function (bfd *abfd, unsigned int r_type) @@ -405,7 +431,7 @@ get_replace_function (bfd *abfd, unsigned int r_type) switch (r_type) { - #include "elf/arc-reloc.def" +#include "elf/arc-reloc.def" } if (func == replace_bits24 && bfd_big_endian (abfd)) @@ -416,7 +442,7 @@ get_replace_function (bfd *abfd, unsigned int r_type) #undef ARC_RELOC_HOWTO static reloc_howto_type * -arc_elf32_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, +arc_elfNN_bfd_reloc_type_lookup (bfd * abfd ATTRIBUTE_UNUSED, bfd_reloc_code_real_type code) { unsigned int i; @@ -503,7 +529,7 @@ arc_elf_copy_private_bfd_data (bfd *ibfd, bfd *obfd) } static reloc_howto_type * -bfd_elf32_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, +bfd_elfNN_bfd_reloc_name_lookup (bfd * abfd ATTRIBUTE_UNUSED, const char *r_name) { unsigned int i; @@ -525,7 +551,7 @@ arc_info_to_howto_rel (bfd * abfd, { unsigned int r_type; - r_type = ELF32_R_TYPE (dst->r_info); + r_type = ELFNN_R_TYPE (dst->r_info); if (r_type >= (unsigned int) R_ARC_max) { /* xgettext:c-format */ @@ -536,7 +562,7 @@ arc_info_to_howto_rel (bfd * abfd, } cache_ptr->howto = arc_elf_howto (r_type); - return true; + return cache_ptr->howto != NULL; } /* Extract CPU features from an NTBS. */ @@ -549,14 +575,14 @@ arc_extract_features (const char *p) if (!p) return 0; - for (i = 0; i < ARRAY_SIZE (bfd_feature_list); i++) + for (i = 0; i < ARRAY_SIZE (FEATURE_LIST_NAME); i++) { - char *t = strstr (p, bfd_feature_list[i].attr); - unsigned l = strlen (bfd_feature_list[i].attr); + char *t = strstr (p, FEATURE_LIST_NAME[i].attr); + unsigned l = strlen (FEATURE_LIST_NAME[i].attr); if ((t != NULL) && (t[l] == ',' || t[l] == '\0')) - r |= bfd_feature_list[i].feature; + r |= FEATURE_LIST_NAME[i].feature; } return r; @@ -629,20 +655,21 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) case Tag_ARC_PCS_config: if (out_attr[i].i == 0) out_attr[i].i = in_attr[i].i; - else if (in_attr[i].i != 0 && out_attr[i].i != in_attr[i].i) + else if ((in_attr[i].i & 0xff) != 0 + && ((out_attr[i].i & 0xff) != (in_attr[i].i & 0xff))) { const char *tagval[] = { "Absent", "Bare-metal/mwdt", - "Bare-metal/newlib", "Linux/uclibc", - "Linux/glibc" }; - BFD_ASSERT (in_attr[i].i < 5); - BFD_ASSERT (out_attr[i].i < 5); + "Bare-metal/newlib", "Linux/uclibc", + "Linux/glibc" }; + BFD_ASSERT ((in_attr[i].i & 0xff) < 5); + BFD_ASSERT ((out_attr[i].i & 0xff) < 5); /* It's sometimes ok to mix different configs, so this is only a warning. */ _bfd_error_handler (_("warning: %pB: conflicting platform configuration " "%s with %s"), ibfd, - tagval[in_attr[i].i], - tagval[out_attr[i].i]); + tagval[in_attr[i].i & 0xff], + tagval[out_attr[i].i & 0xff]); } break; @@ -653,7 +680,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) && ((out_attr[i].i + in_attr[i].i) < 6)) { const char *tagval[] = { "Absent", "ARC6xx", "ARC7xx", - "ARCEM", "ARCHS" }; + "ARCEM", "ARCHS" }; BFD_ASSERT (in_attr[i].i < 5); BFD_ASSERT (out_attr[i].i < 5); /* We cannot mix code for different CPUs. */ @@ -690,33 +717,33 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) /* First, check if a feature is compatible with the output object chosen CPU. */ - for (j = 0; j < ARRAY_SIZE (bfd_feature_list); j++) - if (((in_feature | out_feature) & bfd_feature_list[j].feature) - && (!(cpu_out & bfd_feature_list[j].cpus))) + for (j = 0; j < ARRAY_SIZE (FEATURE_LIST_NAME); j++) + if (((in_feature | out_feature) & FEATURE_LIST_NAME[j].feature) + && (!(cpu_out & FEATURE_LIST_NAME[j].cpus))) { _bfd_error_handler (_("error: %pB: unable to merge ISA extension attributes " "%s"), - obfd, bfd_feature_list[j].name); + obfd, FEATURE_LIST_NAME[j].name); result = false; break; } /* Second, if we have compatible features with the chosen CPU, check if they are compatible among them. */ - for (j = 0; j < ARRAY_SIZE (bfd_conflict_list); j++) - if (((in_feature | out_feature) & bfd_conflict_list[j]) - == bfd_conflict_list[j]) + for (j = 0; j < ARRAY_SIZE (CONFLICT_LIST); j++) + if (((in_feature | out_feature) & CONFLICT_LIST[j]) + == CONFLICT_LIST[j]) { unsigned k; - for (k = 0; k < ARRAY_SIZE (bfd_feature_list); k++) + for (k = 0; k < ARRAY_SIZE (FEATURE_LIST_NAME); k++) { - if (in_feature & bfd_feature_list[k].feature - & bfd_conflict_list[j]) - p1 = (char *) bfd_feature_list[k].name; - if (out_feature & bfd_feature_list[k].feature - & bfd_conflict_list[j]) - p2 = (char *) bfd_feature_list[k].name; + if (in_feature & FEATURE_LIST_NAME[k].feature + & CONFLICT_LIST[j]) + p1 = (char *) FEATURE_LIST_NAME[k].name; + if (out_feature & FEATURE_LIST_NAME[k].feature + & CONFLICT_LIST[j]) + p2 = (char *) FEATURE_LIST_NAME[k].name; } _bfd_error_handler (_("error: %pB: conflicting ISA extension attributes " @@ -728,9 +755,9 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) /* Everithing is alright. */ out_feature |= in_feature; p1 = NULL; - for (j = 0; j < ARRAY_SIZE (bfd_feature_list); j++) - if (out_feature & bfd_feature_list[j].feature) - p1 = arc_stralloc (p1, bfd_feature_list[j].attr); + for (j = 0; j < ARRAY_SIZE (FEATURE_LIST_NAME); j++) + if (out_feature & FEATURE_LIST_NAME[j].feature) + p1 = arc_stralloc (p1, FEATURE_LIST_NAME[j].attr); if (p1) out_attr[Tag_ARC_ISA_config].s = _bfd_elf_attr_strdup (obfd, p1); @@ -784,7 +811,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) if (out_attr[i].i == 0) out_attr[i].i = in_attr[i].i; else if (out_attr[i].i != 0 && in_attr[i].i != 0 - && out_attr[i].i != in_attr[i].i) + && out_attr[i].i != in_attr[i].i) { _bfd_error_handler (_("error: %pB: conflicting attributes %s: %s with %s"), @@ -811,7 +838,7 @@ arc_elf_merge_attributes (bfd *ibfd, struct bfd_link_info *info) if (out_attr[i].i == 0) out_attr[i].i = in_attr[i].i; else if (out_attr[i].i != 0 && in_attr[i].i != 0 - && out_attr[i].i != in_attr[i].i) + && out_attr[i].i != in_attr[i].i) { _bfd_error_handler (_("error: %pB: conflicting attributes %s"), @@ -865,10 +892,19 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) flagword in_flags; asection *sec; - /* Check if we have the same endianess. */ + /* Check if we have the same endianess. */ if (! _bfd_generic_verify_endian_match (ibfd, info)) return false; + if (strcmp (bfd_get_target (ibfd), bfd_get_target (obfd)) != 0) + { + _bfd_error_handler + (_("%pB: ABI is incompatible with the selected emulation:\n" + " target emulation '%s' does not match '%s'"), + ibfd, bfd_get_target (ibfd), bfd_get_target (obfd)); + return false; + } + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return true; @@ -956,7 +992,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) if (bfd_get_mach (obfd) < bfd_get_mach (ibfd)) { - return bfd_set_arch_mach (obfd, bfd_arch_arc, bfd_get_mach (ibfd)); + return bfd_set_arch_mach (obfd, ARC_BFD_ARCH, bfd_get_mach (ibfd)); } return true; @@ -964,7 +1000,7 @@ arc_elf_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) /* Return a best guess for the machine number based on the attributes. */ -static unsigned int +static ATTRIBUTE_UNUSED unsigned int bfd_arc_get_mach_from_attributes (bfd * abfd) { int arch = bfd_elf_get_obj_attr_int (abfd, OBJ_ATTR_PROC, Tag_ARC_CPU_base); @@ -986,19 +1022,24 @@ bfd_arc_get_mach_from_attributes (bfd * abfd) ? bfd_mach_arc_arc700 : bfd_mach_arc_arcv2; } -/* Set the right machine number for an ARC ELF file. */ +/* Set the right machine number for an ARC ELF file. Make sure this + is initialised, or you'll have the potential of passing + garbage---or misleading values---into the call to + bfd_default_set_arch_mach (). */ + static bool arc_elf_object_p (bfd * abfd) { - /* Make sure this is initialised, or you'll have the potential of passing - garbage---or misleading values---into the call to - bfd_default_set_arch_mach (). */ - unsigned int mach = bfd_mach_arc_arc700; - unsigned long arch = elf_elfheader (abfd)->e_flags & EF_ARC_MACH_MSK; - unsigned e_machine = elf_elfheader (abfd)->e_machine; + unsigned int mach; + unsigned long ATTRIBUTE_UNUSED arch = elf_elfheader (abfd)->e_flags + & EF_ARC_MACH_MSK; + unsigned e_machine = elf_elfheader (abfd)->e_machine; - if (e_machine == EM_ARC_COMPACT || e_machine == EM_ARC_COMPACT2) + switch (e_machine) { +#if (ARCH_TYPE == ARC) && (ARCH_SIZE == 32) + case EM_ARC_COMPACT: + case EM_ARC_COMPACT2: switch (arch) { case E_ARC_MACH_ARC600: @@ -1018,24 +1059,29 @@ arc_elf_object_p (bfd * abfd) mach = bfd_arc_get_mach_from_attributes (abfd); break; } - } - else - { - if (e_machine == EM_ARC) - { - _bfd_error_handler - (_("error: the ARC4 architecture is no longer supported")); - return false; - } - else - { - _bfd_error_handler - (_("warning: unset or old architecture flags; " - "use default machine")); - } + break; + + case EM_ARC: + _bfd_error_handler + (_("error: the ARC4 architecture is no longer supported")); + return false; + +#else /* New ARCv3 arches. */ + case EM_ARC_COMPACT3_64: + mach = bfd_mach_arcv3_64; + break; + + case EM_ARC_COMPACT3: + mach = bfd_mach_arcv3_32; + break; +#endif + + default: + _bfd_error_handler (_("error: unset or old architecture flags.")); + return false; } - return bfd_default_set_arch_mach (abfd, bfd_arch_arc, mach); + return bfd_default_set_arch_mach (abfd, ARC_BFD_ARCH, mach); } /* The final processing done just before writing out an ARC ELF object file. @@ -1049,6 +1095,7 @@ arc_elf_final_write_processing (bfd *abfd) Tag_ARC_ABI_osver); flagword e_flags = elf_elfheader (abfd)->e_flags & ~EF_ARC_OSABI_MSK; +#if (ARCH_TYPE == ARC) && (ARCH_SIZE == 32) switch (bfd_get_mach (abfd)) { case bfd_mach_arc_arcv2: @@ -1058,7 +1105,21 @@ arc_elf_final_write_processing (bfd *abfd) emf = EM_ARC_COMPACT; break; } - +#else + switch (bfd_get_mach (abfd)) + { + case bfd_mach_arcv3_64: + emf = EM_ARC_COMPACT3_64; + break; + case bfd_mach_arcv3_32: + emf = EM_ARC_COMPACT3; + break; + default: + _bfd_error_handler (_("Unknown ARC architecture")); + bfd_set_error (bfd_error_sorry); + return false; + } +#endif elf_elfheader (abfd)->e_machine = emf; /* Record whatever is the current syscall ABI version. */ @@ -1108,7 +1169,8 @@ debug_arc_reloc (struct arc_relocation_data reloc_data) ARC_DEBUG (" Input_section:\n"); if (reloc_data.input_section != NULL) { - ARC_DEBUG (" section name = %s, output_offset 0x%08x, output_section->vma = 0x%08x\n", + ARC_DEBUG (" section name = %s, output_offset 0x%08x, " \ + "output_section->vma = 0x%08x\n", reloc_data.input_section->name, (unsigned int) reloc_data.input_section->output_offset, (unsigned int) reloc_data.input_section->output_section->vma); @@ -1120,7 +1182,7 @@ debug_arc_reloc (struct arc_relocation_data reloc_data) } else { - ARC_DEBUG (" input section is NULL\n"); + ARC_DEBUG ("\tinput section is NULL\n"); } } #else @@ -1134,14 +1196,14 @@ middle_endian_convert (bfd_vma insn, bool do_it) { insn = ((insn & 0xffff0000) >> 16) - | ((insn & 0xffff) << 16); + | ((insn & 0xffff) << 16); } return insn; } -/* This function is called for relocations that are otherwise marked as NOT - requiring overflow checks. In here we perform non-standard checks of - the relocation value. */ +/* This function is called for relocations that are otherwise marked + as NOT requiring overflow checks. In here we perform non-standard + checks of the relocation value. */ static inline bfd_reloc_status_type arc_special_overflow_checks (const struct arc_relocation_data reloc_data, @@ -1189,17 +1251,19 @@ arc_special_overflow_checks (const struct arc_relocation_data reloc_data, #define ME(reloc) (reloc) -#define IS_ME(FORMULA,BFD) ((strstr (FORMULA, "ME") != NULL) \ +#define IS_ME(FORMULA,BFD) ((strstr (FORMULA, "ME") != NULL) \ && (!bfd_big_endian (BFD))) -#define S ((bfd_signed_vma) (reloc_data.sym_value \ - + (reloc_data.sym_section->output_section != NULL ? \ - (reloc_data.sym_section->output_offset \ - + reloc_data.sym_section->output_section->vma) : 0))) -#define L ((bfd_signed_vma) (reloc_data.sym_value \ - + (reloc_data.sym_section->output_section != NULL ? \ - (reloc_data.sym_section->output_offset \ - + reloc_data.sym_section->output_section->vma) : 0))) +#define S \ + ((bfd_signed_vma) (reloc_data.sym_value \ + + (reloc_data.sym_section->output_section != NULL ? \ + (reloc_data.sym_section->output_offset \ + + reloc_data.sym_section->output_section->vma) : 0))) +#define L \ + ((bfd_signed_vma) (reloc_data.sym_value \ + + (reloc_data.sym_section->output_section != NULL ? \ + (reloc_data.sym_section->output_offset \ + + reloc_data.sym_section->output_section->vma) : 0))) #define A (reloc_data.reloc_addend) #define B (0) #define G (reloc_data.got_offset_value) @@ -1207,27 +1271,30 @@ arc_special_overflow_checks (const struct arc_relocation_data reloc_data, #define GOT_BEGIN (htab->sgot->output_section->vma) #define MES (0) - /* P: relative offset to PCL The offset should be to the - current location aligned to 32 bits. */ -#define P ((bfd_signed_vma) ( \ - ( \ - (reloc_data.input_section->output_section != NULL ? \ - reloc_data.input_section->output_section->vma : 0) \ - + reloc_data.input_section->output_offset \ - + (reloc_data.reloc_offset - (bitsize >= 32 ? 4 : 0))) \ - & ~0x3)) -#define PDATA ((bfd_signed_vma) ( \ - (reloc_data.input_section->output_section->vma \ - + reloc_data.input_section->output_offset \ - + (reloc_data.reloc_offset)))) -#define SECTSTART (bfd_signed_vma) (reloc_data.sym_section->output_section->vma \ - + reloc_data.sym_section->output_offset) -#define FINAL_SECTSTART \ +/* P: relative offset to PCL The offset should be to the + current location aligned to 32 bits. */ +#define P ((bfd_signed_vma) \ + (((reloc_data.input_section->output_section != NULL ? \ + reloc_data.input_section->output_section->vma : 0) \ + + reloc_data.input_section->output_offset \ + + (reloc_data.reloc_offset - (bitsize == 32 ? 4 : \ + (bitsize == 34 ? 2 : 0)))) \ + & ~0x3)) +#define PDATA \ + ((bfd_signed_vma) ((reloc_data.input_section->output_section->vma \ + + reloc_data.input_section->output_offset \ + + (reloc_data.reloc_offset)))) +#define SECTSTART \ + (bfd_signed_vma) (reloc_data.sym_section->output_section->vma \ + + reloc_data.sym_section->output_offset) +#define FINAL_SECTSTART \ (bfd_signed_vma) (reloc_data.sym_section->output_section->vma) #define JLI (bfd_signed_vma) (reloc_data.sym_section->output_section->vma) #define _SDA_BASE_ (bfd_signed_vma) (reloc_data.sdata_begin_symbol_vma) #define TLS_REL (bfd_signed_vma)(tls_sec->output_section->vma) #define TLS_TBSS (align_power (TCB_SIZE, tls_sec->alignment_power)) +#define ICARRY insn +#define DEREFP (insn) #define none (0) @@ -1279,20 +1346,21 @@ arc_special_overflow_checks (const struct arc_relocation_data reloc_data, #define PRINT_DEBUG_RELOC_INFO_BEFORE(...) #define PRINT_DEBUG_RELOC_INFO_AFTER -#endif /* ARC_ENABLE_DEBUG */ +#endif /* ARC_ENABLE_DEBUG. */ -#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, RELOC_FUNCTION, OVERFLOW, FORMULA) \ +#define ARC_RELOC_HOWTO(TYPE, VALUE, SIZE, BITSIZE, \ + RELOC_FUNCTION, OVERFLOW, FORMULA) \ case R_##TYPE: \ - { \ - bfd_signed_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \ - relocation = FORMULA ; \ - PRINT_DEBUG_RELOC_INFO_BEFORE (#FORMULA, #TYPE); \ - insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \ - insn = (* get_replace_function (abfd, TYPE)) (insn, relocation); \ - insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \ - PRINT_DEBUG_RELOC_INFO_AFTER; \ - } \ - break; + { \ + bfd_signed_vma bitsize ATTRIBUTE_UNUSED = BITSIZE; \ + relocation = FORMULA ; \ + PRINT_DEBUG_RELOC_INFO_BEFORE (#FORMULA, #TYPE); \ + insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \ + insn = (* get_replace_function (abfd, TYPE)) (insn, relocation); \ + insn = middle_endian_convert (insn, IS_ME (#FORMULA, abfd)); \ + PRINT_DEBUG_RELOC_INFO_AFTER; \ + } \ + break; static bfd_reloc_status_type arc_do_relocation (bfd_byte * contents, @@ -1312,6 +1380,11 @@ arc_do_relocation (bfd_byte * contents, switch (bfd_get_reloc_size (reloc_data.howto)) { + case 8: + insn = arc_bfd_get_64 (abfd, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; case 4: insn = arc_bfd_get_32 (abfd, contents + reloc_data.reloc_offset, @@ -1374,7 +1447,7 @@ arc_do_relocation (bfd_byte * contents, DEBUG_ARC_RELOC (reloc_data); ARC_DEBUG ("Relocation value = signed -> %d, unsigned -> %u" ", hex -> (0x%08x)\n", - (int) relocation, (unsigned) relocation, (int) relocation); + (int) relocation, (unsigned) relocation, (int) relocation); return flag; } @@ -1382,6 +1455,11 @@ arc_do_relocation (bfd_byte * contents, /* Write updated instruction back to memory. */ switch (bfd_get_reloc_size (reloc_data.howto)) { + case 8: + arc_bfd_put_64 (abfd, insn, + contents + reloc_data.reloc_offset, + reloc_data.input_section); + break; case 4: arc_bfd_put_32 (abfd, insn, contents + reloc_data.reloc_offset, @@ -1417,6 +1495,7 @@ arc_do_relocation (bfd_byte * contents, #undef SECTSTART #undef JLI #undef _SDA_BASE_ +#undef ICARRY #undef none #undef ARC_RELOC_HOWTO @@ -1437,14 +1516,14 @@ arc_do_relocation (bfd_byte * contents, corresponding to the st_shndx field of each local symbol. */ static int -elf_arc_relocate_section (bfd * output_bfd, - struct bfd_link_info * info, - bfd * input_bfd, - asection * input_section, - bfd_byte * contents, - Elf_Internal_Rela * relocs, - Elf_Internal_Sym * local_syms, - asection ** local_sections) +elf_arc_relocate_section (bfd *output_bfd, + struct bfd_link_info *info, + bfd *input_bfd, + asection *input_section, + bfd_byte *contents, + Elf_Internal_Rela *relocs, + Elf_Internal_Sym *local_syms, + asection **local_sections) { Elf_Internal_Shdr * symtab_hdr; struct elf_link_hash_entry ** sym_hashes; @@ -1452,7 +1531,9 @@ elf_arc_relocate_section (bfd * output_bfd, Elf_Internal_Rela * wrel; Elf_Internal_Rela * relend; struct elf_link_hash_table * htab = elf_hash_table (info); + const struct elf_backend_data *bed; + bed = get_elf_backend_data (output_bfd); symtab_hdr = &((elf_tdata (input_bfd))->symtab_hdr); sym_hashes = elf_sym_hashes (input_bfd); @@ -1460,32 +1541,33 @@ 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; - bool 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; + bool resolved_to_zero; struct arc_relocation_data reloc_data = - { - .reloc_offset = 0, - .reloc_addend = 0, - .got_offset_value = 0, - .sym_value = 0, - .sym_section = NULL, - .howto = NULL, - .input_section = NULL, - .sdata_begin_symbol_vma = 0, - .sdata_begin_symbol_vma_set = false, - .got_symbol_vma = 0, - .should_relocate = false - }; - - r_type = ELF32_R_TYPE (rel->r_info); + { + .reloc_offset = 0, + .reloc_addend = 0, + .got_offset_value = 0, + .sym_value = 0, + .sym_section = NULL, + .howto = NULL, + .input_section = NULL, + .sdata_begin_symbol_vma = 0, + .sdata_begin_symbol_vma_set = false, + .got_symbol_vma = 0, + .should_relocate = false + }; + + r_type = ELFNN_R_TYPE (rel->r_info); if (r_type >= (int) R_ARC_max) { @@ -1494,7 +1576,7 @@ elf_arc_relocate_section (bfd * output_bfd, } howto = arc_elf_howto (r_type); - r_symndx = ELF32_R_SYM (rel->r_info); + r_symndx = ELFNN_R_SYM (rel->r_info); /* If we are generating another .o file and the symbol in not local, skip this relocation. */ @@ -1596,9 +1678,9 @@ elf_arc_relocate_section (bfd * output_bfd, /* For ld -r, remove relocations in debug sections against sections defined in discarded sections. Not done for eh_frame editing code expects to be present. */ - if (bfd_link_relocatable (info) - && (input_section->flags & SEC_DEBUGGING)) - wrel--; + if (bfd_link_relocatable (info) + && (input_section->flags & SEC_DEBUGGING)) + wrel--; continue; } @@ -1610,6 +1692,8 @@ elf_arc_relocate_section (bfd * output_bfd, continue; } + resolved_to_zero = (h != NULL && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)); + if (r_symndx < symtab_hdr->sh_info) /* A local symbol. */ { reloc_data.sym_value = sym->st_value; @@ -1638,7 +1722,7 @@ elf_arc_relocate_section (bfd * output_bfd, BFD_ASSERT (htab->sgot != NULL || !is_reloc_for_GOT (howto)); if (htab->sgot != NULL) reloc_data.got_symbol_vma = htab->sgot->output_section->vma - + htab->sgot->output_offset; + + htab->sgot->output_offset; reloc_data.should_relocate = true; } @@ -1652,19 +1736,18 @@ elf_arc_relocate_section (bfd * output_bfd, while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) - { - struct elf_arc_link_hash_entry *ah_old = - (struct elf_arc_link_hash_entry *) h; - h = (struct elf_link_hash_entry *) h->root.u.i.link; - struct elf_arc_link_hash_entry *ah = - (struct elf_arc_link_hash_entry *) h; - - if (ah->got_ents == 0 && ah_old->got_ents != ah->got_ents) - ah->got_ents = ah_old->got_ents; - } + { + struct elf_arc_link_hash_entry *ah_old + = (struct elf_arc_link_hash_entry *) h; + h = (struct elf_link_hash_entry *) h->root.u.i.link; + struct elf_arc_link_hash_entry *ah + = (struct elf_arc_link_hash_entry *) h; + + if (ah->got_ents == 0 && ah_old->got_ents != ah->got_ents) + ah->got_ents = ah_old->got_ents; + } /* TODO: Need to validate what was the intention. */ - /* BFD_ASSERT ((h->dynindx == -1) || (h->forced_local != 0)); */ reloc_data.symbol_name = h->root.root.string; /* If we have encountered a definition for this symbol. */ @@ -1681,13 +1764,13 @@ elf_arc_relocate_section (bfd * output_bfd, struct elf_arc_link_hash_entry *ah = (struct elf_arc_link_hash_entry *) h; /* TODO: Change it to use arc_do_relocation with - ARC_32 reloc. Try to use ADD_RELA macro. */ + ARC_32 reloc. Try to use ADD_RELA macro. */ bfd_vma relocation = reloc_data.sym_value + reloc_data.reloc_addend + (reloc_data.sym_section->output_section != NULL ? - (reloc_data.sym_section->output_offset - + reloc_data.sym_section->output_section->vma) - : 0); + (reloc_data.sym_section->output_offset + + reloc_data.sym_section->output_section->vma) + : 0); BFD_ASSERT (ah->got_ents); bfd_vma got_offset = ah->got_ents->offset; @@ -1718,7 +1801,8 @@ elf_arc_relocate_section (bfd * output_bfd, reloc_data.sym_section = htab->splt; reloc_data.should_relocate = true; } - else + /* See pr22269. */ + else if (!resolved_to_zero) continue; } else @@ -1752,11 +1836,12 @@ elf_arc_relocate_section (bfd * output_bfd, BFD_ASSERT (htab->sgot != NULL || !is_reloc_for_GOT (howto)); if (htab->sgot != NULL) reloc_data.got_symbol_vma = htab->sgot->output_section->vma - + htab->sgot->output_offset; + + htab->sgot->output_offset; } - if ((is_reloc_for_GOT (howto) - || is_reloc_for_TLS (howto))) + if (is_reloc_for_GOT (howto) + || (is_reloc_for_TLS (howto) + && !resolved_to_zero)) { reloc_data.should_relocate = true; @@ -1776,106 +1861,109 @@ elf_arc_relocate_section (bfd * output_bfd, if (h == NULL) { - create_got_dynrelocs_for_single_entry ( - got_entry_for_type (list, - arc_got_entry_type_for_reloc (howto)), - output_bfd, info, NULL); + create_got_dynrelocs_for_single_entry + (got_entry_for_type (list, + arc_got_entry_type_for_reloc (howto)), + output_bfd, info, NULL); } } -#define IS_ARC_PCREL_TYPE(TYPE) \ - ( (TYPE == R_ARC_PC32) \ - || (TYPE == R_ARC_32_PCREL)) +#define IS_ARC_PCREL_TYPE(TYPE) \ + ((TYPE == R_ARC_PC32) \ + || (TYPE == R_ARC_32_PCREL)) switch (r_type) { - case R_ARC_32: - case R_ARC_32_ME: - 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 - && !h->def_regular - && (!info->symbolic || !h->def_regular)))) - { - Elf_Internal_Rela outrel; - bfd_byte *loc; - bool skip = false; - bool relocate = false; - asection *sreloc = _bfd_elf_get_dynamic_reloc_section - (input_bfd, input_section, - /*RELA*/ true); + case R_ARC_64: + case R_ARC_32: + case R_ARC_32_ME: + case R_ARC_PC32: + case R_ARC_32_PCREL: + case R_ARC_HI32_ME: + case R_ARC_LO32_ME: + if (bfd_link_pic (info) + && !resolved_to_zero + && (input_section->flags & SEC_ALLOC) != 0 + && (!IS_ARC_PCREL_TYPE (r_type) + || (h != NULL + && h->dynindx != -1 + && (!SYMBOL_REFERENCES_LOCAL (info, h))))) + { + Elf_Internal_Rela outrel; + bfd_byte *loc; + bool skip = false; + bool relocate = false; + asection *sreloc = _bfd_elf_get_dynamic_reloc_section + (input_bfd, input_section, + /*RELA*/ true); - BFD_ASSERT (sreloc != NULL); + BFD_ASSERT (sreloc != NULL); - outrel.r_offset = _bfd_elf_section_offset (output_bfd, - info, - input_section, - rel->r_offset); + outrel.r_offset = _bfd_elf_section_offset (output_bfd, + info, + input_section, + rel->r_offset); if (outrel.r_offset == (bfd_vma) -1) skip = true; - outrel.r_addend = rel->r_addend; - outrel.r_offset += (input_section->output_section->vma - + input_section->output_offset); + outrel.r_addend = rel->r_addend; + outrel.r_offset += (input_section->output_section->vma + + input_section->output_offset); - if (skip) - { - memset (&outrel, 0, sizeof outrel); + if (skip) + { + memset (&outrel, 0, sizeof outrel); + relocate = false; + } + else if (h != NULL + && h->dynindx != -1 + && (IS_ARC_PCREL_TYPE (r_type) + || !(bfd_link_executable (info) + || SYMBOLIC_BIND (info, h)) + || ! h->def_regular)) + { + BFD_ASSERT (h != NULL); + if ((input_section->flags & SEC_ALLOC) != 0) relocate = false; - } - else if (h != NULL - && h->dynindx != -1 - && (IS_ARC_PCREL_TYPE (r_type) - || !(bfd_link_executable (info) - || SYMBOLIC_BIND (info, h)) - || ! h->def_regular)) - { - BFD_ASSERT (h != NULL); - if ((input_section->flags & SEC_ALLOC) != 0) - relocate = false; - else - relocate = true; - - BFD_ASSERT (h->dynindx != -1); - outrel.r_info = ELF32_R_INFO (h->dynindx, r_type); - } - else - { - /* Handle local symbols, they either do not have a - global hash table entry (h == NULL), or are - forced local due to a version script - (h->forced_local), or the third condition is - legacy, it appears to say something like, for - links where we are pre-binding the symbols, or - there's not an entry for this symbol in the - dynamic symbol table, and it's a regular symbol - not defined in a shared object, then treat the - symbol as local, resolve it now. */ + else relocate = true; - /* outrel.r_addend = 0; */ - outrel.r_info = ELF32_R_INFO (0, R_ARC_RELATIVE); - } - BFD_ASSERT (sreloc->contents != 0); + BFD_ASSERT (h->dynindx != -1); + outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type); + } + else + { + /* Handle local symbols, they either do not have a + global hash table entry (h == NULL), or are + forced local due to a version script + (h->forced_local), or the third condition is + legacy, it appears to say something like, for + links where we are pre-binding the symbols, or + there's not an entry for this symbol in the + 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; + /* outrel.r_addend = 0; */ + outrel.r_info = ELFNN_R_INFO (0, R_ARC_RELATIVE); + } - loc = sreloc->contents; - loc += sreloc->reloc_count * sizeof (Elf32_External_Rela); - sreloc->reloc_count += 1; + BFD_ASSERT (sreloc->contents != 0); - bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc); + loc = sreloc->contents; + loc += sreloc->reloc_count * sizeof (ElfNN_External_Rela); + sreloc->reloc_count += 1; - if (!relocate) - continue; - } - break; - default: - break; + bed->s->swap_reloca_out (output_bfd, &outrel, loc); + + if (!relocate) + continue; + } + break; + default: + break; } if (is_reloc_SDA_relative (howto) @@ -1892,10 +1980,12 @@ elf_arc_relocate_section (bfd * output_bfd, /* Make sure we have with a dynamic linker. In case of GOT and PLT the sym_section should point to .got or .plt respectively. */ if ((is_reloc_for_GOT (howto) || is_reloc_for_PLT (howto)) - && reloc_data.sym_section == NULL) + && reloc_data.sym_section == NULL + && !resolved_to_zero) { _bfd_error_handler - (_("GOT and PLT relocations cannot be fixed with a non dynamic linker")); + (_("GOT and PLT relocations cannot be fixed with a non dynamic" \ + " linker")); bfd_set_error (bfd_error_bad_value); return false; } @@ -1908,18 +1998,20 @@ elf_arc_relocate_section (bfd * output_bfd, case bfd_reloc_overflow: (*info->callbacks->reloc_overflow) - (info, (h ? &h->root : NULL), reloc_data.symbol_name, howto->name, (bfd_vma) 0, - input_bfd, input_section, rel->r_offset); + (info, (h ? &h->root : NULL), reloc_data.symbol_name, howto->name, + (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; 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: /* xgettext:c-format */ - msg = _("%pB(%pA): warning: unaligned access to symbol '%s' in the small data area"); + msg = _("%pB(%pA): warning: unaligned access to symbol '%s' in the" \ + " small data area"); break; case bfd_reloc_outofrange: @@ -1944,7 +2036,8 @@ elf_arc_relocate_section (bfd * output_bfd, } if (msg) - _bfd_error_handler (msg, input_bfd, input_section, reloc_data.symbol_name); + _bfd_error_handler (msg, input_bfd, input_section, + reloc_data.symbol_name); return false; } @@ -1988,7 +2081,7 @@ elf_arc_check_relocs (bfd * abfd, unsigned long r_symndx; struct elf_link_hash_entry *h; - r_type = ELF32_R_TYPE (rel->r_info); + r_type = ELFNN_R_TYPE (rel->r_info); if (r_type >= (int) R_ARC_max) { @@ -1998,7 +2091,7 @@ elf_arc_check_relocs (bfd * abfd, howto = arc_elf_howto (r_type); /* Load symbol information. */ - r_symndx = ELF32_R_SYM (rel->r_info); + r_symndx = ELFNN_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info) /* Is a local symbol. */ h = NULL; else /* Global one. */ @@ -2012,8 +2105,13 @@ elf_arc_check_relocs (bfd * abfd, switch (r_type) { + case R_ARC_8: + case R_ARC_16: case R_ARC_32: + case R_ARC_64: case R_ARC_32_ME: + case R_ARC_HI32_ME: + case R_ARC_LO32_ME: /* During shared library creation, these relocs should not appear in a shared library (as memory will be read only and the dynamic linker can not resolve these. However @@ -2042,39 +2140,52 @@ elf_arc_check_relocs (bfd * abfd, return false; } - /* In some cases we are not setting the 'non_got_ref' - flag, even though the relocations don't require a GOT - access. We should extend the testing in this area to - ensure that no significant cases are being missed. */ - if (h) - h->non_got_ref = 1; - /* FALLTHROUGH */ - case R_ARC_PC32: - case R_ARC_32_PCREL: - if ((bfd_link_pic (info)) - && ((r_type != R_ARC_PC32 && r_type != R_ARC_32_PCREL) - || (h != NULL - && (!info->symbolic || !h->def_regular)))) - { - if (sreloc == NULL) - { - if (info->dynamic - && ! htab->dynamic_sections_created - && ! _bfd_elf_link_create_dynamic_sections (abfd, info)) - return false; - sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj, - 2, abfd, - /*rela*/ - true); - - if (sreloc == NULL) - return false; - } - sreloc->size += sizeof (Elf32_External_Rela); + /* In some cases we are not setting the 'non_got_ref' flag, + even though the relocations don't require a GOT access. + We should extend the testing in this area to ensure that + no significant cases are being missed. */ + if (h) + h->non_got_ref = 1; - } - default: + /* We don't need to handle relocs into sections not going + into the "real" output. */ + if ((sec->flags & SEC_ALLOC) == 0) break; + + /* No need to do anything if we're not creating a shared + object. */ + if (!bfd_link_pic (info) + || (h != NULL + && UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))) + break; + + /* fall through */ + case R_ARC_PC32: + case R_ARC_32_PCREL: + if (!bfd_link_pic (info)) + break; + + if (((r_type != R_ARC_PC32 && r_type != R_ARC_32_PCREL) + || (!SYMBOL_REFERENCES_LOCAL (info, h)))) + { + if (sreloc == NULL) + { + if (info->dynamic + && ! htab->dynamic_sections_created + && ! _bfd_elf_link_create_dynamic_sections (abfd, info)) + return false; + sreloc = _bfd_elf_make_dynamic_reloc_section (sec, dynobj, + 2, abfd, + /* rela */ + true); + + if (sreloc == NULL) + return false; + } + sreloc->size += sizeof (ElfNN_External_Rela); + } + default: + break; } if (is_reloc_for_PLT (howto)) @@ -2112,20 +2223,18 @@ elf_arc_check_relocs (bfd * abfd, if (! _bfd_elf_create_got_section (dynobj, info)) return false; - arc_fill_got_info_for_reloc ( - arc_got_entry_type_for_reloc (howto), - get_got_entry_list_for_symbol (abfd, r_symndx, h), - info, - h); + arc_fill_got_info_for_reloc + (arc_got_entry_type_for_reloc (howto), + get_got_entry_list_for_symbol (abfd, r_symndx, h), + info, + h); } } return true; } -#define ELF_DYNAMIC_INTERPRETER "/sbin/ld-uClibc.so" - -static const struct plt_version_t * +static struct plt_version_t * arc_get_plt_version (struct bfd_link_info *info) { int i; @@ -2137,7 +2246,12 @@ arc_get_plt_version (struct bfd_link_info *info) (int) plt_versions[i].elem_size); } - if (bfd_get_mach (info->output_bfd) == bfd_mach_arc_arcv2) + if (bfd_get_mach (info->output_bfd) == bfd_mach_arcv3_64) + { + return &(plt_versions[ELF_ARCV3_PIC]); + } + else if (bfd_get_mach (info->output_bfd) == bfd_mach_arc_arcv2 + || bfd_get_mach (info->output_bfd) == bfd_mach_arcv3_32) { if (bfd_link_pic (info)) return &(plt_versions[ELF_ARCV2_PIC]); @@ -2151,6 +2265,8 @@ arc_get_plt_version (struct bfd_link_info *info) else return &(plt_versions[ELF_ARC_ABS]); } + BFD_ASSERT (0); + return NULL; } static bfd_vma @@ -2171,9 +2287,8 @@ add_symbol_to_plt (struct bfd_link_info *info) htab->splt->size += plt_data->elem_size; ARC_DEBUG ("PLT_SIZE = %d\n", (int) htab->splt->size); - htab->sgotplt->size += 4; - htab->srelplt->size += sizeof (Elf32_External_Rela); - + htab->sgotplt->size += GOT_ENTRY_SIZE; + htab->srelplt->size += sizeof (ElfNN_External_Rela); return ret; } @@ -2193,11 +2308,11 @@ plt_do_relocs_for_symbol (bfd *abfd, switch (SYM_ONLY (reloc->symbol)) { - case SGOT: - relocation - = htab->sgotplt->output_section->vma - + htab->sgotplt->output_offset + symbol_got_offset; - break; + case SGOT: + relocation + = htab->sgotplt->output_section->vma + + htab->sgotplt->output_offset + symbol_got_offset; + break; } relocation += reloc->addend; @@ -2208,26 +2323,26 @@ plt_do_relocs_for_symbol (bfd *abfd, reloc_offset -= (IS_INSN_24 (reloc->symbol)) ? 2 : 0; relocation -= htab->splt->output_section->vma - + htab->splt->output_offset - + plt_offset + reloc_offset; + + htab->splt->output_offset + + plt_offset + reloc_offset; } /* TODO: being ME is not a property of the relocation but of the - section of which is applying the relocation. */ + section of which is applying the relocation. */ if (IS_MIDDLE_ENDIAN (reloc->symbol) && !bfd_big_endian (abfd)) { relocation = ((relocation & 0xffff0000) >> 16) - | ((relocation & 0xffff) << 16); + | ((relocation & 0xffff) << 16); } switch (reloc->size) { - case 32: - bfd_put_32 (htab->splt->output_section->owner, - relocation, - htab->splt->contents + plt_offset + reloc->offset); - break; + case 32: + bfd_put_32 (htab->splt->output_section->owner, + relocation, + htab->splt->contents + plt_offset + reloc->offset); + break; } reloc = &(reloc[1]); /* Jump to next relocation. */ @@ -2241,10 +2356,12 @@ relocate_plt_for_symbol (bfd *output_bfd, { const struct plt_version_t *plt_data = arc_get_plt_version (info); struct elf_link_hash_table *htab = elf_hash_table (info); + const struct elf_backend_data *bed; bfd_vma plt_index = (h->plt.offset - plt_data->entry_size) - / plt_data->elem_size; - bfd_vma got_offset = (plt_index + 3) * 4; + / plt_data->elem_size; + bfd_vma got_offset = (plt_index + 3) * GOT_ENTRY_SIZE; + bed = get_elf_backend_data (output_bfd); ARC_DEBUG ("arc_info: PLT_OFFSET = %#lx, PLT_ENTRY_VMA = %#lx, \ GOT_ENTRY_OFFSET = %#lx, GOT_ENTRY_VMA = %#lx, for symbol %s\n", @@ -2293,32 +2410,30 @@ GOT_ENTRY_OFFSET = %#lx, GOT_ENTRY_VMA = %#lx, for symbol %s\n", rel.r_addend = 0; BFD_ASSERT (h->dynindx != -1); - rel.r_info = ELF32_R_INFO (h->dynindx, R_ARC_JMP_SLOT); + rel.r_info = ELFNN_R_INFO (h->dynindx, R_ARC_JMP_SLOT); loc = htab->srelplt->contents; - loc += plt_index * sizeof (Elf32_External_Rela); /* relA */ - bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + loc += plt_index * sizeof (ElfNN_External_Rela); /* relA */ + bed->s->swap_reloca_out (output_bfd, &rel, loc); } } +/* Initialize the PLT with ARC specific PLT header. See arc-plt.def. + Use middle-endian to fill in the data as it is executable code. */ + static void relocate_plt_for_entry (bfd *abfd, struct bfd_link_info *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 i = 0; + uint16_t *ptr = (uint16_t *) plt_data->entry; - { - bfd_vma i = 0; - uint16_t *ptr = (uint16_t *) plt_data->entry; - for (i = 0; i < plt_data->entry_size/2; i++) - { - uint16_t data = ptr[i]; - bfd_put_16 (abfd, - (bfd_vma) data, - htab->splt->contents + (i*2)); - } - } + for (i = 0; i < plt_data->entry_size/2; i++) + { + bfd_put_16 (abfd, (bfd_vma) ptr[i], htab->splt->contents + (i*2)); + } PLT_DO_RELOCS_FOR_ENTRY (abfd, htab, plt_data->entry_relocs); } @@ -2330,7 +2445,7 @@ relocate_plt_for_entry (bfd *abfd, static bool elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, - struct elf_link_hash_entry *h) + struct elf_link_hash_entry *h) { asection *s; bfd *dynobj = (elf_hash_table (info))->dynobj; @@ -2432,7 +2547,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, struct elf_arc_link_hash_table *arc_htab = elf_arc_hash_table (info); BFD_ASSERT (arc_htab->elf.srelbss != NULL); - arc_htab->elf.srelbss->size += sizeof (Elf32_External_Rela); + arc_htab->elf.srelbss->size += sizeof (ElfNN_External_Rela); h->needs_copy = 1; } @@ -2445,7 +2560,7 @@ elf_arc_adjust_dynamic_symbol (struct bfd_link_info *info, /* Function : elf_arc_finish_dynamic_symbol Brief : Finish up dynamic symbol handling. We set the - contents of various dynamic sections here. + contents of various dynamic sections here. Args : output_bfd : info : h : @@ -2458,6 +2573,10 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, struct elf_link_hash_entry *h, Elf_Internal_Sym * sym) { + const struct elf_backend_data *bed; + + bed = get_elf_backend_data (output_bfd); + if (h->plt.offset != (bfd_vma) -1) { relocate_plt_for_symbol (output_bfd, info, h); @@ -2475,12 +2594,8 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, create respective dynamic relocs. */ /* TODO: Make function to get list and not access the list directly. */ /* TODO: Move function to relocate_section create this relocs eagerly. */ - struct elf_arc_link_hash_entry *ah = - (struct elf_arc_link_hash_entry *) h; - create_got_dynrelocs_for_got_info (&ah->got_ents, - output_bfd, - info, - h); + struct elf_arc_link_hash_entry *ah = (struct elf_arc_link_hash_entry *) h; + create_got_dynrelocs_for_got_info (&ah->got_ents, output_bfd, info, h); if (h->needs_copy) { @@ -2500,7 +2615,7 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, + h->root.u.def.section->output_offset); bfd_byte * loc = arc_htab->elf.srelbss->contents - + (arc_htab->elf.srelbss->reloc_count * sizeof (Elf32_External_Rela)); + + (arc_htab->elf.srelbss->reloc_count * sizeof (ElfNN_External_Rela)); arc_htab->elf.srelbss->reloc_count++; Elf_Internal_Rela rel; @@ -2508,9 +2623,9 @@ elf_arc_finish_dynamic_symbol (bfd * output_bfd, rel.r_offset = rel_offset; BFD_ASSERT (h->dynindx != -1); - rel.r_info = ELF32_R_INFO (h->dynindx, R_ARC_COPY); + rel.r_info = ELFNN_R_INFO (h->dynindx, R_ARC_COPY); - bfd_elf32_swap_reloca_out (output_bfd, &rel, loc); + bed->s->swap_reloca_out (output_bfd, &rel, loc); } /* Mark _DYNAMIC and _GLOBAL_OFFSET_TABLE_ as absolute. */ @@ -2554,8 +2669,7 @@ arc_create_forced_local_got_entries_for_tls (struct bfd_hash_entry *bh, while (list != NULL) { create_got_dynrelocs_for_single_entry (list, tmp->output_bfd, - tmp->info, - (struct elf_link_hash_entry *) h); + tmp->info, (struct elf_link_hash_entry *) h); list = list->next; } } @@ -2579,14 +2693,17 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, struct elf_link_hash_table *htab = elf_hash_table (info); bfd *dynobj = (elf_hash_table (info))->dynobj; asection *sdyn = bfd_get_linker_section (dynobj, ".dynamic"); + const struct elf_backend_data *bed = get_elf_backend_data (output_bfd); + /* TODO: instead of checking for sdyn, we can use elf_hash_table + (info)->dynamic_sections_created to see if we have dynamic + sections creared. */ if (sdyn) { - Elf32_External_Dyn *dyncon, *dynconend; + ElfNN_External_Dyn *dyncon, *dynconend; - dyncon = (Elf32_External_Dyn *) sdyn->contents; - dynconend - = (Elf32_External_Dyn *) (sdyn->contents + sdyn->size); + dyncon = (ElfNN_External_Dyn *) sdyn->contents; + dynconend = (ElfNN_External_Dyn *) (sdyn->contents + sdyn->size); for (; dyncon < dynconend; dyncon++) { Elf_Internal_Dyn internal_dyn; @@ -2595,20 +2712,20 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, struct elf_link_hash_entry *h = NULL; asection *s = NULL; - bfd_elf32_swap_dyn_in (dynobj, dyncon, &internal_dyn); + bed->s->swap_dyn_in (dynobj, dyncon, &internal_dyn); switch (internal_dyn.d_tag) { GET_SYMBOL_OR_SECTION (DT_INIT, info->init_function, NULL) - GET_SYMBOL_OR_SECTION (DT_FINI, info->fini_function, NULL) - GET_SYMBOL_OR_SECTION (DT_PLTGOT, NULL, ".plt") - GET_SYMBOL_OR_SECTION (DT_JMPREL, NULL, ".rela.plt") - GET_SYMBOL_OR_SECTION (DT_PLTRELSZ, NULL, ".rela.plt") - GET_SYMBOL_OR_SECTION (DT_VERSYM, NULL, ".gnu.version") - GET_SYMBOL_OR_SECTION (DT_VERDEF, NULL, ".gnu.version_d") - GET_SYMBOL_OR_SECTION (DT_VERNEED, NULL, ".gnu.version_r") - default: - break; + GET_SYMBOL_OR_SECTION (DT_FINI, info->fini_function, NULL) + GET_SYMBOL_OR_SECTION (DT_PLTGOT, NULL, ".plt") + GET_SYMBOL_OR_SECTION (DT_JMPREL, NULL, ".rela.plt") + GET_SYMBOL_OR_SECTION (DT_PLTRELSZ, NULL, ".rela.plt") + GET_SYMBOL_OR_SECTION (DT_VERSYM, NULL, ".gnu.version") + GET_SYMBOL_OR_SECTION (DT_VERDEF, NULL, ".gnu.version_d") + GET_SYMBOL_OR_SECTION (DT_VERNEED, NULL, ".gnu.version_r") + default: + break; } /* In case the dynamic symbols should be updated with a symbol. */ @@ -2659,9 +2776,10 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, } if (do_it) - bfd_elf32_swap_dyn_out (output_bfd, &internal_dyn, dyncon); + bed->s->swap_dyn_out (output_bfd, &internal_dyn, dyncon); } + /* Fill in the first entry in the procedure linkage table. */ if (htab->splt->size > 0) { relocate_plt_for_entry (output_bfd, info); @@ -2670,30 +2788,40 @@ elf_arc_finish_dynamic_sections (bfd * output_bfd, /* TODO: Validate this. */ if (htab->srelplt->output_section != bfd_abs_section_ptr) elf_section_data (htab->srelplt->output_section) - ->this_hdr.sh_entsize = 12; + ->this_hdr.sh_entsize = GOT_ENTRY_SIZE * 3; } /* Fill in the first three entries in the global offset table. */ if (htab->sgot) { - struct elf_link_hash_entry *h; - h = elf_link_hash_lookup (elf_hash_table (info), "_GLOBAL_OFFSET_TABLE_", - false, false, true); - - if (h != NULL && h->root.type != bfd_link_hash_undefined - && h->root.u.def.section != NULL) + struct elf_link_hash_entry *got; + /* Get the hash entry of the first GOT entry. */ + got = elf_link_hash_lookup (elf_hash_table (info), + "_GLOBAL_OFFSET_TABLE_", false, false, true); + + if (got != NULL + && got->root.type != bfd_link_hash_undefined + && got->root.u.def.section != NULL) { - asection *sec = h->root.u.def.section; + asection *sec = got->root.u.def.section; + bfd_vma dyn_vma = 0; - if (sdyn == NULL) - bfd_put_32 (output_bfd, (bfd_vma) 0, - sec->contents); - else - bfd_put_32 (output_bfd, - sdyn->output_section->vma + sdyn->output_offset, - sec->contents); - bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 4); - bfd_put_32 (output_bfd, (bfd_vma) 0, sec->contents + 8); + /* Check if we participate in a dynamic linking. */ + if (sdyn) + { + /* Get the unrelocated address of the _DYNAMIC, which is + the start of the start of the dynamic sction. */ + dyn_vma = sdyn->output_section->vma + sdyn->output_offset; + } + + /* _GLOBAL_OFFSET_TABLE_[0] = VMA (.dynamic) */ + write_in_got (output_bfd, dyn_vma, sec->contents); + /* _GLOBAL_OFFSET_TABLE_[1] = 0. Reserved for dynamic linker. */ + write_in_got (output_bfd, (bfd_vma) 0, + sec->contents + (GOT_ENTRY_SIZE)); + /* _GLOBAL_OFFSET_TABLE_[2] = 0. Reserved for dynamic linker. */ + write_in_got (output_bfd, (bfd_vma) 0, + sec->contents + (GOT_ENTRY_SIZE * 2)); } } @@ -2721,6 +2849,7 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, bfd *dynobj; asection *s; bool relocs_exist = false; + bool reltext_exist = false; struct elf_link_hash_table *htab = elf_hash_table (info); dynobj = htab->dynobj; @@ -2736,8 +2865,8 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { s = bfd_get_section_by_name (dynobj, ".interp"); BFD_ASSERT (s != NULL); - s->size = sizeof (ELF_DYNAMIC_INTERPRETER); - s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER; + s->size = sizeof (ELFNN_DYNAMIC_INTERPRETER); + s->contents = (unsigned char *) ELFNN_DYNAMIC_INTERPRETER; } /* Add some entries to the .dynamic section. We fill in some of @@ -2775,7 +2904,29 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, else if (startswith (s->name, ".rela")) { if (s->size != 0 && s != htab->srelplt) - relocs_exist = true; + { + 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; + } /* We use the reloc_count field as a counter if we need to copy relocs into the output file. */ @@ -2802,18 +2953,44 @@ elf_arc_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, return false; } - return _bfd_elf_add_dynamic_tags (output_bfd, info, relocs_exist); + 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 (ElfNN_External_Rela))) + return false; + + if (reltext_exist) + if (!_bfd_elf_add_dynamic_entry (info, DT_TEXTREL, 0)) + return false; + } + + return true; } -/* Classify dynamic relocs such that -z combreloc can reorder and combine - them. */ +/* Classify dynamic relocs such that -z combreloc can reorder and + combine them. */ static enum elf_reloc_type_class -elf32_arc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, - const asection *rel_sec ATTRIBUTE_UNUSED, - const Elf_Internal_Rela *rela) +arc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, + const asection *rel_sec ATTRIBUTE_UNUSED, + const Elf_Internal_Rela *rela) { - switch ((int) ELF32_R_TYPE (rela->r_info)) + switch ((int) ELFNN_R_TYPE (rela->r_info)) { case R_ARC_RELATIVE: return reloc_class_relative; @@ -2821,47 +2998,44 @@ elf32_arc_reloc_type_class (const struct bfd_link_info *info ATTRIBUTE_UNUSED, return reloc_class_plt; case R_ARC_COPY: return reloc_class_copy; - /* TODO: Needed in future to support ifunc. */ - /* - case R_ARC_IRELATIVE: - return reloc_class_ifunc; - */ default: return reloc_class_normal; } } -const struct elf_size_info arc_elf32_size_info = -{ - sizeof (Elf32_External_Ehdr), - sizeof (Elf32_External_Phdr), - sizeof (Elf32_External_Shdr), - sizeof (Elf32_External_Rel), - sizeof (Elf32_External_Rela), - sizeof (Elf32_External_Sym), - sizeof (Elf32_External_Dyn), - sizeof (Elf_External_Note), - 4, - 1, - 32, 2, - ELFCLASS32, EV_CURRENT, - bfd_elf32_write_out_phdrs, - bfd_elf32_write_shdrs_and_ehdr, - bfd_elf32_checksum_contents, - bfd_elf32_write_relocs, - bfd_elf32_swap_symbol_in, - bfd_elf32_swap_symbol_out, - bfd_elf32_slurp_reloc_table, - bfd_elf32_slurp_symbol_table, - bfd_elf32_swap_dyn_in, - bfd_elf32_swap_dyn_out, - bfd_elf32_swap_reloc_in, - bfd_elf32_swap_reloc_out, - bfd_elf32_swap_reloca_in, - bfd_elf32_swap_reloca_out -}; +/* We use this so we can override certain functions + (though currently we don't). */ -#define elf_backend_size_info arc_elf32_size_info +const struct elf_size_info arc_elfNN_size_info = + { + sizeof (ElfNN_External_Ehdr), + sizeof (ElfNN_External_Phdr), + sizeof (ElfNN_External_Shdr), + sizeof (ElfNN_External_Rel), + sizeof (ElfNN_External_Rela), + sizeof (ElfNN_External_Sym), + sizeof (ElfNN_External_Dyn), + sizeof (Elf_External_Note), + 4, + 1, + ARCH_SIZE, + LOG_FILE_ALIGN, + ELFCLASSNN, EV_CURRENT, + bfd_elfNN_write_out_phdrs, + bfd_elfNN_write_shdrs_and_ehdr, + bfd_elfNN_checksum_contents, + bfd_elfNN_write_relocs, + bfd_elfNN_swap_symbol_in, + bfd_elfNN_swap_symbol_out, + bfd_elfNN_slurp_reloc_table, + bfd_elfNN_slurp_symbol_table, + bfd_elfNN_swap_dyn_in, + bfd_elfNN_swap_dyn_out, + bfd_elfNN_swap_reloc_in, + bfd_elfNN_swap_reloc_out, + bfd_elfNN_swap_reloca_in, + bfd_elfNN_swap_reloca_out + }; /* GDB expects general purpose registers to be in section .reg. However Linux kernel doesn't create this section and instead writes registers to NOTE @@ -2871,7 +3045,7 @@ const struct elf_size_info arc_elf32_size_info = stable. */ static bool -elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) +elfNN_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) { int offset; size_t size; @@ -2882,11 +3056,11 @@ elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) return false; case 236: /* sizeof (struct elf_prstatus) on Linux/arc. */ - /* pr_cursig */ + /* pr_cursig. */ elf_tdata (abfd)->core->signal = bfd_get_16 (abfd, note->descdata + 12); - /* pr_pid */ + /* pr_pid. */ elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24); - /* pr_regs */ + /* pr_regs. */ offset = 72; size = (40 * 4); /* There are 40 registers in user_regs_struct. */ break; @@ -2900,11 +3074,11 @@ elf32_arc_grok_prstatus (bfd *abfd, Elf_Internal_Note *note) string or both. */ static int -elf32_arc_obj_attrs_arg_type (int tag) +elfNN_arc_obj_attrs_arg_type (int tag) { if (tag == Tag_ARC_CPU_name - || tag == Tag_ARC_ISA_config - || tag == Tag_ARC_ISA_apex) + || tag == Tag_ARC_ISA_config + || tag == Tag_ARC_ISA_apex) return ATTR_TYPE_FLAG_STR_VAL; else if (tag < (Tag_ARC_ISA_mpy_option + 1)) return ATTR_TYPE_FLAG_INT_VAL; @@ -2915,7 +3089,7 @@ elf32_arc_obj_attrs_arg_type (int tag) /* Attribute numbers >=14 can be safely ignored. */ static bool -elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) +elfNN_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) { if ((tag & 127) < (Tag_ARC_ISA_mpy_option + 1)) { @@ -2934,12 +3108,12 @@ elf32_arc_obj_attrs_handle_unknown (bfd *abfd, int tag) } } -/* Handle an ARC specific section when reading an object file. This is - called when bfd_section_from_shdr finds a section with an unknown - type. */ +/* Handle an ARC specific section when reading an object file. This + is called when bfd_section_from_shdr finds a section with an + unknown type. */ static bool -elf32_arc_section_from_shdr (bfd *abfd, +elfNN_arc_section_from_shdr (bfd *abfd, Elf_Internal_Shdr * hdr, const char *name, int shindex) @@ -2960,13 +3134,138 @@ elf32_arc_section_from_shdr (bfd *abfd, return true; } +/* Delete a number of bytes from a given section while relaxing. */ + +static bool +arc_relax_delete_bytes (struct bfd_link_info *link_info, bfd *abfd, + asection *sec, bfd_vma addr, int count) +{ + Elf_Internal_Shdr *symtab_hdr; + unsigned int sec_shndx; + bfd_byte *contents; + Elf_Internal_Rela *irel, *irelend; + bfd_vma toaddr; + Elf_Internal_Sym *isym; + Elf_Internal_Sym *isymend; + struct elf_link_hash_entry **sym_hashes; + struct elf_link_hash_entry **end_hashes; + struct elf_link_hash_entry **start_hashes; + unsigned int symcount; + + sec_shndx = _bfd_elf_section_from_bfd_section (abfd, sec); + + contents = elf_section_data (sec)->this_hdr.contents; + + toaddr = sec->size; + + irel = elf_section_data (sec)->relocs; + irelend = irel + sec->reloc_count; + + /* Actually delete the bytes. */ + memmove (contents + addr, contents + addr + count, + (size_t) (toaddr - addr - count)); + sec->size -= count; + + /* Adjust all the relocs. */ + for (irel = elf_section_data (sec)->relocs; irel < irelend; irel++) + /* Get the new reloc address. */ + if ((irel->r_offset > addr && irel->r_offset < toaddr)) + irel->r_offset -= count; + + /* Adjust the local symbols defined in this section. */ + symtab_hdr = &elf_tdata (abfd)->symtab_hdr; + isym = (Elf_Internal_Sym *) symtab_hdr->contents; + for (isymend = isym + symtab_hdr->sh_info; isym < isymend; isym++) + { + if (isym->st_shndx == sec_shndx + && isym->st_value > addr + && isym->st_value <= toaddr) + { + /* Adjust the addend of SWITCH relocations in this section, + which reference this local symbol. */ + isym->st_value -= count; + } + } + + /* Now adjust the global symbols defined in this section. */ + symcount = (symtab_hdr->sh_size / sizeof (ElfNN_External_Sym) + - symtab_hdr->sh_info); + sym_hashes = start_hashes = elf_sym_hashes (abfd); + end_hashes = sym_hashes + symcount; + + for (; sym_hashes < end_hashes; sym_hashes++) + { + struct elf_link_hash_entry *sym_hash = *sym_hashes; + + /* The '--wrap SYMBOL' option is causing a pain when the object + file, containing the definition of __wrap_SYMBOL, includes a + direct call to SYMBOL as well. Since both __wrap_SYMBOL and + SYMBOL reference the same symbol (which is __wrap_SYMBOL), + but still exist as two different symbols in 'sym_hashes', we + don't want to adjust the global symbol __wrap_SYMBOL twice. + This check is only relevant when symbols are being + wrapped. */ + if (link_info->wrap_hash != NULL) + { + struct elf_link_hash_entry **cur_sym_hashes; + + /* Loop only over the symbols whom been already checked. */ + for (cur_sym_hashes = start_hashes; cur_sym_hashes < sym_hashes; + cur_sym_hashes++) + /* If the current symbol is identical to 'sym_hash', that means + the symbol was already adjusted (or at least checked). */ + if (*cur_sym_hashes == sym_hash) + break; + + /* Don't adjust the symbol again. */ + if (cur_sym_hashes < sym_hashes) + continue; + } + + if ((sym_hash->root.type == bfd_link_hash_defined + || sym_hash->root.type == bfd_link_hash_defweak) + && sym_hash->root.u.def.section == sec) + { + /* As above, adjust the value if needed. */ + if (sym_hash->root.u.def.value > addr + && sym_hash->root.u.def.value <= toaddr) + sym_hash->root.u.def.value -= count; + + /* As above, adjust the size if needed. */ + if (sym_hash->root.u.def.value <= addr + && sym_hash->root.u.def.value + sym_hash->size > addr + && sym_hash->root.u.def.value + sym_hash->size <= toaddr) + sym_hash->size -= count; + } + } + + return true; +} + +/* Check Tag_ARC_PCS_config if we can relax. */ +static bool +arc_can_relax_p (bfd *abfd) +{ + obj_attribute *attr = elf_known_obj_attributes_proc (abfd); + + if (attr[Tag_ARC_PCS_config].i & 0x100) + return true; + return false; +} + /* Relaxation hook. These are the current relaxing opportunities available: * R_ARC_GOTPC32 => R_ARC_PCREL. + * R_ARC_S25W_PCREL => R_ARC_S13_PCREL. -*/ + This is a two step relaxation procedure, in the first round, we + relax all the above opportunities. In the second round, we deal + with function align by removing unnecessary NOP_S placed by the + assembler. + + Inspired from CRX and RISCV backends. */ static bool arc_elf_relax_section (bfd *abfd, asection *sec, @@ -2977,10 +3276,14 @@ arc_elf_relax_section (bfd *abfd, asection *sec, Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; Elf_Internal_Sym *isymbuf = NULL; + bool do_relax = false; /* Assume nothing changes. */ *again = false; + /* Check if we can do size related relaxation. */ + do_relax = arc_can_relax_p (abfd); + /* 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. */ @@ -2988,6 +3291,7 @@ arc_elf_relax_section (bfd *abfd, asection *sec, || sec->reloc_count == 0 || (sec->flags & SEC_RELOC) == 0 || (sec->flags & SEC_HAS_CONTENTS) == 0 + || sec->sec_flg0 || (sec->flags & SEC_CODE) == 0) return true; @@ -3003,45 +3307,78 @@ arc_elf_relax_section (bfd *abfd, asection *sec, 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; + asection *sym_sec; + struct elf_link_hash_entry *htop = NULL; + bfd_vma symval; + + /* If this isn't something that can be relaxed, then ignore this + reloc. */ + if (ELFNN_R_TYPE (irel->r_info) != (int) R_ARC_GOTPC32 + && ELFNN_R_TYPE (irel->r_info) != (int) R_ARC_S25W_PCREL + && ELFNN_R_TYPE (irel->r_info) != (int) R_ARC_ALIGN) + 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; - } + { + /* 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; + { + 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; + } - if (ELF32_R_SYM (irel->r_info) >= symtab_hdr->sh_info) + /* Get the value of the symbol referred to by the reloc. */ + if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info) + { + /* A local symbol. */ + Elf_Internal_Sym *isym; + + isym = isymbuf + ELFNN_R_SYM (irel->r_info); + sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx); + symval = isym->st_value; + /* If the reloc is absolute, it will not have + a symbol or section associated with it. */ + if (sym_sec) + symval += sym_sec->output_section->vma + + sym_sec->output_offset; + } + else { /* An external symbol. */ - unsigned int indx = ELF32_R_SYM (irel->r_info) - symtab_hdr->sh_info; + unsigned int indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info; htop = elf_sym_hashes (abfd)[indx]; + + BFD_ASSERT (htop != NULL); + if (htop->root.type != bfd_link_hash_defined + && htop->root.type != bfd_link_hash_defweak) + /* This appears to be a reference to an undefined + symbol. Just ignore it--it will be caught by the + regular reloc processing. */ + continue; + + symval = (htop->root.u.def.value + + htop->root.u.def.section->output_section->vma + + htop->root.u.def.section->output_offset); + sym_sec = htop->root.u.def.section; } - if (ELF32_R_TYPE (irel->r_info) == (int) R_ARC_GOTPC32 - && SYMBOL_REFERENCES_LOCAL (link_info, htop)) + if (ELFNN_R_TYPE (irel->r_info) == (int) R_ARC_GOTPC32 + && SYMBOL_REFERENCES_LOCAL (link_info, htop) + && link_info->relax_pass == 0) { unsigned int code; @@ -3054,7 +3391,7 @@ arc_elf_relax_section (bfd *abfd, asection *sec, 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); + irel->r_info = ELFNN_R_INFO (ELFNN_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. @@ -3069,26 +3406,121 @@ arc_elf_relax_section (bfd *abfd, asection *sec, /* The size isn't changed, don't redo. */ *again = false; } + + /* Any of the next relax rules are changing the size, allow them + is assembler was informed. */ + if (!do_relax) + continue; + + if (ELFNN_R_TYPE (irel->r_info) == (int) R_ARC_S25W_PCREL + && link_info->relax_pass == 0) + { + unsigned int code; + bfd_vma value = symval + irel->r_addend; + bfd_vma dot, gap; + + /* Get the address (PCL) of this instruction. */ + dot = (sec->output_section->vma + + sec->output_offset + irel->r_offset) & ~0x03; + + /* Compute the distance from this insn to the branch target. */ + gap = value - dot; + + /* Check if the gap falls in the range that can be + accomodated in 13bit signed range (32-bit aligned). */ + if ((int) gap < -4094 || (int) gap > 4097 || ((int) gap & 0x3) != 0) + continue; + + /* Get the opcode. */ + code = bfd_get_32_me (abfd, contents + irel->r_offset); + /* bl @symb@pcl -> bl_s @symb@pcl. */ + /* 0000 1sss ssss ss10 SSSS SSSS SSNR tttt. */ + BFD_ASSERT ((code & 0xF8030000) == 0x08020000); + + /* Check for delay slot bit. */ + if (code & 0x20) + continue; + + /* 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 = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_ARC_S13_PCREL); + + /* Write back bl_s instruction. */ + bfd_put_16 (abfd, 0xF800, contents + irel->r_offset); + /* Delete two bytes of data. */ + if (!arc_relax_delete_bytes (link_info, abfd, sec, + irel->r_offset + 2, 2)) + goto error_return; + + *again = true; + } + + if (ELFNN_R_TYPE (irel->r_info) == (int) R_ARC_ALIGN + && link_info->relax_pass == 1) + { + bfd_vma aligned_addr; + bfd_vma nop_bytes; + bfd_vma alignment = 4; + + if (irel->r_addend == 2) + alignment = 2; + aligned_addr = ((irel->r_offset - 1) & ~(alignment - 1)) + alignment; + nop_bytes = aligned_addr - irel->r_offset; + + /* Cannot remove more than we have left. */ + BFD_ASSERT (irel->r_addend >= nop_bytes); + /* I should be always 16bit multiple quantum. */ + BFD_ASSERT (nop_bytes == 0 || nop_bytes == 2); + + /* Once we aligned we cannot relax anything else. */ + sec->sec_flg0 = true; + + /* 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; + + /* Delete the relocation's type. */ + irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), + R_ARC_NONE); + + /* Add an NOP_S if needed. */ + if (nop_bytes != 0) + bfd_put_16 (abfd, 0x78E0, contents + irel->r_offset); + + /* Delete nop_bytes bytes of data. */ + if (!arc_relax_delete_bytes (link_info, abfd, sec, + irel->r_offset + nop_bytes, + irel->r_addend - nop_bytes)) + goto error_return; + + *again = true; + } } if (isymbuf != NULL && symtab_hdr->contents != (unsigned char *) isymbuf) { if (!link_info->keep_memory) - free (isymbuf); + free (isymbuf); else - /* Cache the symbols for elf_link_input_bfd. */ - symtab_hdr->contents = (unsigned char *) isymbuf; + /* 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); + free (contents); else - /* Cache the section contents for elf_link_input_bfd. */ - elf_section_data (sec)->this_hdr.contents = contents; + /* 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) @@ -3107,24 +3539,35 @@ arc_elf_relax_section (bfd *abfd, asection *sec, return false; } -#define TARGET_LITTLE_SYM arc_elf32_le_vec -#define TARGET_LITTLE_NAME "elf32-littlearc" -#define TARGET_BIG_SYM arc_elf32_be_vec -#define TARGET_BIG_NAME "elf32-bigarc" -#define ELF_ARCH bfd_arch_arc +#define TARGET_LITTLE_SYM arcAA_elfNN_le_vec +#define TARGET_LITTLE_NAME "elfNN-littlearcAA" +#define TARGET_BIG_SYM arc_elfNN_be_vec +#define TARGET_BIG_NAME "elfNN-bigarc" +#define ELF_ARCH ARC_BFD_ARCH #define ELF_TARGET_ID ARC_ELF_DATA -#define ELF_MACHINE_CODE EM_ARC_COMPACT -#define ELF_MACHINE_ALT1 EM_ARC_COMPACT2 + +#if (ARCH_TYPE == ARC) && (ARCH_SIZE == 32) +# define ELF_MACHINE_CODE EM_ARC_COMPACT2 +# define ELF_MACHINE_ALT1 EM_ARC_COMPACT +#elif (ARCH_TYPE == ARC32) || (ARCH_TYPE == ARC64) +# define ELF_MACHINE_CODE EM_ARC_COMPACT3_64 +# define ELF_MACHINE_ALT1 EM_ARC_COMPACT3 +#else +# error "Unsupported ARC architecture" +#endif + #define ELF_MAXPAGESIZE 0x2000 -#define bfd_elf32_bfd_link_hash_table_create arc_elf_link_hash_table_create +#define bfd_elfNN_bfd_link_hash_table_create arc_elf_link_hash_table_create + +#define bfd_elfNN_bfd_merge_private_bfd_data arc_elf_merge_private_bfd_data +#define bfd_elfNN_bfd_reloc_type_lookup arc_elfNN_bfd_reloc_type_lookup +#define bfd_elfNN_bfd_set_private_flags arc_elf_set_private_flags +#define bfd_elfNN_bfd_print_private_bfd_data arc_elf_print_private_bfd_data +#define bfd_elfNN_bfd_copy_private_bfd_data arc_elf_copy_private_bfd_data +#define bfd_elfNN_bfd_relax_section arc_elf_relax_section -#define bfd_elf32_bfd_merge_private_bfd_data arc_elf_merge_private_bfd_data -#define bfd_elf32_bfd_reloc_type_lookup arc_elf32_bfd_reloc_type_lookup -#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_backend_size_info arc_elfNN_size_info #define elf_info_to_howto_rel arc_info_to_howto_rel #define elf_backend_object_p arc_elf_object_p @@ -3134,7 +3577,7 @@ arc_elf_relax_section (bfd *abfd, asection *sec, #define elf_backend_check_relocs elf_arc_check_relocs #define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections -#define elf_backend_reloc_type_class elf32_arc_reloc_type_class +#define elf_backend_reloc_type_class arc_reloc_type_class #define elf_backend_adjust_dynamic_symbol elf_arc_adjust_dynamic_symbol #define elf_backend_finish_dynamic_symbol elf_arc_finish_dynamic_symbol @@ -3147,14 +3590,14 @@ arc_elf_relax_section (bfd *abfd, asection *sec, #define elf_backend_plt_readonly 1 #define elf_backend_rela_plts_and_copies_p 1 #define elf_backend_want_plt_sym 0 -#define elf_backend_got_header_size 12 +#define elf_backend_got_header_size (GOT_ENTRY_SIZE * 3) #define elf_backend_dtrel_excludes_plt 1 #define elf_backend_may_use_rel_p 0 #define elf_backend_may_use_rela_p 1 #define elf_backend_default_use_rela_p 1 -#define elf_backend_grok_prstatus elf32_arc_grok_prstatus +#define elf_backend_grok_prstatus elfNN_arc_grok_prstatus #define elf_backend_default_execstack 0 @@ -3163,11 +3606,12 @@ arc_elf_relax_section (bfd *abfd, asection *sec, #undef elf_backend_obj_attrs_section #define elf_backend_obj_attrs_section ".ARC.attributes" #undef elf_backend_obj_attrs_arg_type -#define elf_backend_obj_attrs_arg_type elf32_arc_obj_attrs_arg_type +#define elf_backend_obj_attrs_arg_type elfNN_arc_obj_attrs_arg_type #undef elf_backend_obj_attrs_section_type #define elf_backend_obj_attrs_section_type SHT_ARC_ATTRIBUTES -#define elf_backend_obj_attrs_handle_unknown elf32_arc_obj_attrs_handle_unknown +#define elf_backend_obj_attrs_handle_unknown \ + elfNN_arc_obj_attrs_handle_unknown -#define elf_backend_section_from_shdr elf32_arc_section_from_shdr +#define elf_backend_section_from_shdr elfNN_arc_section_from_shdr -#include "elf32-target.h" +#include "elfNN-target.h" diff --git a/bfd/libbfd.h b/bfd/libbfd.h index d5f42f22c08..b97d0f7910d 100644 --- a/bfd/libbfd.h +++ b/bfd/libbfd.h @@ -1876,6 +1876,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARC_16", "BFD_RELOC_ARC_24", "BFD_RELOC_ARC_32", + "BFD_RELOC_ARC_64", "BFD_RELOC_ARC_N8", "BFD_RELOC_ARC_N16", "BFD_RELOC_ARC_N24", @@ -1940,6 +1941,27 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@", "BFD_RELOC_ARC_S21H_PCREL_PLT", "BFD_RELOC_ARC_NPS_CMEM16", "BFD_RELOC_ARC_JLI_SECTOFF", + "BFD_RELOC_ARC_S7H_PCREL", + "BFD_RELOC_ARC_S8H_PCREL", + "BFD_RELOC_ARC_S9H_PCREL", + "BFD_RELOC_ARC_S10H_PCREL", + "BFD_RELOC_ARC_S13H_PCREL", + "BFD_RELOC_ARC_ALIGN", + "BFD_RELOC_ARC_ADD8", + "BFD_RELOC_ARC_ADD16", + "BFD_RELOC_ARC_SUB8", + "BFD_RELOC_ARC_SUB16", + "BFD_RELOC_ARC_SUB32", + "BFD_RELOC_ARC_LO32", + "BFD_RELOC_ARC_HI32", + "BFD_RELOC_ARC_LO32_ME", + "BFD_RELOC_ARC_HI32_ME", + "BFD_RELOC_ARC_N64", + "BFD_RELOC_ARC_SDA_LDST3", + "BFD_RELOC_ARC_NLO32", + "BFD_RELOC_ARC_NLO32_ME", + "BFD_RELOC_ARC_PCLO32_ME_2", + "BFD_RELOC_ARC_PLT34", "BFD_RELOC_BFIN_16_IMM", "BFD_RELOC_BFIN_16_HIGH", "BFD_RELOC_BFIN_4_PCREL", diff --git a/bfd/reloc.c b/bfd/reloc.c index 2ac883d0eac..bba269a9b74 100644 --- a/bfd/reloc.c +++ b/bfd/reloc.c @@ -3424,6 +3424,8 @@ ENUMX BFD_RELOC_ARC_24 ENUMX BFD_RELOC_ARC_32 +ENUMX + BFD_RELOC_ARC_64 ENUMX BFD_RELOC_ARC_N8 ENUMX @@ -3552,6 +3554,48 @@ ENUMX BFD_RELOC_ARC_NPS_CMEM16 ENUMX BFD_RELOC_ARC_JLI_SECTOFF +ENUMX + BFD_RELOC_ARC_S7H_PCREL +ENUMX + BFD_RELOC_ARC_S8H_PCREL +ENUMX + BFD_RELOC_ARC_S9H_PCREL +ENUMX + BFD_RELOC_ARC_S10H_PCREL +ENUMX + BFD_RELOC_ARC_S13H_PCREL +ENUMX + BFD_RELOC_ARC_ALIGN +ENUMX + BFD_RELOC_ARC_ADD8 +ENUMX + BFD_RELOC_ARC_ADD16 +ENUMX + BFD_RELOC_ARC_SUB8 +ENUMX + BFD_RELOC_ARC_SUB16 +ENUMX + BFD_RELOC_ARC_SUB32 +ENUMX + BFD_RELOC_ARC_LO32 +ENUMX + BFD_RELOC_ARC_HI32 +ENUMX + BFD_RELOC_ARC_LO32_ME +ENUMX + BFD_RELOC_ARC_HI32_ME +ENUMX + BFD_RELOC_ARC_N64 +ENUMX + BFD_RELOC_ARC_SDA_LDST3 +ENUMX + BFD_RELOC_ARC_NLO32 +ENUMX + BFD_RELOC_ARC_NLO32_ME +ENUMX + BFD_RELOC_ARC_PCLO32_ME_2 +ENUMX + BFD_RELOC_ARC_PLT34 ENUMDOC ARC relocs. diff --git a/bfd/targets.c b/bfd/targets.c index 63b3abbd287..e9d608d9918 100644 --- a/bfd/targets.c +++ b/bfd/targets.c @@ -695,6 +695,8 @@ extern const bfd_target amdgcn_elf64_le_vec; extern const bfd_target aout_vec; extern const bfd_target arc_elf32_be_vec; extern const bfd_target arc_elf32_le_vec; +extern const bfd_target arc64_elf32_le_vec; +extern const bfd_target arc64_elf64_le_vec; extern const bfd_target arm_elf32_be_vec; extern const bfd_target arm_elf32_le_vec; extern const bfd_target arm_elf32_fdpic_be_vec; @@ -999,6 +1001,10 @@ static const bfd_target * const _bfd_target_vector[] = &aarch64_mach_o_vec, &aarch64_pe_le_vec, &aarch64_pei_le_vec, + &arc_elf32_be_vec, + &arc_elf32_le_vec, + &arc64_elf32_le_vec, + &arc64_elf64_le_vec, #endif #ifdef BFD64 -- 2.30.2