diff options
author | Yao Qi <yao.qi@linaro.org> | 2017-10-23 14:52:28 +0100 |
---|---|---|
committer | Christoph Muellner <christoph.muellner@theobroma-systems.com> | 2019-05-03 21:29:09 +0200 |
commit | 31fbde179f8cf2e8925f7c7ad7e1e49e943ad5b0 (patch) | |
tree | fcadee5188ce54dbea1bdf05810b7249660beb77 | |
parent | bb95ceb92704f0a57d2ea017498c91637dc9c05d (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.c | 25 | ||||
-rw-r--r-- | gdb/aarch64-linux-tdep.c | 73 | ||||
-rw-r--r-- | gdb/aarch64-tdep.c | 35 | ||||
-rw-r--r-- | gdb/aarch64-tdep.h | 3 | ||||
-rw-r--r-- | gdb/gdbserver/linux-aarch64-low.c | 7 |
5 files changed, 124 insertions, 19 deletions
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 6f91e9568e..441ae3917d 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 = regcache->ptid ().lwp (); iovec.iov_base = ®s; - 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 = regcache->ptid ().lwp (); iovec.iov_base = ®s; - 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 = ®s; - 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 = ®s; - 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 *) ®s.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 62cfc76c82..4d61ff3f3b 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -130,7 +130,7 @@ 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 @@ -184,7 +184,7 @@ read_aarch64_ctx (CORE_ADDR ctx_addr, enum bfd_endian byte_order, return magic; } -/* 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, @@ -379,6 +379,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[] = @@ -1421,8 +1477,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, @@ -1432,7 +1492,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 b051563937..a298e8257a 100644 --- a/gdb/aarch64-tdep.c +++ b/gdb/aarch64-tdep.c @@ -2157,6 +2157,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 * @@ -2962,6 +2978,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)) @@ -3039,6 +3059,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; } @@ -3058,6 +3081,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); @@ -3100,9 +3124,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); @@ -3145,6 +3169,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 704eacb50c..2a930d6cb2 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 0b2946ea22..56fbaf5344 100644 --- a/gdb/gdbserver/linux-aarch64-low.c +++ b/gdb/gdbserver/linux-aarch64-low.c @@ -498,7 +498,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); |