mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
2 Commits
1ae9fa5c60
...
users/lina
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5e5a2a68c7 | ||
|
|
2c5e2ba3ce |
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ®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);
|
||||
@@ -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 = ®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);
|
||||
@@ -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 = ®s;
|
||||
|
||||
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 = ®s;
|
||||
|
||||
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 *) ®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)
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user