diff --git a/bfd/config.bfd b/bfd/config.bfd
index a4c6c8e885..9edd7a0a15 100644
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -238,6 +238,11 @@ esac
case "${targ}" in
# START OF targmatch.h
#ifdef BFD64
+ aarch64-*-solaris2*)
+ targ_defvec=aarch64_elf64_le_vec
+ targ_selvecs="aarch64_elf64_be_vec aarch64_elf32_le_vec aarch64_elf32_be_vec arm_elf32_le_vec arm_elf32_be_vec"
+ want64=true
+ ;;
aarch64-*-darwin*)
targ_defvec=aarch64_mach_o_vec
targ_selvecs="arm_mach_o_vec mach_o_le_vec mach_o_be_vec mach_o_fat_vec"
diff --git a/bfd/configure b/bfd/configure
index 24531087d4..a0aed712a5 100755
--- a/bfd/configure
+++ b/bfd/configure
@@ -13757,6 +13757,9 @@ CORE_HEADER=
TRAD_HEADER=
if test "${target}" = "${host}"; then
case "${host}" in
+ aarch64*-*-solaris*)
+ COREFILE=''
+ ;;
alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-*vms*)
COREFILE=''
;;
@@ -13853,6 +13856,9 @@ if test "${target}" = "${host}"; then
ns32k-*-netbsd* | ns32k-*-openbsd*)
COREFILE=netbsd-core.lo
;;
+ riscv64-*-solaris*)
+ COREFILE=''
+ ;;
rs6000-*-lynx*)
COREFILE=lynx-core.lo
;;
diff --git a/bfd/configure.ac b/bfd/configure.ac
index 6146efb5ae..2f701a7f51 100644
--- a/bfd/configure.ac
+++ b/bfd/configure.ac
@@ -801,6 +801,9 @@ CORE_HEADER=
TRAD_HEADER=
if test "${target}" = "${host}"; then
case "${host}" in
+ aarch64*-*-solaris*)
+ COREFILE=''
+ ;;
alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu | alpha*-*-*vms*)
COREFILE=''
;;
@@ -921,6 +924,9 @@ changequote([,])dnl
ns32k-*-netbsd* | ns32k-*-openbsd*)
COREFILE=netbsd-core.lo
;;
+ riscv64-*-solaris*)
+ COREFILE=''
+ ;;
rs6000-*-lynx*)
COREFILE=lynx-core.lo
;;
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 2b1450fa4e..5c51c67921 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -6954,6 +6954,11 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
for (n = t->deps; n != NULL; n = n->next)
{
+ if (n->version_needed_name) {
+ info->callbacks->einfo(_("%Xversion `%s' is not found\n"),
+ n->version_needed_name);
+ }
+ BFD_ASSERT (n->version_needed_name == NULL);
if (n->version_needed == NULL)
{
/* This can happen if there was an error in the
@@ -7321,7 +7326,11 @@ NOTE: This behaviour is deprecated and will be removed in a future version of th
if (!_bfd_elf_add_dynamic_entry (info, DT_FINI, 0))
return false;
}
-
+ if (info->rtldinfo)
+ {
+ if (!_bfd_elf_add_dynamic_entry (info, DT_SUNW_RTLDINF, 0))
+ return false;
+ }
s = bfd_get_section_by_name (output_bfd, ".preinit_array");
if (s != NULL && s->linker_has_input)
{
@@ -13182,7 +13191,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info)
relr_entsize = 0;
}
continue;
-
+ case DT_SUNW_RTLDINF:
+ name = info->rtldinfo_name;
+ goto get_sym;
case DT_INIT:
name = info->init_function;
goto get_sym;
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c
index 251a27edb5..827722e7ee 100644
--- a/bfd/elfnn-aarch64.c
+++ b/bfd/elfnn-aarch64.c
@@ -9989,6 +9989,59 @@ const struct elf_size_info elfNN_aarch64_size_info =
bfd_elfNN_swap_reloca_out
};
+static int
+elfNN_aarch64_additional_program_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ asection *s;
+ int count = 0;
+
+ /* Check to see if we need a large readonly segment. */
+ s = bfd_get_section_by_name (abfd, ".dtrace_data");
+ if (s && (s->flags & SEC_LOAD))
+ count++;
+
+ return count;
+}
+
+#define PT_SUNWDTRACE 0x6ffffffc
+static bool
+elfNN_aarch64_modify_segment_map (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
+{
+ struct elf_segment_map *m;
+ asection *sec;
+
+ sec = bfd_get_section_by_name (abfd, ".dtrace_data");
+ if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
+ {
+ m = elf_seg_map (abfd);
+ while (m && m->p_type != PT_SUNWDTRACE)
+ m = m->next;
+
+ if (!m)
+ {
+ m = (struct elf_segment_map *) bfd_zalloc(abfd, sizeof (struct elf_segment_map));
+ if (m == NULL)
+ return false;
+ m->p_type = PT_SUNWDTRACE;
+ m->count = 1;
+ m->sections[0] = sec;
+ m->next = elf_seg_map (abfd);
+ elf_seg_map (abfd) = m;
+ }
+ }
+
+ return true;
+}
+
+static const struct bfd_elf_special_section
+ elfNN_aarch64_special_sections[]=
+{
+ { STRING_COMMA_LEN (".dtrace_data"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR},
+ { NULL, 0, 0, 0, 0 }
+};
+
#define ELF_ARCH bfd_arch_aarch64
#define ELF_MACHINE_CODE EM_AARCH64
#define ELF_MAXPAGESIZE 0x10000
@@ -10104,6 +10157,15 @@ const struct elf_size_info elfNN_aarch64_size_info =
#define elf_backend_merge_gnu_properties \
elfNN_aarch64_merge_gnu_properties
+#define elf_backend_special_sections \
+ elfNN_aarch64_special_sections
+
+#define elf_backend_modify_segment_map \
+ elfNN_aarch64_modify_segment_map
+
+#define elf_backend_additional_program_headers \
+ elfNN_aarch64_additional_program_headers
+
#define elf_backend_can_refcount 1
#define elf_backend_can_gc_sections 1
#define elf_backend_plt_readonly 1
diff --git a/bfd/elfnn-riscv.c b/bfd/elfnn-riscv.c
index 8f9f0d8a86..ec84f3e442 100644
--- a/bfd/elfnn-riscv.c
+++ b/bfd/elfnn-riscv.c
@@ -5169,9 +5169,16 @@ riscv_elf_additional_program_headers (bfd *abfd,
if (bfd_get_section_by_name (abfd, RISCV_ATTRIBUTES_SECTION_NAME))
++ret;
+ /* Check to see if we need a large readonly segment. */
+ asection *s = bfd_get_section_by_name (abfd, ".dtrace_data");
+ if (s && (s->flags & SEC_LOAD))
+ ++ret;
+
return ret;
}
+#define PT_SUNWDTRACE 0x6ffffffc
+
static bool
riscv_elf_modify_segment_map (bfd *abfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -5213,6 +5220,26 @@ riscv_elf_modify_segment_map (bfd *abfd,
}
}
+ asection *sec = bfd_get_section_by_name (abfd, ".dtrace_data");
+ if (sec != NULL && (sec->flags & SEC_LOAD) != 0)
+ {
+ m = elf_seg_map (abfd);
+ while (m && m->p_type != PT_SUNWDTRACE)
+ m = m->next;
+
+ if (!m)
+ {
+ m = (struct elf_segment_map *) bfd_zalloc(abfd, sizeof (struct elf_segment_map));
+ if (m == NULL)
+ return false;
+ m->p_type = PT_SUNWDTRACE;
+ m->count = 1;
+ m->sections[0] = sec;
+ m->next = elf_seg_map (abfd);
+ elf_seg_map (abfd) = m;
+ }
+ }
+
return true;
}
@@ -5238,6 +5265,13 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
h->other |= STO_RISCV_VARIANT_CC;
}
+static const struct bfd_elf_special_section
+ riscv_elf_special_sections[]=
+{
+ { STRING_COMMA_LEN (".dtrace_data"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_EXECINSTR},
+ { NULL, 0, 0, 0, 0 }
+};
+
#define TARGET_LITTLE_SYM riscv_elfNN_vec
#define TARGET_LITTLE_NAME "elfNN-littleriscv"
#define TARGET_BIG_SYM riscv_elfNN_be_vec
@@ -5278,6 +5312,8 @@ riscv_elf_merge_symbol_attribute (struct elf_link_hash_entry *h,
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
+#define elf_backend_special_sections riscv_elf_special_sections
+
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
#define elf_backend_want_got_plt 1
diff --git a/gas/configure.tgt b/gas/configure.tgt
index 62f806bdfe..80e5a4d385 100644
--- a/gas/configure.tgt
+++ b/gas/configure.tgt
@@ -134,6 +134,7 @@ case ${generic_target} in
aarch64*-linux-gnu_ilp32) arch=aarch64:32 ;;
esac ;;
aarch64*-*-netbsd*) fmt=elf em=nbsd;;
+ aarch64*-*-solaris*) fmt=elf em=solaris ;;
alpha-*-*vms*) fmt=evax ;;
alpha-*-osf*) fmt=ecoff ;;
@@ -369,6 +370,7 @@ case ${generic_target} in
pru-*-*) fmt=elf ;;
+ riscv64-*-solaris*) fmt=elf endian=little em=solaris ;;
riscv*-*-haiku*) fmt=elf endian=little em=haiku ;;
riscv*-*-*) fmt=elf ;;
diff --git a/gas/dw2gencfi.c b/gas/dw2gencfi.c
index 961a3b9218..46d9212d38 100644
--- a/gas/dw2gencfi.c
+++ b/gas/dw2gencfi.c
@@ -257,7 +257,7 @@ get_debugseg_name (segT seg, const char *base_name)
else
name = dollar;
- return concat (base_name, name, NULL);
+ return concat (base_name, name, (void *)0);
}
/* Allocate a dwcfi_seg_list structure. */
diff --git a/gdb/aarch64-sol2-nat.c b/gdb/aarch64-sol2-nat.c
new file mode 100644
index 0000000000..527958d819
--- /dev/null
+++ b/gdb/aarch64-sol2-nat.c
@@ -0,0 +1,53 @@
+/* Native-dependent code for Solaris SPARC.
+
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "defs.h"
+#include "regcache.h"
+
+#include
+#include "gregset.h"
+
+#include "aarch64-tdep.h"
+#include "aarch64-sol2-tdep.h"
+#include "target.h"
+#include "procfs.h"
+
+void
+supply_gregset (struct regcache *regcache, const prgregset_t *gregs)
+{
+ regcache_supply_regset (&aarch64_sol2_gregset, regcache, -1, (const gdb_byte *) gregs, AARCH64_SOL2_SIZEOF_GREGSET);
+}
+
+void
+supply_fpregset (struct regcache *regcache, const prfpregset_t *fpregs)
+{
+ regcache_supply_regset (&aarch64_sol2_fpregset, regcache, -1, (const gdb_byte *) fpregs, AARCH64_SOL2_SIZEOF_FPREGSET);
+}
+
+void
+fill_gregset (const struct regcache *regcache, prgregset_t *gregs, int regnum)
+{
+ regcache_collect_regset (&aarch64_sol2_gregset, regcache, regnum, (gdb_byte *) gregs, AARCH64_SOL2_SIZEOF_GREGSET);
+}
+
+void
+fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs, int regnum)
+{
+ regcache_collect_regset (&aarch64_sol2_fpregset, regcache, regnum, (gdb_byte *) fpregs, AARCH64_SOL2_SIZEOF_FPREGSET);
+}
diff --git a/gdb/aarch64-sol2-tdep.c b/gdb/aarch64-sol2-tdep.c
new file mode 100644
index 0000000000..7918e51f8d
--- /dev/null
+++ b/gdb/aarch64-sol2-tdep.c
@@ -0,0 +1,253 @@
+/* Target-dependent code for Newlib AArch64.
+
+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "gdbarch.h"
+#include "aarch64-tdep.h"
+#include "aarch64-sol2-tdep.h"
+#include "osabi.h"
+#include "inferior.h"
+#include "regcache.h"
+#include "regset.h"
+#include "solib-svr4.h"
+#include "trad-frame.h"
+#include "sol2-tdep.h"
+#include "stap-probe.h"
+#include "parser-defs.h"
+#include "user-regs.h"
+#include
+
+/* Register maps. */
+
+static const struct regcache_map_entry aarch64_sol2_gregmap[] =
+ {
+ { 31, AARCH64_X0_REGNUM, 8 }, /* x0 ... x30 */
+ { 1, AARCH64_SP_REGNUM, 8 },
+ { 1, AARCH64_PC_REGNUM, 8 },
+ { 1, AARCH64_CPSR_REGNUM, 8 },
+ { 0 }
+ };
+
+static const struct regcache_map_entry aarch64_sol2_fpregmap[] =
+ {
+ { 32, AARCH64_V0_REGNUM, 16 }, /* v0 ... v31 */
+ { 1, AARCH64_FPCR_REGNUM, 4 },
+ { 1, AARCH64_FPSR_REGNUM, 4 },
+ { 0 }
+ };
+
+/* Register set definitions. */
+
+const struct regset aarch64_sol2_gregset =
+ {
+ aarch64_sol2_gregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+const struct regset aarch64_sol2_fpregset =
+ {
+ aarch64_sol2_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+/* Implement the "regset_from_core_section" gdbarch method. */
+
+static void
+aarch64_sol2_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
+{
+ cb (".reg", AARCH64_SOL2_SIZEOF_GREGSET, AARCH64_SOL2_SIZEOF_GREGSET, &aarch64_sol2_gregset,
+ NULL, cb_data);
+ cb (".reg2", AARCH64_SOL2_SIZEOF_FPREGSET, AARCH64_SOL2_SIZEOF_FPREGSET, &aarch64_sol2_fpregset,
+ NULL, cb_data);
+}
+
+
+struct aarch64_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+
+ /* Do we have a frame? */
+ int frameless_p;
+
+ /* The offset from the base register to the CFA. */
+ int frame_offset;
+
+ /* Mask of `local' and `in' registers saved in the register save area. */
+ unsigned short int saved_regs_mask;
+
+ /* Mask of `out' registers copied or renamed to their `in' sibling. */
+ unsigned char copied_regs_mask;
+
+ /* Do we have a Structure, Union or Quad-Precision return value? */
+ int struct_return_p;
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static CORE_ADDR
+aarch64_sol2_mcontext_addr (struct frame_info *this_frame)
+{
+ CORE_ADDR ucontext_addr;
+
+ ucontext_addr = get_frame_register_unsigned (this_frame, AARCH64_X0_REGNUM + 2);
+ return ucontext_addr + 8 * 7;
+}
+
+static struct aarch64_frame_cache *
+aarch64_alloc_frame_cache (void)
+{
+ struct aarch64_frame_cache *cache;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct aarch64_frame_cache);
+
+ /* Base address. */
+ cache->base = 0;
+ cache->pc = 0;
+
+ /* Frameless until proven otherwise. */
+ cache->frameless_p = 1;
+ cache->frame_offset = 0;
+ cache->saved_regs_mask = 0;
+ cache->copied_regs_mask = 0;
+ cache->struct_return_p = 0;
+
+ return cache;
+}
+
+static struct aarch64_frame_cache *
+aarch64_sol2_sigtramp_frame_cache (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct aarch64_frame_cache *cache;
+ CORE_ADDR mcontext_addr;
+ int regnum;
+
+ if (*this_cache)
+ return (aarch64_frame_cache*)*this_cache;
+
+ cache = aarch64_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ mcontext_addr = aarch64_sol2_mcontext_addr (this_frame);
+
+ for (regnum = 0; regnum < 31; regnum++)
+ cache->saved_regs[regnum].set_addr(mcontext_addr + regnum * 8);
+ cache->saved_regs[AARCH64_SP_REGNUM].set_addr(mcontext_addr + 31 * 8); // sp
+ cache->saved_regs[AARCH64_PC_REGNUM].set_addr(mcontext_addr + 32 * 8); // pc
+ cache->saved_regs[AARCH64_CPSR_REGNUM].set_addr(mcontext_addr + 33 * 8); // cpsr
+
+ for (regnum = 0; regnum < 32; regnum++)
+ cache->saved_regs[regnum + AARCH64_V0_REGNUM].set_addr(mcontext_addr + 36 * 8 + regnum * 16);
+
+ cache->saved_regs[AARCH64_FPCR_REGNUM].set_addr(mcontext_addr + 36 * 8 + 32 * 16);
+ cache->saved_regs[AARCH64_FPSR_REGNUM].set_addr(mcontext_addr + 36 * 8 + 32 * 16 + 4);
+
+ return cache;
+}
+
+static void
+aarch64_sol2_sigtramp_frame_this_id (struct frame_info *this_frame,
+ void **this_cache,
+ struct frame_id *this_id)
+{
+ struct aarch64_frame_cache *cache =
+ aarch64_sol2_sigtramp_frame_cache (this_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static struct value *
+aarch64_sol2_sigtramp_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache,
+ int regnum)
+{
+ struct aarch64_frame_cache *cache =
+ aarch64_sol2_sigtramp_frame_cache (this_frame, this_cache);
+
+ struct value *ret = trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+ return ret;
+}
+
+static int
+aarch64_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_cache)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ const char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ return (name && (strcmp ("sigacthandler", name) == 0 || strcmp (name, "ucbsigvechandler") == 0));
+}
+
+
+static const struct frame_unwind aarch64_sol2_sigtramp_frame_unwind =
+{
+ "aarch64 solaris sigtramp",
+ SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
+ aarch64_sol2_sigtramp_frame_this_id,
+ aarch64_sol2_sigtramp_frame_prev_register,
+ NULL,
+ aarch64_sol2_sigtramp_frame_sniffer
+};
+
+
+/* Implement the 'init_osabi' method of struct gdb_osabi_handler. */
+
+static void
+aarch64_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ aarch64_gdbarch_tdep *tdep = (aarch64_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ tdep->lowest_pc = 0x8000;
+ tdep->jb_pc = 11;
+
+ frame_unwind_append_unwinder (gdbarch, &aarch64_sol2_sigtramp_frame_unwind);
+ sol2_init_abi (info, gdbarch);
+
+ /* Solaris has SVR4-style shared libraries... */
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+ set_solib_svr4_fetch_link_map_offsets (gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+ /* Solaris has kernel-assisted single-stepping support. */
+ /* Breakpoint manipulation. */
+ set_gdbarch_software_single_step (gdbarch, NULL);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_aarch64_sol2_tdep;
+
+void
+_initialize_aarch64_sol2_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_aarch64, 0, GDB_OSABI_SOLARIS,
+ aarch64_sol2_init_abi);
+}
diff --git a/gdb/aarch64-sol2-tdep.h b/gdb/aarch64-sol2-tdep.h
new file mode 100644
index 0000000000..3592030fc6
--- /dev/null
+++ b/gdb/aarch64-sol2-tdep.h
@@ -0,0 +1,31 @@
+/* GNU/Linux on AArch64 target support, prototypes.
+
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "regset.h"
+
+/* X0 - X31, SP, PC, PSR, TP */
+#define AARCH64_SOL2_SIZEOF_GREGSET (36 * X_REGISTER_SIZE)
+
+/* V0 - V31, FPCR, FPSR */
+#define AARCH64_SOL2_SIZEOF_FPREGSET (33 * V_REGISTER_SIZE)
+
+extern const struct regset aarch64_sol2_gregset;
+extern const struct regset aarch64_sol2_fpregset;
+
diff --git a/gdb/config/aarch64/nm-sol2.h b/gdb/config/aarch64/nm-sol2.h
new file mode 100644
index 0000000000..bee367004e
--- /dev/null
+++ b/gdb/config/aarch64/nm-sol2.h
@@ -0,0 +1,26 @@
+/* Native-dependent definitions for Solaris AArch64.
+
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#ifndef NM_SOL2_H
+#define NM_SOL2_H
+
+#define GDB_GREGSET_T prgregset_t
+#define GDB_FPREGSET_T prfpregset_t
+
+#endif /* nm-sol2.h */
diff --git a/gdb/config/riscv64/nm-sol2.h b/gdb/config/riscv64/nm-sol2.h
new file mode 100644
index 0000000000..90c663de94
--- /dev/null
+++ b/gdb/config/riscv64/nm-sol2.h
@@ -0,0 +1,26 @@
+/* Native-dependent definitions for Solaris RISC-V.
+
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#ifndef NM_SOL2_H
+#define NM_SOL2_H
+
+#define GDB_GREGSET_T prgregset_t
+#define GDB_FPREGSET_T prfpregset_t
+
+#endif /* nm-sol2.h */
diff --git a/gdb/configure.host b/gdb/configure.host
index da71675b20..e98f88092f 100644
--- a/gdb/configure.host
+++ b/gdb/configure.host
@@ -81,6 +81,7 @@ case "${host}" in
aarch64*-*-linux*) gdb_host=linux ;;
aarch64*-*-freebsd*) gdb_host=fbsd ;;
+aarch64*-*-solaris2.1[0-9]*) gdb_host=sol2 ;;
alpha*-*-linux*) gdb_host=alpha-linux ;;
alpha*-*-netbsdaout* | alpha*-*-knetbsdaout*-gnu)
@@ -147,6 +148,7 @@ powerpc*-*-linux*) gdb_host=linux ;;
riscv*-*-freebsd*) gdb_host=fbsd ;;
riscv*-*-linux*) gdb_host=linux ;;
+riscv*-*-solaris2.1[0-9]*) gdb_host=sol2 ;;
s390*-*-linux*) gdb_host=linux ;;
diff --git a/gdb/configure.nat b/gdb/configure.nat
index d219d6a960..1177f3ad06 100644
--- a/gdb/configure.nat
+++ b/gdb/configure.nat
@@ -498,6 +498,16 @@ case ${gdb_host} in
NAT_FILE='nm-sol2.h'
NATDEPFILES="${NATDEPFILES} sparc-sol2-nat.o"
;;
+ aarch64)
+ # Host: Solaris AArch64
+ NAT_FILE='nm-sol2.h'
+ NATDEPFILES="${NATDEPFILES} aarch64-sol2-nat.o"
+ ;;
+ riscv*)
+ # Host: Solaris RISC-V
+ NAT_FILE='nm-sol2.h'
+ NATDEPFILES="${NATDEPFILES} riscv-sol2-nat.o"
+ ;;
esac
;;
esac
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index 0705ccf32b..ee59691912 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -144,6 +144,12 @@ aarch64*-*-linux*)
symfile-mem.o linux-record.o"
;;
+aarch64*-*-solaris2.1[0-9]*)
+ # Target: AArch64 Solaris
+ gdb_target_obs="aarch64-tdep.o aarch64-sol2-tdep.o arch/aarch64-insn.o arch/aarch64.o \
+ sol2-tdep.o solib-svr4.o ravenscar-thread.o aarch64-ravenscar-thread.o"
+ ;;
+
alpha*-*-linux*)
# Target: Little-endian Alpha running Linux
gdb_target_obs="alpha-mdebug-tdep.o alpha-linux-tdep.o \
@@ -535,6 +541,12 @@ riscv*-*-linux*)
linux-tdep.o solib-svr4.o symfile-mem.o linux-record.o"
;;
+riscv*-*-solaris2.1[0-9]*)
+ # Target: RISC-V Solaris
+ gdb_target_obs="riscv-sol2-tdep.o \
+ sol2-tdep.o solib-svr4.o"
+ ;;
+
riscv*-*-*)
# Target: RISC-V architecture
gdb_target_obs=""
diff --git a/gdb/procfs.c b/gdb/procfs.c
index ffb4d18029..b5bd8b24d6 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -2155,7 +2155,7 @@ procfs_target::wait (ptid_t ptid, struct target_waitstatus *status,
}
else
{
- int temp = ::wait (&wstat);
+ int temp = ::waitpid(pi->pid, &wstat, 0);
/* FIXME: shouldn't I make sure I get the right
event from the right process? If (for
diff --git a/gdb/riscv-sol2-nat.c b/gdb/riscv-sol2-nat.c
new file mode 100644
index 0000000000..bff150ee1f
--- /dev/null
+++ b/gdb/riscv-sol2-nat.c
@@ -0,0 +1,57 @@
+/* Native-dependent code for Solaris SPARC.
+
+ Copyright (C) 2003-2014 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "defs.h"
+#include "regcache.h"
+
+#include
+#include "gregset.h"
+
+#include "riscv-tdep.h"
+#include "riscv-sol2-tdep.h"
+#include "target.h"
+#include "procfs.h"
+
+void
+supply_gregset (struct regcache *regcache, const prgregset_t *gregs)
+{
+ int xlen = register_size (regcache->arch(), RISCV_RA_REGNUM);
+ regcache_supply_regset (&riscv_sol2_gregset, regcache, -1, (const gdb_byte *) gregs, xlen * 32);
+}
+
+void
+supply_fpregset (struct regcache *regcache, const prfpregset_t *fpregs)
+{
+ int flen = register_size (regcache->arch(), RISCV_FIRST_FP_REGNUM);
+ regcache_supply_regset (&riscv_sol2_fpregset, regcache, -1, (const gdb_byte *) fpregs, flen * 32 + 8);
+}
+
+void
+fill_gregset (const struct regcache *regcache, prgregset_t *gregs, int regnum)
+{
+ int xlen = register_size (regcache->arch(), RISCV_RA_REGNUM);
+ regcache_collect_regset (&riscv_sol2_gregset, regcache, regnum, (gdb_byte *) gregs, xlen * 32);
+}
+
+void
+fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs, int regnum)
+{
+ int flen = register_size (regcache->arch(), RISCV_FIRST_FP_REGNUM);
+ regcache_collect_regset (&riscv_sol2_fpregset, regcache, regnum, (gdb_byte *) fpregs, flen * 32 + 8);
+}
diff --git a/gdb/riscv-sol2-tdep.c b/gdb/riscv-sol2-tdep.c
new file mode 100644
index 0000000000..e827d743a0
--- /dev/null
+++ b/gdb/riscv-sol2-tdep.c
@@ -0,0 +1,248 @@
+/* Target-dependent code for Newlib AArch64.
+
+ Copyright (C) 2011-2014 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "defs.h"
+#include "frame.h"
+#include "frame-unwind.h"
+#include "gdbarch.h"
+#include "riscv-tdep.h"
+#include "riscv-sol2-tdep.h"
+#include "osabi.h"
+#include "inferior.h"
+#include "regcache.h"
+#include "regset.h"
+#include "solib-svr4.h"
+#include "trad-frame.h"
+#include "sol2-tdep.h"
+#include "stap-probe.h"
+#include "parser-defs.h"
+#include "user-regs.h"
+#include
+
+/* Register maps. */
+
+static const struct regcache_map_entry riscv_sol2_gregmap[] =
+ {
+ { 31, RISCV_RA_REGNUM, 0 }, /* x1 to x31 */
+ { 1, RISCV_PC_REGNUM, 0 },
+ { 0 }
+};
+
+static const struct regcache_map_entry riscv_sol2_fpregmap[] =
+ {
+ { 32, RISCV_FIRST_FP_REGNUM, 0 },
+ { 1, RISCV_CSR_FCSR_REGNUM, 0 },
+ { 0 }
+};
+
+/* Register set definitions. */
+
+const struct regset riscv_sol2_gregset =
+ {
+ riscv_sol2_gregmap, regcache_supply_regset, regcache_collect_regset
+ };
+
+const struct regset riscv_sol2_fpregset =
+ {
+ riscv_sol2_fpregmap,
+ regcache_supply_regset, regcache_collect_regset
+ };
+
+/* Implement the "regset_from_core_section" gdbarch method. */
+
+static void
+riscv_sol2_iterate_over_regset_sections (struct gdbarch *gdbarch,
+ iterate_over_regset_sections_cb *cb,
+ void *cb_data,
+ const struct regcache *regcache)
+{
+ cb (".reg", (32 * riscv_isa_xlen (gdbarch)), (32 * riscv_isa_xlen (gdbarch)),
+ &riscv_sol2_gregset, NULL, cb_data);
+ cb (".reg2", (32 * riscv_isa_flen (gdbarch)) + 8,
+ (32 * riscv_isa_flen (gdbarch)) + 8,
+ &riscv_sol2_fpregset, NULL, cb_data);
+}
+
+
+struct riscv_frame_cache
+{
+ /* Base address. */
+ CORE_ADDR base;
+ CORE_ADDR pc;
+
+ /* Do we have a frame? */
+ int frameless_p;
+
+ /* The offset from the base register to the CFA. */
+ int frame_offset;
+
+ /* Mask of `local' and `in' registers saved in the register save area. */
+ unsigned short int saved_regs_mask;
+
+ /* Mask of `out' registers copied or renamed to their `in' sibling. */
+ unsigned char copied_regs_mask;
+
+ /* Do we have a Structure, Union or Quad-Precision return value? */
+ int struct_return_p;
+
+ /* Table of saved registers. */
+ struct trad_frame_saved_reg *saved_regs;
+};
+
+static CORE_ADDR
+riscv_sol2_mcontext_addr (struct frame_info *this_frame)
+{
+ CORE_ADDR ucontext_addr;
+
+ ucontext_addr = get_frame_register_unsigned (this_frame, RISCV_A0_REGNUM + 2);
+ return ucontext_addr + 8 * 7;
+}
+
+static struct riscv_frame_cache *
+riscv_alloc_frame_cache (void)
+{
+ struct riscv_frame_cache *cache;
+
+ cache = FRAME_OBSTACK_ZALLOC (struct riscv_frame_cache);
+
+ /* Base address. */
+ cache->base = 0;
+ cache->pc = 0;
+
+ /* Frameless until proven otherwise. */
+ cache->frameless_p = 1;
+ cache->frame_offset = 0;
+ cache->saved_regs_mask = 0;
+ cache->copied_regs_mask = 0;
+ cache->struct_return_p = 0;
+
+ return cache;
+}
+
+static struct riscv_frame_cache *
+riscv_sol2_sigtramp_frame_cache (struct frame_info *this_frame,
+ void **this_cache)
+{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct riscv_frame_cache *cache;
+ CORE_ADDR mcontext_addr;
+ int regnum;
+ int xlen = riscv_isa_xlen (gdbarch);
+ int flen = riscv_isa_flen (gdbarch);
+
+ if (*this_cache)
+ return (riscv_frame_cache*)*this_cache;
+
+ cache = riscv_alloc_frame_cache ();
+ *this_cache = cache;
+
+ cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+ mcontext_addr = riscv_sol2_mcontext_addr (this_frame);
+
+ for (regnum = 0; regnum < 31; regnum++)
+ cache->saved_regs[regnum].set_addr(mcontext_addr + regnum * xlen);
+ cache->saved_regs[RISCV_PC_REGNUM].set_addr(mcontext_addr + 31 * xlen); // pc
+
+ for (regnum = 0; regnum < 32; regnum++)
+ cache->saved_regs[regnum + RISCV_FIRST_FP_REGNUM].set_addr(mcontext_addr + 32 * xlen + regnum * flen);
+
+ cache->saved_regs[RISCV_CSR_FCSR_REGNUM].set_addr(mcontext_addr + 32 * xlen + 32 * flen);
+
+ return cache;
+}
+
+static void
+riscv_sol2_sigtramp_frame_this_id (struct frame_info *this_frame,
+ void **this_cache,
+ struct frame_id *this_id)
+{
+ struct riscv_frame_cache *cache =
+ riscv_sol2_sigtramp_frame_cache (this_frame, this_cache);
+
+ (*this_id) = frame_id_build (cache->base, cache->pc);
+}
+
+static struct value *
+riscv_sol2_sigtramp_frame_prev_register (struct frame_info *this_frame,
+ void **this_cache,
+ int regnum)
+{
+ struct riscv_frame_cache *cache =
+ riscv_sol2_sigtramp_frame_cache (this_frame, this_cache);
+
+ struct value *ret = trad_frame_get_prev_register (this_frame, cache->saved_regs, regnum);
+ return ret;
+}
+
+static int
+riscv_sol2_sigtramp_frame_sniffer (const struct frame_unwind *self,
+ struct frame_info *this_frame,
+ void **this_cache)
+{
+ CORE_ADDR pc = get_frame_pc (this_frame);
+ const char *name;
+
+ find_pc_partial_function (pc, &name, NULL, NULL);
+ return (name && (strcmp ("sigacthandler", name) == 0 || strcmp (name, "ucbsigvechandler") == 0));
+}
+
+
+static const struct frame_unwind riscv_sol2_sigtramp_frame_unwind =
+{
+ "riscv solaris sigtramp",
+ SIGTRAMP_FRAME,
+ default_frame_unwind_stop_reason,
+ riscv_sol2_sigtramp_frame_this_id,
+ riscv_sol2_sigtramp_frame_prev_register,
+ NULL,
+ riscv_sol2_sigtramp_frame_sniffer
+};
+
+
+/* Implement the 'init_osabi' method of struct gdb_osabi_handler. */
+
+static void
+riscv_sol2_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ frame_unwind_append_unwinder (gdbarch, &riscv_sol2_sigtramp_frame_unwind);
+ sol2_init_abi (info, gdbarch);
+
+ /* Solaris has SVR4-style shared libraries... */
+ set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ (riscv_isa_xlen (gdbarch) == 4
+ ? svr4_ilp32_fetch_link_map_offsets
+ : svr4_lp64_fetch_link_map_offsets));
+
+ set_gdbarch_software_single_step (gdbarch, riscv_software_single_step);
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes. */
+extern initialize_file_ftype _initialize_riscv_sol2_tdep;
+
+void
+_initialize_riscv_sol2_tdep (void)
+{
+ gdbarch_register_osabi (bfd_arch_riscv, 0, GDB_OSABI_SOLARIS,
+ riscv_sol2_init_abi);
+}
diff --git a/gdb/riscv-sol2-tdep.h b/gdb/riscv-sol2-tdep.h
new file mode 100644
index 0000000000..6900818df2
--- /dev/null
+++ b/gdb/riscv-sol2-tdep.h
@@ -0,0 +1,25 @@
+/* GNU/Linux on AArch64 target support, prototypes.
+
+ Copyright (C) 2012-2014 Free Software Foundation, Inc.
+ Contributed by ARM Ltd.
+
+ This file is part of GDB.
+
+ 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, see . */
+
+#include "regset.h"
+
+extern const struct regset riscv_sol2_gregset;
+extern const struct regset riscv_sol2_fpregset;
+
diff --git a/gnulib/import/string.in.h b/gnulib/import/string.in.h
index 33160b2525..6eafdf0b36 100644
--- a/gnulib/import/string.in.h
+++ b/gnulib/import/string.in.h
@@ -127,6 +127,8 @@ _GL_EXTERN_C void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
+# elif defined __cplusplus && defined __sun__ && defined __GNUC__
+_GL_EXTERN_C void std::free (void *);
# else
_GL_EXTERN_C void free (void *);
# endif
@@ -138,6 +140,8 @@ _GL_EXTERN_C void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
+# elif defined __cplusplus && defined __sun__ && defined __GNUC__
+_GL_EXTERN_C void std::free (void *);
# else
_GL_EXTERN_C void free (void *);
# endif
diff --git a/gnulib/import/wchar.in.h b/gnulib/import/wchar.in.h
index 0d5c0b7abe..b19d917da1 100644
--- a/gnulib/import/wchar.in.h
+++ b/gnulib/import/wchar.in.h
@@ -190,6 +190,8 @@ _GL_EXTERN_C void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
+# elif defined __cplusplus && defined __sun__ && defined __GNUC__
+_GL_EXTERN_C void std::free (void *);
# else
_GL_EXTERN_C void free (void *);
# endif
@@ -201,6 +203,8 @@ _GL_EXTERN_C void __cdecl free (void *);
# else
# if defined __cplusplus && (__GLIBC__ + (__GLIBC_MINOR__ >= 14) > 2)
_GL_EXTERN_C void free (void *) throw ();
+# elif defined __cplusplus && defined __sun__ && defined __GNUC__
+_GL_EXTERN_C void std::free (void *);
# else
_GL_EXTERN_C void free (void *);
# endif
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 09a3ec0168..c6e7465f90 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -554,6 +554,10 @@ struct bfd_link_info
/* TRUE if commonpagesize is set on command-line. */
unsigned int commonpagesize_is_set : 1;
+ unsigned int rtldinfo: 1;
+
+ char *rtldinfo_name;
+
/* Char that may appear as the first char of a symbol, but should be
skipped (like symbol_leading_char) when looking up symbols in
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */
@@ -1038,6 +1042,7 @@ struct bfd_elf_version_deps
struct bfd_elf_version_deps *next;
/* The version which this version depends upon. */
struct bfd_elf_version_tree *version_needed;
+ const char *version_needed_name;
};
/* A node in the version tree. */
diff --git a/include/elf/common.h b/include/elf/common.h
index e4bc53e35b..8b57a949c6 100644
--- a/include/elf/common.h
+++ b/include/elf/common.h
@@ -1176,6 +1176,8 @@
#define DT_VERNEED 0x6ffffffe
#define DT_VERNEEDNUM 0x6fffffff
+#define DT_SUNW_RTLDINF 0x6000000e
+
/* This tag is a GNU extension to the Solaris version scheme. */
#define DT_VERSYM 0x6ffffff0
diff --git a/ld/configure.tgt b/ld/configure.tgt
index 2bae9099b6..3d97c056e1 100644
--- a/ld/configure.tgt
+++ b/ld/configure.tgt
@@ -80,6 +80,8 @@ fi
# Please try to keep this table more or less in alphabetic order - it
# makes it much easier to lookup a specific archictecture.
case "${targ}" in
+aarch64-*-solaris2*) targ_emul=aarch64elf
+ targ_extra_emuls="aarch64elf32 aarch64elf32b aarch64elfb armelf armelfb" ;;
aarch64_be-*-elf) targ_emul=aarch64elfb
targ_extra_emuls="aarch64elf aarch64elf32 aarch64elf32b armelfb armelf"
;;
@@ -811,6 +813,7 @@ riscv64be*-*-linux*) targ_emul=elf64briscv
targ_extra_emuls="elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32 elf64lriscv elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32"
targ_extra_libpath=$targ_extra_emuls
;;
+riscv64-*-solaris2*) targ_emul=elf64lriscv ;;
riscv64*-*-linux*) targ_emul=elf64lriscv
targ_extra_emuls="elf64lriscv_lp64f elf64lriscv_lp64 elf32lriscv elf32lriscv_ilp32f elf32lriscv_ilp32 elf64briscv elf64briscv_lp64f elf64briscv_lp64 elf32briscv elf32briscv_ilp32f elf32briscv_ilp32"
targ_extra_libpath=$targ_extra_emuls
diff --git a/ld/emulparams/aarch64elf.sh b/ld/emulparams/aarch64elf.sh
index 8f68e517b4..92e5d1acda 100644
--- a/ld/emulparams/aarch64elf.sh
+++ b/ld/emulparams/aarch64elf.sh
@@ -12,16 +12,19 @@ NO_REL_RELOCS=yes
TEMPLATE_NAME=elf
EXTRA_EM_FILE=aarch64elf
+# SEPARATE_CODE=yes
+
GENERATE_SHLIB_SCRIPT=yes
GENERATE_PIE_SCRIPT=yes
MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
ENTRY=_start
EMBEDDED=yes
SEPARATE_GOTPLT=24
IREL_IN_PLT=
-TEXT_START_ADDR=0x00400000
+TEXT_START_ADDR="0x00400000 + SIZEOF_HEADERS"
DATA_START_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__data_start = .${CREATE_SHLIB+)};"
@@ -34,6 +37,7 @@ OTHER_END_SYMBOLS="${CREATE_SHLIB+PROVIDE (}__end__ = .${CREATE_SHLIB+)};"
OTHER_SECTIONS='.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }'
ATTRS_SECTIONS='.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }'
+PLT=".plt ${RELOCATING-0} : ALIGN(16) { *(.plt)${IREL_IN_PLT+ *(.iplt)} }"
# This sets the stack to the top of the simulator memory (2^19 bytes).
STACK_ADDR=0x80000
diff --git a/ld/emultempl/aarch64elf.em b/ld/emultempl/aarch64elf.em
index 1968f12cf2..097f967019 100644
--- a/ld/emultempl/aarch64elf.em
+++ b/ld/emultempl/aarch64elf.em
@@ -60,9 +60,92 @@ fragment <dynobj == NULL)
+ hash_table->dynobj = abfd;
+
+ if (hash_table->dynstr == NULL)
+ {
+ hash_table->dynstr = _bfd_elf_strtab_init ();
+ if (hash_table->dynstr == NULL)
+ return false;
+ }
+ return true;
+}
+
+static void
+elf_add_dt_needed_tag (bfd *abfd,
+ struct bfd_link_info *info,
+ const char *soname,
+ bool do_it)
+{
+ struct elf_link_hash_table *hash_table;
+ bfd_size_type oldsize;
+ bfd_size_type strindex;
+
+ if (!_bfd_elf_link_create_dynstrtab (abfd, info))
+ return;
+
+ hash_table = elf_hash_table (info);
+ oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+ strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, false);
+ if (strindex == (bfd_size_type) -1)
+ return;
+
+ if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+ {
+ asection *sdyn;
+ const struct elf_backend_data *bed;
+ bfd_byte *extdyn;
+
+ bed = get_elf_backend_data (hash_table->dynobj);
+ sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+ if (sdyn != NULL)
+ for (extdyn = sdyn->contents;
+ extdyn < sdyn->contents + sdyn->size;
+ extdyn += bed->s->sizeof_dyn)
+ {
+ Elf_Internal_Dyn dyn;
+
+ bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+ if (dyn.d_tag == DT_NEEDED
+ && dyn.d_un.d_val == strindex)
+ {
+ _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+ return;
+ }
+ }
+ }
+
+ if (do_it)
+ {
+ if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
+ return;
+
+ if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+ return;
+ }
+ else
+ /* We were just checking for existence of the tag. */
+ _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+
+ return;
+}
static void
aarch64_elf_before_allocation (void)
{
+ struct bfd_link_needed_list *entry = force_needed_top;
+ while (entry) {
+ elf_add_dt_needed_tag (link_info.output_bfd, &link_info, entry->name, true);
+ entry = entry->next;
+ }
/* We should be able to set the size of the interworking stub section. We
can't do it until later if we have dynamic sections, though. */
if (! elf_hash_table (&link_info)->dynamic_sections_created)
@@ -363,6 +446,7 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_FIX_ERRATUM_835769 313
#define OPTION_FIX_ERRATUM_843419 314
#define OPTION_NO_APPLY_DYNAMIC_RELOCS 315
+#define OPTION_FORCE_ADD_NEEDED 316
'
PARSE_AND_LIST_SHORTOPTS=p
@@ -376,6 +460,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "fix-cortex-a53-835769", no_argument, NULL, OPTION_FIX_ERRATUM_835769},
{ "fix-cortex-a53-843419", optional_argument, NULL, OPTION_FIX_ERRATUM_843419},
{ "no-apply-dynamic-relocs", no_argument, NULL, OPTION_NO_APPLY_DYNAMIC_RELOCS},
+ { "force-add-needed", required_argument, NULL, OPTION_FORCE_ADD_NEEDED },
'
PARSE_AND_LIST_OPTIONS='
@@ -408,6 +493,7 @@ PARSE_AND_LIST_OPTIONS='
fprintf (file, _(" --no-apply-dynamic-relocs Do not apply link-time values for dynamic relocations\n"));
fprintf (file, _(" -z force-bti Turn on Branch Target Identification mechanism and generate PLTs with BTI. Generate warnings for missing BTI on inputs\n"));
fprintf (file, _(" -z pac-plt Protect PLTs with Pointer Authentication.\n"));
+ fprintf (file, _(" --force-add-needed= Force add needed\n"));
'
PARSE_AND_LIST_ARGS_CASE_Z_AARCH64='
@@ -462,6 +548,25 @@ PARSE_AND_LIST_ARGS_CASES='
no_apply_dynamic_relocs = 1;
break;
+ case OPTION_FORCE_ADD_NEEDED:
+ {
+ struct bfd_link_needed_list *new_entry = xmalloc (sizeof (struct bfd_link_needed_list));
+ if (new_entry) {
+ new_entry->name = strdup(optarg);
+ new_entry->by = 0;
+ new_entry->next = 0;
+ struct bfd_link_needed_list *entry = force_needed_top;;
+ if (entry) {
+ while (entry->next)
+ entry = entry->next;
+ entry->next = new_entry;
+ } else {
+ force_needed_top = new_entry;
+ }
+ }
+ }
+ break;
+
case OPTION_STUBGROUP_SIZE:
{
const char *end;
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index c52484f35d..16712d434c 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -737,6 +737,11 @@ fragment <dynobj == NULL)
+ hash_table->dynobj = abfd;
+
+ if (hash_table->dynstr == NULL)
+ {
+ hash_table->dynstr = _bfd_elf_strtab_init ();
+ if (hash_table->dynstr == NULL)
+ return false;
+ }
+ return true;
+}
+
+static void
+elf_add_dt_needed_tag (bfd *abfd,
+ struct bfd_link_info *info,
+ const char *soname,
+ bool do_it)
+{
+ struct elf_link_hash_table *hash_table;
+ bfd_size_type oldsize;
+ bfd_size_type strindex;
+
+ if (!_bfd_elf_link_create_dynstrtab (abfd, info))
+ return;
+
+ hash_table = elf_hash_table (info);
+ oldsize = _bfd_elf_strtab_size (hash_table->dynstr);
+ strindex = _bfd_elf_strtab_add (hash_table->dynstr, soname, false);
+ if (strindex == (bfd_size_type) -1)
+ return;
+
+ if (oldsize == _bfd_elf_strtab_size (hash_table->dynstr))
+ {
+ asection *sdyn;
+ const struct elf_backend_data *bed;
+ bfd_byte *extdyn;
+
+ bed = get_elf_backend_data (hash_table->dynobj);
+ sdyn = bfd_get_section_by_name (hash_table->dynobj, ".dynamic");
+ if (sdyn != NULL)
+ for (extdyn = sdyn->contents;
+ extdyn < sdyn->contents + sdyn->size;
+ extdyn += bed->s->sizeof_dyn)
+ {
+ Elf_Internal_Dyn dyn;
+
+ bed->s->swap_dyn_in (hash_table->dynobj, extdyn, &dyn);
+ if (dyn.d_tag == DT_NEEDED
+ && dyn.d_un.d_val == strindex)
+ {
+ _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+ return;
+ }
+ }
+ }
+
+ if (do_it)
+ {
+ if (!_bfd_elf_link_create_dynamic_sections (hash_table->dynobj, info))
+ return;
+
+ if (!_bfd_elf_add_dynamic_entry (info, DT_NEEDED, strindex))
+ return;
+ }
+ else
+ /* We were just checking for existence of the tag. */
+ _bfd_elf_strtab_delref (hash_table->dynstr, strindex);
+
+ return;
+}
+
static void
riscv_elf_before_allocation (void)
{
+ struct bfd_link_needed_list *entry = force_needed_top;
+ while (entry) {
+ elf_add_dt_needed_tag (link_info.output_bfd, &link_info, entry->name, true);
+ entry = entry->next;
+ }
gld${EMULATION_NAME}_before_allocation ();
if (link_info.discard == discard_sec_merge)
@@ -100,6 +184,43 @@ riscv_create_output_section_statements (void)
EOF
+# Define some shell vars to insert bits of code into the standard elf
+# parse_args and list_options functions.
+#
+PARSE_AND_LIST_PROLOGUE='
+#define OPTION_FORCE_ADD_NEEDED 300
+'
+
+PARSE_AND_LIST_LONGOPTS='
+ { "force-add-needed", required_argument, NULL, OPTION_FORCE_ADD_NEEDED },
+'
+
+PARSE_AND_LIST_OPTIONS='
+ fprintf (file, _("\
+ --force-add-needed= Force add needed\n"));
+'
+
+PARSE_AND_LIST_ARGS_CASES='
+ case OPTION_FORCE_ADD_NEEDED:
+ {
+ struct bfd_link_needed_list *new_entry = xmalloc (sizeof (struct bfd_link_needed_list));
+ if (new_entry) {
+ new_entry->name = strdup(optarg);
+ new_entry->by = 0;
+ new_entry->next = 0;
+ struct bfd_link_needed_list *entry = force_needed_top;;
+ if (entry) {
+ while (entry->next)
+ entry = entry->next;
+ entry->next = new_entry;
+ } else {
+ force_needed_top = new_entry;
+ }
+ }
+ }
+ break;
+'
+
LDEMUL_BEFORE_ALLOCATION=riscv_elf_before_allocation
LDEMUL_AFTER_ALLOCATION=gld${EMULATION_NAME}_after_allocation
LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=riscv_create_output_section_statements
diff --git a/ld/ldgram.y b/ld/ldgram.y
index 3a904e3948..ea11373de4 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -154,7 +154,7 @@ static int error_index;
%token LOG2CEIL FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
%token VERS_TAG VERS_IDENTIFIER
-%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
+%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT SYMBOL_VERSION SYMBOL_SCOPE
%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL INPUT_SECTION_FLAGS ALIGN_WITH_INPUT
%token EXCLUDE_FILE
%token CONSTANT
@@ -1381,6 +1381,18 @@ vers_node:
{
lang_register_vers_node (NULL, $2, NULL);
}
+ | SYMBOL_SCOPE '{' vers_tag '}' ';'
+ {
+ lang_register_vers_node (NULL, $3, NULL);
+ }
+ | SYMBOL_VERSION VERS_TAG '{' vers_tag '}' ';'
+ {
+ lang_register_vers_node ($2, $4, NULL);
+ }
+ | SYMBOL_VERSION VERS_TAG '{' vers_tag '}' verdep ';'
+ {
+ lang_register_vers_node ($2, $4, $6);
+ }
| VERS_TAG '{' vers_tag '}' ';'
{
lang_register_vers_node ($1, $3, NULL);
diff --git a/ld/ldlang.c b/ld/ldlang.c
index f12c09633a..4e4261f9f3 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -9465,9 +9465,41 @@ lang_register_vers_node (const char *name,
else
version->vernum = 0;
+ int vernum = version->vernum;
+ for (t = link_info.version_info; t != NULL; t = t->next) {
+ struct bfd_elf_version_deps *ver_deps = t->deps;
+ while (ver_deps) {
+ if (ver_deps->version_needed_name &&
+ strcmp (ver_deps->version_needed_name, name) == 0) {
+ ver_deps->version_needed = version;
+ free(ver_deps->version_needed_name);
+ ver_deps->version_needed_name = NULL;
+ if (t->vernum < vernum)
+ vernum = t->vernum;
+ }
+ ver_deps = ver_deps->next;
+ }
+ }
+
for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next)
- ;
+ ;
*pp = version;
+
+ while (vernum != version->vernum) {
+ for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next) {
+ if ((*pp)->next == version) {
+ t = *pp;
+ int v = t->vernum;
+ t->vernum = version->vernum;
+ version->vernum = v;
+
+ t->next = version->next;
+ version->next = t;
+ *pp = version;
+ break;
+ }
+ }
+ }
}
/* This is called when we see a version dependency. */
@@ -9480,6 +9512,7 @@ lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret);
ret->next = list;
+ ret->version_needed_name = NULL;
for (t = link_info.version_info; t != NULL; t = t->next)
{
@@ -9490,9 +9523,10 @@ lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name)
}
}
- einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
+// einfo (_("%X%P: unable to find version dependency `%s'\n"), name);
ret->version_needed = NULL;
+ ret->version_needed_name = strdup(name);
return ret;
}
diff --git a/ld/ldlex.l b/ld/ldlex.l
index c38b46b933..a18410f55f 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -444,6 +444,8 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*