summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2017-10-23 14:52:28 +0100
committerChristoph Muellner <christoph.muellner@theobroma-systems.com>2018-12-05 16:09:34 +0100
commit12fe6323be3783c0dca0d2c30c41425b0f26ed3d (patch)
tree469376ddd67a5f14578b403754efcc6656ae128f
parent27c11e872356657ba6beb9af2d4bf5747f95d93c (diff)
Rebased 5e5a2a68c772d59c41d4e536949ce4ba3dc9b3ea from linaro's gdb-aarch64-ilp32 branch on GDB 8.1-release. gdb: 2017-03-06 Andrew Pinski <apinski@cavium.com> Steve Ellcey <sellcey@cavium.com> Yao Qi <yao.qi@linaro.org> * aarch64-linux-nat.c (IS_ARM32): New macro. (fetch_gregs_from_thread): Use IS_ARM32 macro. (store_gregs_to_thread): Ditto. (fetch_fpregs_from_thread): Ditto. (store_fpregs_to_thread): Ditto. (ps_get_thread_area): Ditto. (aarch64_linux_siginfo_fixup): Ditto. * aarch64-linux-tdep.c (aarch64_linux_init_abi): Set link map offsets to 32 or 64 bits. * aarch64-tdep.c (aarch64_ilp32_register_type): New function. (aarch64_gdbarch_init): Setup ILP32 support. Make sure the gdbarches have compatible ilp32 flags. Set long and ptr sizes correctly for ilp32. * aarch64-tdep.h (gdbarch_tdep) <ilp32>: New field. gdb/gdbserver: 2017-03-06 Andrew Pinski <apinski@cavium.com> Steve Ellcey <sellcey@cavium.com> * linux-aarch64-low.c (aarch64_linux_read_description):
-rw-r--r--gdb/aarch64-linux-nat.c25
-rw-r--r--gdb/aarch64-linux-tdep.c73
-rw-r--r--gdb/aarch64-tdep.c35
-rw-r--r--gdb/aarch64-tdep.h3
-rw-r--r--gdb/gdbserver/linux-aarch64-low.c7
5 files changed, 124 insertions, 19 deletions
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index c9fd062cd9..16f10921fa 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -98,6 +98,10 @@ public:
static aarch64_linux_nat_target the_aarch64_linux_nat_target;
+/* Check if we are on arm (as opposed to aarch64). */
+#define IS_ARM32(gdbarch) \
+ (gdbarch_bfd_arch_info(gdbarch)->arch == bfd_arch_arm)
+
/* Per-process data. We don't bind this to a per-inferior registry
because of targets like x86 GNU/Linux that need to keep track of
processes that aren't bound to any inferior (e.g., fork children,
@@ -215,7 +219,7 @@ fetch_gregs_from_thread (struct regcache *regcache)
tid = ptid_get_lwp (regcache->ptid ());
iovec.iov_base = &regs;
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
iovec.iov_len = 18 * 4;
else
iovec.iov_len = sizeof (regs);
@@ -224,7 +228,7 @@ fetch_gregs_from_thread (struct regcache *regcache)
if (ret < 0)
perror_with_name (_("Unable to fetch general registers."));
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
aarch32_gp_regcache_supply (regcache, (uint32_t *) regs, 1);
else
{
@@ -252,7 +256,7 @@ store_gregs_to_thread (const struct regcache *regcache)
tid = ptid_get_lwp (regcache->ptid ());
iovec.iov_base = &regs;
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
iovec.iov_len = 18 * 4;
else
iovec.iov_len = sizeof (regs);
@@ -261,7 +265,7 @@ store_gregs_to_thread (const struct regcache *regcache)
if (ret < 0)
perror_with_name (_("Unable to fetch general registers."));
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
aarch32_gp_regcache_collect (regcache, (uint32_t *) regs, 1);
else
{
@@ -296,7 +300,7 @@ fetch_fpregs_from_thread (struct regcache *regcache)
iovec.iov_base = &regs;
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
{
iovec.iov_len = VFP_REGS_SIZE;
@@ -342,7 +346,7 @@ store_fpregs_to_thread (const struct regcache *regcache)
iovec.iov_base = &regs;
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
{
iovec.iov_len = VFP_REGS_SIZE;
@@ -373,7 +377,7 @@ store_fpregs_to_thread (const struct regcache *regcache)
regcache->raw_collect (AARCH64_FPCR_REGNUM, (char *) &regs.fpcr);
}
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
{
ret = ptrace (PTRACE_SETREGSET, tid, NT_ARM_VFP, &iovec);
if (ret < 0)
@@ -554,10 +558,9 @@ ps_err_e
ps_get_thread_area (struct ps_prochandle *ph,
lwpid_t lwpid, int idx, void **base)
{
- int is_64bit_p
- = (gdbarch_bfd_arch_info (target_gdbarch ())->bits_per_word == 64);
+ int is_aarch64_p = !IS_ARM32 (target_gdbarch ());
- return aarch64_ps_get_thread_area (ph, lwpid, idx, base, is_64bit_p);
+ return aarch64_ps_get_thread_area (ph, lwpid, idx, base, is_aarch64_p);
}
@@ -623,7 +626,7 @@ aarch64_linux_nat_target::low_siginfo_fixup (siginfo_t *native, gdb_byte *inf,
/* Is the inferior 32-bit? If so, then do fixup the siginfo
object. */
- if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+ if (IS_ARM32 (gdbarch))
{
if (direction == 0)
aarch64_compat_siginfo_from_siginfo ((struct compat_siginfo *) inf,
diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c
index 93b6d416a3..ff22c10f19 100644
--- a/gdb/aarch64-linux-tdep.c
+++ b/gdb/aarch64-linux-tdep.c
@@ -131,13 +131,13 @@
ucontext.uc_mcontext. */
/* These magic numbers need to reflect the layout of the kernel
- defined struct rt_sigframe and ucontext. */
+ defined struct rt_sigframe and ucontext in LP64 mode. */
#define AARCH64_SIGCONTEXT_REG_SIZE 8
#define AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET 128
#define AARCH64_UCONTEXT_SIGCONTEXT_OFFSET 176
#define AARCH64_SIGCONTEXT_XO_OFFSET 8
-/* Implement the "init" method of struct tramp_frame. */
+/* Implement the "init" method of struct tramp_frame for LP64. */
static void
aarch64_linux_sigframe_init (const struct tramp_frame *self,
@@ -186,6 +186,62 @@ static const struct tramp_frame aarch64_linux_rt_sigframe =
aarch64_linux_sigframe_init
};
+/* These magic numbers need to reflect the layout of the kernel
+ defined struct rt_sigframe and ucontext in LP64 mode. */
+#define AARCH64_ILP32_SIGCONTEXT_REG_SIZE 8
+#define AARCH64_ILP32_RT_SIGFRAME_UCONTEXT_OFFSET 128
+#define AARCH64_ILP32_UCONTEXT_SIGCONTEXT_OFFSET 160
+#define AARCH64_ILP32_SIGCONTEXT_XO_OFFSET 8
+
+/* Implement the "init" method of struct tramp_frame for ILP32. */
+
+static void
+aarch64_ilp32_linux_sigframe_init (const struct tramp_frame *self,
+ struct frame_info *this_frame,
+ struct trad_frame_cache *this_cache,
+ CORE_ADDR func)
+{
+ CORE_ADDR sp = get_frame_register_unsigned (this_frame, AARCH64_SP_REGNUM);
+ CORE_ADDR sigcontext_addr =
+ sp
+ + AARCH64_RT_SIGFRAME_UCONTEXT_OFFSET
+ + AARCH64_ILP32_UCONTEXT_SIGCONTEXT_OFFSET;
+ int i;
+
+ for (i = 0; i < 31; i++)
+ {
+ trad_frame_set_reg_addr (this_cache,
+ AARCH64_X0_REGNUM + i,
+ sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
+ + i * AARCH64_SIGCONTEXT_REG_SIZE);
+ }
+ trad_frame_set_reg_addr (this_cache, AARCH64_SP_REGNUM,
+ sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
+ + 31 * AARCH64_SIGCONTEXT_REG_SIZE);
+ trad_frame_set_reg_addr (this_cache, AARCH64_PC_REGNUM,
+ sigcontext_addr + AARCH64_SIGCONTEXT_XO_OFFSET
+ + 32 * AARCH64_SIGCONTEXT_REG_SIZE);
+
+ trad_frame_set_id (this_cache, frame_id_build (sp, func));
+}
+
+static const struct tramp_frame aarch64_ilp32_linux_rt_sigframe =
+{
+ SIGTRAMP_FRAME,
+ 4,
+ {
+ /* movz x8, 0x8b (S=1,o=10,h=0,i=0x8b,r=8)
+ Soo1 0010 1hhi iiii iiii iiii iiir rrrr */
+ {0xd2801168, -1},
+
+ /* svc 0x0 (o=0, l=1)
+ 1101 0100 oooi iiii iiii iiii iii0 00ll */
+ {0xd4000001, -1},
+ {TRAMP_SENTINEL_INSN, -1}
+ },
+ aarch64_ilp32_linux_sigframe_init
+};
+
/* Register maps. */
static const struct regcache_map_entry aarch64_linux_gregmap[] =
@@ -1026,8 +1082,12 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
linux_init_abi (info, gdbarch);
- set_solib_svr4_fetch_link_map_offsets (gdbarch,
- svr4_lp64_fetch_link_map_offsets);
+ if (tdep->ilp32)
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ svr4_ilp32_fetch_link_map_offsets);
+ else
+ set_solib_svr4_fetch_link_map_offsets (gdbarch,
+ svr4_lp64_fetch_link_map_offsets);
/* Enable TLS support. */
set_gdbarch_fetch_tls_load_module_address (gdbarch,
@@ -1037,7 +1097,10 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
- tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
+ if (tdep->ilp32)
+ tramp_frame_prepend_unwinder (gdbarch, &aarch64_ilp32_linux_rt_sigframe);
+ else
+ tramp_frame_prepend_unwinder (gdbarch, &aarch64_linux_rt_sigframe);
/* Enable longjmp. */
tdep->jb_pc = 11;
diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 5120fffe77..c55b68fc66 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -2145,6 +2145,22 @@ aarch64_gen_return_address (struct gdbarch *gdbarch,
}
+/* Implement the "register_type" gdbarch method.
+ Adjust the register type of $PC and $SP on ILP32. */
+
+static struct type *
+aarch64_ilp32_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ gdb_assert (tdep->ilp32);
+
+ if (regnum == AARCH64_SP_REGNUM || regnum == AARCH64_PC_REGNUM)
+ return builtin_type (gdbarch)->builtin_uint64;
+ else
+ return tdesc_register_type (gdbarch, regnum);
+}
+
/* Return the pseudo register name corresponding to register regnum. */
static const char *
@@ -2950,6 +2966,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
const struct tdesc_feature *feature_sve;
int num_regs = 0;
int num_pseudo_regs = 0;
+ bool ilp32 = false;
+
+ if (info.bfd_arch_info->mach == bfd_mach_aarch64_ilp32)
+ ilp32 = true;
/* Ensure we always have a target description. */
if (!tdesc_has_registers (tdesc))
@@ -3027,6 +3047,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
best_arch != NULL;
best_arch = gdbarch_list_lookup_by_info (best_arch->next, &info))
{
+ /* ILP32 and LP64 are incompatible. */
+ if (gdbarch_tdep (arches->gdbarch)->ilp32 != ilp32)
+ continue;
/* Found a match. */
break;
}
@@ -3046,6 +3069,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->jb_pc = -1; /* Longjump support not enabled by default. */
tdep->jb_elt_size = 8;
tdep->vq = aarch64_get_tdesc_vq (tdesc);
+ tdep->ilp32 = ilp32;
set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
@@ -3088,9 +3112,9 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_float_bit (gdbarch, 32);
set_gdbarch_double_bit (gdbarch, 64);
set_gdbarch_long_double_bit (gdbarch, 128);
- set_gdbarch_long_bit (gdbarch, 64);
+ set_gdbarch_long_bit (gdbarch, ilp32 ? 32 : 64);
set_gdbarch_long_long_bit (gdbarch, 64);
- set_gdbarch_ptr_bit (gdbarch, 64);
+ set_gdbarch_ptr_bit (gdbarch, ilp32 ? 32 : 64);
set_gdbarch_char_signed (gdbarch, 0);
set_gdbarch_wchar_signed (gdbarch, 0);
set_gdbarch_float_format (gdbarch, floatformats_ieee_single);
@@ -3133,6 +3157,13 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdesc_use_registers (gdbarch, tdesc, tdesc_data);
+ if (ilp32)
+ {
+ /* Override tdesc_register_type to adjust the types of $PC and
+ $SP in ILP32. */
+ set_gdbarch_register_type (gdbarch, aarch64_ilp32_register_type);
+ }
+
/* Add standard register aliases. */
for (i = 0; i < ARRAY_SIZE (aarch64_register_aliases); i++)
user_reg_add (gdbarch, aarch64_register_aliases[i].name,
diff --git a/gdb/aarch64-tdep.h b/gdb/aarch64-tdep.h
index 7e5031f0fd..e18e8f9a9d 100644
--- a/gdb/aarch64-tdep.h
+++ b/gdb/aarch64-tdep.h
@@ -87,6 +87,9 @@ struct gdbarch_tdep
{
return vq != 0;
}
+
+ /* If this is ILP32 or LP64. */
+ bool ilp32;
};
const target_desc *aarch64_read_description (uint64_t vq);
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 1d34e319df..86baacf143 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -514,7 +514,12 @@ aarch64_arch_setup (void)
is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
- if (is_elf64)
+ /* There are problems with ptrace when gdbserver is 32 bits and the
+ program being debugged is 64 bits. */
+ if (sizeof (void *) == 4 && is_elf64)
+ error (_("Can't debug 64-bit process with 32-bit GDBserver"));
+
+ if (machine == EM_AARCH64)
{
uint64_t vq = aarch64_sve_get_vq (tid);
current_process ()->tdesc = aarch64_linux_read_description (vq);