Re: [RFC] Add support for PPC Altivec registers in gcore

Carlos Eduardo Seo
2008-02-08T21:42:47Z

[-- Attachment #1: Type: text/plain, Size: 898 bytes --]

Ulrich Weigand wrote:
> Yes, exactly. You'll have to update the list in gdbarch.sh,
> and run the script to regenerate gdbarch.c and gdbarch.h.
>

Ok, here's my first shot at this new approach for writing core files. I
had to add a new BFD function (binutils patch is attached as well - I'll
submit this to the binutils mailing list later) and I didn't include the
fill_register fallbacks in the new implementation.

I believe a similar loop could also be used in -tdep.c files to read the
core files as well, right?

Only wrote the code for ppc, but this could be easily expanded to other
archs, adding modifications similar to those I did in ppc-linux-tdep.c.

I think this first code is very raw, but I believe we can improve it and
use this approach for all archs in the future.

Opinions / suggestions?

Regards,

--
Carlos Eduardo Seo
Software Engineer
IBM Linux Technology Center

[-- Attachment #2: gdbarch-core-regset.diff --]
[-- Type: text/x-patch, Size: 9845 bytes --]

2008-02-08 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>

* gdbarch.c: Refreshed.
* gdbarch.h: Refreshed.
* gdbarch.sh: Added new gdbarch struct core_regset_sections.
* regset.h (core_regset_section): Declare.
* ppc-linux-tdep.c: (ppc_regset_sections): Declare.
(ppc_linux_init_abi): Initialized new gdbarch struct
core_regset_sections.
* linux-nat.c (linux_nat_do_thread_registers): Added
support to the new gdbarch struct core_regset_sections.

Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c
+++ src/gdb/gdbarch.c
@@ -222,6 +222,7 @@ struct gdbarch
gdbarch_register_reggroup_p_ftype *register_reggroup_p;
gdbarch_fetch_pointer_argument_ftype *fetch_pointer_argument;
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
+ struct core_regset_section * core_regset_sections;
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
int vtable_function_descriptors;
int vbit_in_delta;
@@ -344,6 +345,7 @@ struct gdbarch startup_gdbarch =
default_register_reggroup_p, /* register_reggroup_p */
0, /* fetch_pointer_argument */
0, /* regset_from_core_section */
+ 0, /* core_regset_sections */
0, /* core_xfer_shared_libraries */
0, /* vtable_function_descriptors */
0, /* vbit_in_delta */
@@ -694,6 +696,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: core_read_description = <0x%lx>\n",
(long) gdbarch->core_read_description);
fprintf_unfiltered (file,
+ "gdbarch_dump: core_regset_sections = %s\n",
+ (char *) gdbarch->core_regset_sections);
+ fprintf_unfiltered (file,
"gdbarch_dump: gdbarch_core_xfer_shared_libraries_p() = %d\n",
gdbarch_core_xfer_shared_libraries_p (gdbarch));
fprintf_unfiltered (file,
@@ -2810,6 +2815,22 @@ set_gdbarch_regset_from_core_section (st
gdbarch->regset_from_core_section = regset_from_core_section;
}

+struct core_regset_section *
+gdbarch_core_regset_sections (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_core_regset_sections called\n");
+ return gdbarch->core_regset_sections;
+}
+
+void
+set_gdbarch_core_regset_sections (struct gdbarch *gdbarch,
+ struct core_regset_section * core_regset_sections)
+{
+ gdbarch->core_regset_sections = core_regset_sections;
+}
+
int
gdbarch_core_xfer_shared_libraries_p (struct gdbarch *gdbarch)
{
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h
+++ src/gdb/gdbarch.h
@@ -50,6 +50,7 @@ struct target_ops;
struct obstack;
struct bp_target_info;
struct target_desc;
+struct core_regset_section;

extern struct gdbarch *current_gdbarch;

@@ -626,6 +627,11 @@ typedef const struct regset * (gdbarch_r
extern const struct regset * gdbarch_regset_from_core_section (struct gdbarch *gdbarch, const char *sect_name, size_t sect_size);
extern void set_gdbarch_regset_from_core_section (struct gdbarch *gdbarch, gdbarch_regset_from_core_section_ftype *regset_from_core_section);

+/* Supported register notes in core files */
+
+extern struct core_regset_section * gdbarch_core_regset_sections (struct gdbarch *gdbarch);
+extern void set_gdbarch_core_regset_sections (struct gdbarch *gdbarch, struct core_regset_section * core_regset_sections);
+
/* Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
core file into buffer READBUF with length LEN. */

Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh
+++ src/gdb/gdbarch.sh
@@ -594,6 +594,9 @@ F:CORE_ADDR:fetch_pointer_argument:struc
# name SECT_NAME and size SECT_SIZE.
M:const struct regset *:regset_from_core_section:const char *sect_name, size_t sect_size:sect_name, sect_size

+# Supported register notes in core files
+v:struct core_regset_section *:core_regset_sections:const char *name, int len::::::(char *) gdbarch->core_regset_sections
+
# Read offset OFFSET of TARGET_OBJECT_LIBRARIES formatted shared libraries list from
# core file into buffer READBUF with length LEN.
M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
@@ -729,6 +732,7 @@ struct target_ops;
struct obstack;
struct bp_target_info;
struct target_desc;
+struct core_regset_section;

extern struct gdbarch *current_gdbarch;
EOF
Index: src/gdb/regset.h
===================================================================
--- src.orig/gdb/regset.h
+++ src/gdb/regset.h
@@ -20,6 +20,12 @@
#ifndef REGSET_H
#define REGSET_H 1

+struct core_regset_section
+{
+ const char *sect_name;
+ int size;
+};
+
struct gdbarch;
struct regcache;

Index: src/gdb/ppc-linux-tdep.c
===================================================================
--- src.orig/gdb/ppc-linux-tdep.c
+++ src/gdb/ppc-linux-tdep.c
@@ -38,6 +38,13 @@
#include "frame-unwind.h"
#include "tramp-frame.h"

+static struct core_regset_section ppc_regset_sections[] =
+{
+ {".reg2", 264},
+ {".reg-ppc-vmx", 544},
+ {NULL, 0}
+};
+
static CORE_ADDR
ppc_linux_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
{
@@ -945,6 +952,10 @@ ppc_linux_init_abi (struct gdbarch_info
tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame);
tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame);
}
+
+ /* Register sections. */
+ set_gdbarch_core_regset_sections (gdbarch, ppc_regset_sections);
+
set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section);

/* Enable TLS support. */
Index: src/gdb/linux-nat.c
===================================================================
--- src.orig/gdb/linux-nat.c
+++ src/gdb/linux-nat.c
@@ -2631,6 +2631,9 @@ linux_nat_do_thread_registers (bfd *obfd
const struct regset *regset;
int core_regset_p;
struct cleanup *old_chain;
+ struct core_regset_section *sect_list;
+ char *gdb_regset;
+ int i = 0;

old_chain = save_inferior_ptid ();
inferior_ptid = ptid;
@@ -2638,6 +2641,8 @@ linux_nat_do_thread_registers (bfd *obfd
do_cleanups (old_chain);

core_regset_p = gdbarch_regset_from_core_section_p (gdbarch);
+ sect_list = gdbarch_core_regset_sections (gdbarch);
+
if (core_regset_p
&& (regset = gdbarch_regset_from_core_section (gdbarch, ".reg",
sizeof (gregs))) != NULL
@@ -2653,35 +2658,69 @@ linux_nat_do_thread_registers (bfd *obfd
lwp,
stop_signal, &gregs);

- if (core_regset_p
- && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
- sizeof (fpregs))) != NULL
- && regset->collect_regset != NULL)
- regset->collect_regset (regset, regcache, -1,
- &fpregs, sizeof (fpregs));
+ /* The loop below uses the new struct core_regset_section, which stores
+ the supported section names and sizes for the core file. Note that
+ note PRSTATUS needs to be treated specially. But the other notes are
+ structurally the same, so they can benefit from the new struct. */
+
+ if (core_regset_p && sect_list != NULL)
+ while ((sect_list + i)->sect_name != NULL)
+ {
+ if ((regset = gdbarch_regset_from_core_section (gdbarch,
+ (sect_list + i)->sect_name,
+ (*(sect_list + i)).size))
+ != NULL && regset->collect_regset != NULL)
+ {
+ gdb_regset = xmalloc ((*(sect_list + i)).size);
+ regset->collect_regset (regset, regcache, -1,
+ gdb_regset, (*(sect_list + i)).size);
+ note_data = (char *) elfcore_write_register_note (obfd,
+ note_data,
+ note_size,
+ (sect_list + i)->sect_name,
+ gdb_regset,
+ (*(sect_list + i)).size);
+ xfree (gdb_regset);
+ }
+ i++;
+ }
+
+ /* For architectures that does not have the struct core_regset_section implemented,
+ we use the old method. When all the architectures have the new support, the code
+ below should be deprecated. */
+
else
- fill_fpregset (regcache, &fpregs, -1);
+ {
+ if (core_regset_p
+ && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg2",
+ sizeof (fpregs))) != NULL
+ && regset->collect_regset != NULL)
+ regset->collect_regset (regset, regcache, -1,
+ &fpregs, sizeof (fpregs));
+ else
+ fill_fpregset (regcache, &fpregs, -1);

- note_data = (char *) elfcore_write_prfpreg (obfd,
- note_data,
- note_size,
- &fpregs, sizeof (fpregs));
+ note_data = (char *) elfcore_write_prfpreg (obfd,
+ note_data,
+ note_size,
+ &fpregs, sizeof (fpregs));

#ifdef FILL_FPXREGSET
- if (core_regset_p
- && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp",
- sizeof (fpxregs))) != NULL
- && regset->collect_regset != NULL)
- regset->collect_regset (regset, regcache, -1,
- &fpxregs, sizeof (fpxregs));
- else
- fill_fpxregset (regcache, &fpxregs, -1);
+ if (core_regset_p
+ && (regset = gdbarch_regset_from_core_section (gdbarch, ".reg-xfp",
+ sizeof (fpxregs))) != NULL
+ && regset->collect_regset != NULL)
+ regset->collect_regset (regset, regcache, -1,
+ &fpxregs, sizeof (fpxregs));
+ else
+ fill_fpxregset (regcache, &fpxregs, -1);

- note_data = (char *) elfcore_write_prxfpreg (obfd,
- note_data,
- note_size,
- &fpxregs, sizeof (fpxregs));
+ note_data = (char *) elfcore_write_prxfpreg (obfd,
+ note_data,
+ note_size,
+ &fpxregs, sizeof (fpxregs));
#endif
+ }
return note_data;
}

[-- Attachment #3: write-register-note.patch --]
[-- Type: text/x-patch, Size: 1566 bytes --]

2008-02-03 Carlos Eduardo Seo <cseo@linux.vnet.ibm.com>

* elf.c (elfcore_write_register_note): New function.
* elf-bfd.h (elfcore_write_register_note): New prototype.

Index: src/bfd/elf.c
===================================================================
--- src.orig/bfd/elf.c
+++ src/bfd/elf.c
@@ -8438,6 +8438,23 @@ elfcore_write_ppc_vmx (bfd *abfd,
note_name, NT_PPC_VMX, ppc_vmx, size);
}

+char *
+elfcore_write_register_note (bfd *abfd,
+ char *buf,
+ int *bufsiz,
+ const char *section,
+ const void *data,
+ int size)
+{
+ if (strcmp (section, ".reg2") == 0)
+ return elfcore_write_prfpreg (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-xfp") == 0)
+ return elfcore_write_prxfpreg (abfd, buf, bufsiz, data, size);
+ if (strcmp (section, ".reg-ppc-vmx") == 0)
+ return elfcore_write_ppc_vmx (abfd, buf, bufsiz, data, size);
+ return NULL;
+}
+
static bfd_boolean
elf_parse_notes (bfd *abfd, char *buf, size_t size, file_ptr offset)
{
Index: src/bfd/elf-bfd.h
===================================================================
--- src.orig/bfd/elf-bfd.h
+++ src/bfd/elf-bfd.h
@@ -2109,6 +2109,8 @@ extern char *elfcore_write_ppc_vmx
(bfd *, char *, int *, const void *, int);
extern char *elfcore_write_lwpstatus
(bfd *, char *, int *, long, int, const void *);
+extern char *elfcore_write_register_note
+ (bfd *, char *, int *, const char *, const void *, int);

extern bfd *_bfd_elf32_bfd_from_remote_memory
(bfd *templ, bfd_vma ehdr_vma, bfd_vma *loadbasep,