From abd215c9bd3752a9bb475ee30affb5a26d65b1a7 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 22 Jan 2016 10:00:34 +1030 Subject: [PATCH] x32 write_linux_prstatus x32 uses an elf_gregset64_t in the prstatus struct, which aligns the struct to eight bytes. This means four bytes of padding at the end of the struct. * amd64-linux-tdep.c: Include elf-bfd.h. (amd64_x32_write_linux_prstatus): New function. (amd64_x32_linux_init_abi): Use it. * linux-tdep.c (linux_collect_regset_section_cb): Allocate an extra four bytes for regset buffer. * gdbarch.sh (elfcore_write_linux_prstatus): Remove const from info. * gdbarch.c: Regenerate. * gdbarch.h: Regenerate. --- gdb/amd64-linux-tdep.c | 22 +++++++++++++++++++++- gdb/gdbarch.c | 2 +- gdb/gdbarch.h | 4 ++-- gdb/gdbarch.sh | 2 +- gdb/linux-tdep.c | 3 ++- 5 files changed, 27 insertions(+), 6 deletions(-) diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index c545cd02a56..cdde600b657 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -28,6 +28,7 @@ #include "gdbtypes.h" #include "reggroups.h" #include "regset.h" +#include "elf-bfd.h" /* for elfcore_write_* */ #include "parser-defs.h" #include "user-regs.h" #include "amd64-linux-tdep.h" @@ -1646,6 +1647,25 @@ amd64_linux_iterate_over_regset_sections (struct gdbarch *gdbarch, &amd64_linux_xstateregset, "XSAVE extended state", cb_data); } +/* The standard elfcore_write_linux_prstatus32 isn't quite correct + for x32, which needs an extra 4 bytes of padding at the end of + the note. */ + +static char * +amd64_x32_write_linux_prstatus (bfd *obfd, + char *buf, + int *bufsize, + struct elf_internal_linux_prstatus *prstatus) +{ + /* Tack pr_fpvalid to end of pr_regs. */ + bfd_put_32 (obfd, prstatus->pr_fpvalid, + (char *) prstatus->pr_reg + prstatus->pr_reg_size); + prstatus->pr_reg_size += 4; + /* pr_fpvalid becomes padding. */ + prstatus->pr_fpvalid = 0; + return elfcore_write_linux_prstatus32 (obfd, buf, bufsize, prstatus); +} + /* The instruction sequences used in x86_64 machines for a disabled is-enabled probe. */ @@ -2075,7 +2095,7 @@ amd64_x32_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* x32's layout is not compatible with the 32-bit layout. */ set_gdbarch_elfcore_write_linux_prstatus - (gdbarch, gdb_deprecated_elfcore_write_linux_prstatus); + (gdbarch, amd64_x32_write_linux_prstatus); amd64_x32_init_abi (info, gdbarch); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index fe0acbc8640..58f8ce51dec 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -3481,7 +3481,7 @@ gdbarch_elfcore_write_linux_prstatus_p (struct gdbarch *gdbarch) } char * -gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info) +gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, struct elf_internal_linux_prstatus *info) { gdb_assert (gdbarch != NULL); gdb_assert (gdbarch->elfcore_write_linux_prstatus != NULL); diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 5e00b32c9f4..7e6e8ca8d0a 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -833,8 +833,8 @@ extern void set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, g extern int gdbarch_elfcore_write_linux_prstatus_p (struct gdbarch *gdbarch); -typedef char * (gdbarch_elfcore_write_linux_prstatus_ftype) (bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info); -extern char * gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info); +typedef char * (gdbarch_elfcore_write_linux_prstatus_ftype) (bfd *obfd, char *note_data, int *note_size, struct elf_internal_linux_prstatus *info); +extern char * gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, struct elf_internal_linux_prstatus *info); extern void set_gdbarch_elfcore_write_linux_prstatus (struct gdbarch *gdbarch, gdbarch_elfcore_write_linux_prstatus_ftype *elfcore_write_linux_prstatus); /* Find core file memory regions */ diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 71e3e8c580f..c10ac6a1e0a 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -703,7 +703,7 @@ M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size # as we call the Linux generic routines in bfd to write notes by # default. F:char *:elfcore_write_linux_prpsinfo:bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info:obfd, note_data, note_size, info -F:char *:elfcore_write_linux_prstatus:bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prstatus *info:obfd, note_data, note_size, info +F:char *:elfcore_write_linux_prstatus:bfd *obfd, char *note_data, int *note_size, struct elf_internal_linux_prstatus *info:obfd, note_data, note_size, info # Find core file memory regions M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index d432c471438..a49a0f012ec 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -1574,7 +1574,8 @@ linux_collect_regset_section_cb (const char *sect_name, int size, gdb_assert (regset && regset->collect_regset); - buf = (char *) xmalloc (size); + /* Extra 4 bytes for use by amd64_x32_write_linux_prstatus. */ + buf = (char *) xmalloc (size + 4); regset->collect_regset (regset, data->regcache, -1, buf, size); /* PRSTATUS still needs to be treated specially. */ -- 2.47.2