Compare commits

...

2 Commits

Author SHA1 Message Date
Yao Qi
5e5a2a68c7 ILP32: GDB
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):
2017-10-23 14:52:28 +01:00
Yao Qi
2c5e2ba3ce ILP32: BFD
bfd:

2017-03-06  Andrew Pinski  <apinski@cavium.com>
            Steve Ellcey  <sellcey@cavium.com>

	* cpu-aarch64.c (compatible):
	Don't reject different ILP32/LP64 ABI's here.
	* elfnn-aarch64.c (elfNN_aarch64_merge_private_bfd_data):
	Add an error message on why endianess is rejected.
	Reject different ILP32/LP64 ABI settings.
	* elfxx-aarch64.c (_bfd_aarch64_elf_grok_prstatus): Handle
	size and offset of ILP32 executables.
	(_bfd_aarch64_elf_grok_psinfo):  Ditto.
2017-10-23 14:50:18 +01:00
8 changed files with 180 additions and 30 deletions

View File

@@ -25,7 +25,8 @@
/* This routine is provided two arch_infos and works out which Aarch64
machine which would be compatible with both and returns a pointer
to its info structure. */
to its info structure. ABI (ilp32 vs. lp64) and endianness compatibility
are checked in elfNN_aarch64_merge_private_bfd_data. */
static const bfd_arch_info_type *
compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
@@ -38,10 +39,6 @@ compatible (const bfd_arch_info_type * a, const bfd_arch_info_type * b)
if (a->mach == b->mach)
return a;
/* Don't allow mixing ilp32 with lp64. */
if ((a->mach & bfd_mach_aarch64_ilp32) != (b->mach & bfd_mach_aarch64_ilp32))
return NULL;
/* Otherwise if either a or b is the 'default' machine
then it can be polymorphed into the other. */
if (a->the_default)

View File

@@ -6591,11 +6591,26 @@ elfNN_aarch64_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info)
/* Check if we have the same endianess. */
if (!_bfd_generic_verify_endian_match (ibfd, info))
return FALSE;
{
(*_bfd_error_handler)
(_("%B: endianness incompatible with that of the selected emulation"),
ibfd);
return FALSE;
}
if (!is_aarch64_elf (ibfd) || !is_aarch64_elf (obfd))
return TRUE;
/* Don't allow mixing ilp32 with lp64. */
if ((bfd_get_arch_info (ibfd)->mach & bfd_mach_aarch64_ilp32)
!= (bfd_get_arch_info (obfd)->mach & bfd_mach_aarch64_ilp32))
{
(*_bfd_error_handler)
(_("%B: ABI is incompatible with that of the selected emulation: \"%s\" != \"%s\""),
ibfd, bfd_get_target (ibfd), bfd_get_target (obfd));
return FALSE;
}
/* The input BFD must have had its flags initialised. */
/* The following seems bogus to me -- The flags are initialized in
the assembler but I don't think an elf_flags_init field is

View File

@@ -548,7 +548,18 @@ _bfd_aarch64_elf_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
return TRUE;
}
/* Support for core dump NOTE sections. */
/* Support for core dump NOTE sections.
note->descsz should be the size of elf_prstatus, defined in
usr/include/linux/elfcore.h. The size is 352 in ILP32 mode
and 392 in LP64 mode. elf_tdata (abfd)->core->signal is set from the
pr_cursig field of elf_prstatus which is at an offset of 12 in the
elf_prstatus structure in both ILP32 and LP64 modes.
elf_tdata (abfd)->core->lwpid is set from the pr_pid field of the
elf_prstatus structure. It has an offset of 24 in ILP32 mode and
32 in LP64 mode due to two long fields in the structure that are in
front of the pr_pid field. */
bfd_boolean
_bfd_aarch64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
@@ -561,14 +572,27 @@ _bfd_aarch64_elf_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
default:
return FALSE;
case 392: /* sizeof(struct elf_prstatus) on Linux/arm64. */
case 352: /* sizeof(struct elf_prstatus) on Linux/aarch64 ilp32. */
/* pr_cursig */
elf_tdata (abfd)->core->signal
= bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
elf_tdata (abfd)->core->lwpid
= bfd_get_32 (abfd, note->descdata + 32);
elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 24);
/* pr_reg */
offset = 72;
size = 272;
break;
case 392: /* sizeof(struct elf_prstatus) on Linux/aarch64. */
/* pr_cursig */
elf_tdata (abfd)->core->signal
= bfd_get_16 (abfd, note->descdata + 12);
/* pr_pid */
elf_tdata (abfd)->core->lwpid = bfd_get_32 (abfd, note->descdata + 32);
/* pr_reg */
offset = 112;
@@ -590,12 +614,21 @@ _bfd_aarch64_elf_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
default:
return FALSE;
case 136: /* This is sizeof(struct elf_prpsinfo) on Linux/aarch64. */
case 124: /* sizeof(struct elf_prpsinfo) on Linux/aarch64 ilp32. */
elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 12);
elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 28, 16);
elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 44, 80);
break;
case 136: /* sizeof(struct elf_prpsinfo) on Linux/aarch64. */
elf_tdata (abfd)->core->pid = bfd_get_32 (abfd, note->descdata + 24);
elf_tdata (abfd)->core->program
= _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
elf_tdata (abfd)->core->command
= _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
break;
}
/* Note that for some reason, a spurious space is tacked

View File

@@ -49,6 +49,10 @@
#define TRAP_HWBKPT 0x0004
#endif
/* 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,
@@ -166,7 +170,7 @@ fetch_gregs_from_thread (struct regcache *regcache)
tid = ptid_get_lwp (regcache_get_ptid (regcache));
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);
@@ -175,7 +179,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
{
@@ -203,7 +207,7 @@ store_gregs_to_thread (const struct regcache *regcache)
tid = ptid_get_lwp (regcache_get_ptid (regcache));
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);
@@ -212,7 +216,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
{
@@ -248,7 +252,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;
@@ -295,7 +299,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;
@@ -328,7 +332,7 @@ store_fpregs_to_thread (const struct regcache *regcache)
(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)
@@ -460,10 +464,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);
}
@@ -517,7 +520,7 @@ aarch64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
/* 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,

View File

@@ -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[] =
@@ -1016,8 +1072,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,
@@ -1027,7 +1087,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;

View File

@@ -2086,6 +2086,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 *
@@ -2848,6 +2864,10 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
const struct tdesc_feature *feature;
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 descriptor. */
if (!tdesc_has_registers (tdesc))
@@ -2905,6 +2925,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;
}
@@ -2923,6 +2946,7 @@ aarch64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep->lowest_pc = 0x20;
tdep->jb_pc = -1; /* Longjump support not enabled by default. */
tdep->jb_elt_size = 8;
tdep->ilp32 = ilp32;
set_gdbarch_push_dummy_call (gdbarch, aarch64_push_dummy_call);
set_gdbarch_frame_align (gdbarch, aarch64_frame_align);
@@ -2965,9 +2989,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);
@@ -3010,6 +3034,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,

View File

@@ -97,6 +97,9 @@ struct gdbarch_tdep
/* syscall record. */
int (*aarch64_syscall_record) (struct regcache *regcache, unsigned long svc_number);
/* If this is ILP32 or LP64. */
bool ilp32;
};
extern struct target_desc *tdesc_aarch64;

View File

@@ -492,7 +492,12 @@ aarch64_linux_read_description (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)
return tdesc_aarch64;
else
return tdesc_arm_with_neon;