This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[commit] core file lwp/pid encoding on solaris
- From: Pedro Alves <pedro at codesourcery dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 16 Feb 2009 03:19:07 +0000
- Subject: [commit] core file lwp/pid encoding on solaris
Something I noticed while doing some across-all-targets changes.
Solaris encodes the pid of the cored inferior in regset section names,
like so:
[LWPID << 16 | PID]
See:
pedro@opensolaris:~/orlando/gdb/baseline/build-solaris/gdb$ objdump -h ./core
./core: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 note0 0000087c 00000000 00000000 000002d4 2**0
CONTENTS, READONLY
1 .reg/145693 0000004c 00000000 00000000 00000564 2**2
^^^^^^^^^^
CONTENTS
2 .reg 0000004c 00000000 00000000 00000564 2**2
CONTENTS
3 .reg2/145693 0000017c 00000000 00000000 000005c4 2**2
^^^^^^^^^^^
CONTENTS
4 .reg2 0000017c 00000000 00000000 000005c4 2**2
CONTENTS
5 .reg/80157 0000004c 00000000 00000000 000008b8 2**2
^^^^^^^^^^
CONTENTS
6 .reg2/80157 0000017c 00000000 00000000 00000918 2**2
^^^^^^^^^^
(...)
The patch below teaches gdbarch.sh, the solaris tdep files, and corelow.c
about systems that do this. I've chosen a gdbarch setting instead of
tweaking sol-thread.c:solaris_pid_to_str, because, first, I'm going
to clean up sol-thread.c, after which, there will be no
"solaris-core" target anymore. Second, this patch is just a UI tweak
for now, but is actually necessary to be able to debug threaded
core files. Third, this way works for cross-core debugging as well.
I had started out with gdbarch callbacks to do ptid_t <-> regset section
name conversion, but in the end, I considered that a boolean setting
would be better and simpler for now. We can do something else if
we ever find a system that does more complicated ".reg/XXX" section
name decoding.
>From the user's perpective, with the core from the objdump listing above,
"info threads" output changes from this:
(gdb) info threads
2 LWP 80157 thread_function (arg=0x0) at ../../../src/gdb/testsuite/gdb.threads/schedlock.c:59
* 1 LWP 145693 0xfee910c0 in _thr_setup () from /lib/libc.so.1
(gdb)
To this:
(gdb) info threads
2 LWP 1 thread_function (arg=0x0) at ../../../src/gdb/testsuite/gdb.threads/schedlock.c:59
* 1 LWP 2 0xfee910c0 in _thr_setup () from /lib/libc.so.1
(gdb) info inferiors
* 1 14621
That is, it looks just like it was when the inferior was a live
process, not a core dump.
FYI, dbx also doesn't expose that encoded lwpid to the user:
(dbx) threads
o> t@1 a l@1 ?() signal SIGSEGV in main()
(dbx) lwps
o>l@1 signal SIGSEGV in main()
(that's thread 1 and lwp 1 in dbx's lingo)
(note, that was a core from a different app)
"gcore" on solaris, through procfs.c:procfs_do_thread_registers
is already being compatible with what the kernel produces, by
also generating this encoding.
I needed to move the post_create_inferior call to after
adding the threads, as deep in post_create_inferior there
may be are register reads that would fail otherwise, due to reading
off of an inferior ptid.
Also no regressions on x86_64-linux. I've also smoke tested debugging
threaded and non-threaded cores on i386-openbsd4.3, to confirm that
core files without ".reg/XXX" sections, only ".reg", still load
fine into gdb.
Checked in.
--
Pedro Alves
2009-02-16 Pedro Alves <pedro@codesourcery.com>
* corelow.c (core_close): Don't hardcode the core's pid.
(core_open): Find core threads before calling
post_create_inferior.
(add_to_thread_list, get_core_register_section): Take into account
systems where the regset section names encode the pid of the
inferior.
* gdbarch.sh (core_reg_section_encodes_pid): New gdbarch setting.
* gdbarch.h, gdbarch.c: Regenerate.
* amd64-sol2-tdep.c (amd64_sol2_init_abi): Set it.
* i386-sol2-tdep.c (i386_sol2_init_abi): Set it.
* sparc-sol2-tdep.c (sparc32_sol2_init_abi): Set it.
* sparc64-sol2-tdep.c (sparc64_sol2_init_abi): Set it.
---
gdb/amd64-sol2-tdep.c | 4 ++++
gdb/corelow.c | 32 +++++++++++++++++++++++++-------
gdb/gdbarch.c | 23 +++++++++++++++++++++++
gdb/gdbarch.h | 11 ++++++++++-
gdb/gdbarch.sh | 7 +++++++
gdb/i386-sol2-tdep.c | 4 ++++
gdb/sparc-sol2-tdep.c | 4 ++++
gdb/sparc64-sol2-tdep.c | 4 ++++
8 files changed, 81 insertions(+), 8 deletions(-)
Index: src/gdb/corelow.c
===================================================================
--- src.orig/gdb/corelow.c 2009-02-16 00:23:30.000000000 +0000
+++ src/gdb/corelow.c 2009-02-16 03:02:45.000000000 +0000
@@ -199,8 +199,9 @@ core_close (int quitting)
if (core_bfd)
{
+ int pid = ptid_get_pid (inferior_ptid);
inferior_ptid = null_ptid; /* Avoid confusion from thread stuff */
- delete_inferior_silent (CORELOW_PID);
+ delete_inferior_silent (pid);
/* Clear out solib state while the bfd is still open. See
comments in clear_solib in solib.c. */
@@ -244,7 +245,15 @@ add_to_thread_list (bfd *abfd, asection
thread_id = atoi (bfd_section_name (abfd, asect) + 5);
- ptid = ptid_build (ptid_get_pid (inferior_ptid), thread_id, 0);
+ if (core_gdbarch
+ && gdbarch_core_reg_section_encodes_pid (core_gdbarch))
+ {
+ uint32_t merged_pid = thread_id;
+ ptid = ptid_build (merged_pid & 0xffff,
+ merged_pid >> 16, 0);
+ }
+ else
+ ptid = ptid_build (ptid_get_pid (inferior_ptid), thread_id, 0);
if (ptid_get_lwp (inferior_ptid) == 0)
/* The main thread has already been added before getting here, and
@@ -374,16 +383,14 @@ core_open (char *filename, int from_tty)
from ST to MT. */
add_thread_silent (inferior_ptid);
- /* This is done first, before anything has a chance to query the
- inferior for information such as symbols. */
- post_create_inferior (&core_ops, from_tty);
-
/* Build up thread list from BFD sections, and possibly set the
current thread to the .reg/NN section matching the .reg
section. */
bfd_map_over_sections (core_bfd, add_to_thread_list,
bfd_get_section_by_name (core_bfd, ".reg"));
+ post_create_inferior (&core_ops, from_tty);
+
/* Now go through the target stack looking for threads since there
may be a thread_stratum target loaded on top of target core by
now. The layer above should claim threads found in the BFD
@@ -453,7 +460,18 @@ get_core_register_section (struct regcac
char *contents;
xfree (section_name);
- if (ptid_get_lwp (inferior_ptid))
+
+ if (core_gdbarch
+ && gdbarch_core_reg_section_encodes_pid (core_gdbarch))
+ {
+ uint32_t merged_pid;
+
+ merged_pid = ptid_get_lwp (inferior_ptid);
+ merged_pid = merged_pid << 16 | ptid_get_pid (inferior_ptid);
+
+ section_name = xstrprintf ("%s/%s", name, plongest (merged_pid));
+ }
+ else if (ptid_get_lwp (inferior_ptid))
section_name = xstrprintf ("%s/%ld", name, ptid_get_lwp (inferior_ptid));
else
section_name = xstrdup (name);
Index: src/gdb/gdbarch.sh
===================================================================
--- src.orig/gdb/gdbarch.sh 2009-02-16 00:23:30.000000000 +0000
+++ src/gdb/gdbarch.sh 2009-02-16 03:03:40.000000000 +0000
@@ -600,6 +600,13 @@ 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
+# When creating core dumps, some systems encode the PID in addition
+# to the LWP id in core file register section names. In those cases, the
+# "XXX" in ".reg/XXX" is encoded as [LWPID << 16 | PID]. This setting
+# is set to true for such architectures; false if "XXX" represents an LWP
+# or thread id with no special encoding.
+v:int:core_reg_section_encodes_pid:::0:0::0
+
# Supported register notes in a core file.
v:struct core_regset_section *:core_regset_sections:const char *name, int len::::::host_address_to_string (gdbarch->core_regset_sections)
Index: src/gdb/amd64-sol2-tdep.c
===================================================================
--- src.orig/gdb/amd64-sol2-tdep.c 2009-02-16 00:24:03.000000000 +0000
+++ src/gdb/amd64-sol2-tdep.c 2009-02-16 01:19:25.000000000 +0000
@@ -113,6 +113,10 @@ amd64_sol2_init_abi (struct gdbarch_info
set_gdbarch_skip_solib_resolver (gdbarch, sol2_skip_solib_resolver);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_lp64_fetch_link_map_offsets);
+
+ /* Solaris encodes the pid of the inferior in regset section
+ names. */
+ set_gdbarch_core_reg_section_encodes_pid (gdbarch, 1);
}
Index: src/gdb/gdbarch.c
===================================================================
--- src.orig/gdb/gdbarch.c 2009-02-16 00:24:35.000000000 +0000
+++ src/gdb/gdbarch.c 2009-02-16 03:04:11.000000000 +0000
@@ -223,6 +223,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;
+ int core_reg_section_encodes_pid;
struct core_regset_section * core_regset_sections;
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
int vtable_function_descriptors;
@@ -356,6 +357,7 @@ struct gdbarch startup_gdbarch =
default_register_reggroup_p, /* register_reggroup_p */
0, /* fetch_pointer_argument */
0, /* regset_from_core_section */
+ 0, /* core_reg_section_encodes_pid */
0, /* core_regset_sections */
0, /* core_xfer_shared_libraries */
0, /* vtable_function_descriptors */
@@ -609,6 +611,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of register_reggroup_p, invalid_p == 0 */
/* Skip verify of fetch_pointer_argument, has predicate */
/* Skip verify of regset_from_core_section, has predicate */
+ /* Skip verify of core_reg_section_encodes_pid, invalid_p == 0 */
/* Skip verify of core_xfer_shared_libraries, has predicate */
/* Skip verify of vtable_function_descriptors, invalid_p == 0 */
/* Skip verify of vbit_in_delta, invalid_p == 0 */
@@ -736,6 +739,9 @@ gdbarch_dump (struct gdbarch *gdbarch, s
"gdbarch_dump: core_read_description = <%s>\n",
host_address_to_string (gdbarch->core_read_description));
fprintf_unfiltered (file,
+ "gdbarch_dump: core_reg_section_encodes_pid = %s\n",
+ plongest (gdbarch->core_reg_section_encodes_pid));
+ fprintf_unfiltered (file,
"gdbarch_dump: core_regset_sections = %s\n",
host_address_to_string (gdbarch->core_regset_sections));
fprintf_unfiltered (file,
@@ -2899,6 +2905,23 @@ set_gdbarch_regset_from_core_section (st
gdbarch->regset_from_core_section = regset_from_core_section;
}
+int
+gdbarch_core_reg_section_encodes_pid (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ /* Skip verify of core_reg_section_encodes_pid, invalid_p == 0 */
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_core_reg_section_encodes_pid called\n");
+ return gdbarch->core_reg_section_encodes_pid;
+}
+
+void
+set_gdbarch_core_reg_section_encodes_pid (struct gdbarch *gdbarch,
+ int core_reg_section_encodes_pid)
+{
+ gdbarch->core_reg_section_encodes_pid = core_reg_section_encodes_pid;
+}
+
struct core_regset_section *
gdbarch_core_regset_sections (struct gdbarch *gdbarch)
{
Index: src/gdb/gdbarch.h
===================================================================
--- src.orig/gdb/gdbarch.h 2009-02-16 00:24:31.000000000 +0000
+++ src/gdb/gdbarch.h 2009-02-16 03:04:01.000000000 +0000
@@ -638,6 +638,15 @@ 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);
+/* When creating core dumps, some systems encode the PID in addition
+ to the LWP id in core file register section names. In those cases, the
+ "XXX" in ".reg/XXX" is encoded as [LWPID << 16 | PID]. This setting
+ is set to true for such architectures; false if "XXX" represents an LWP
+ or thread id with no special encoding. */
+
+extern int gdbarch_core_reg_section_encodes_pid (struct gdbarch *gdbarch);
+extern void set_gdbarch_core_reg_section_encodes_pid (struct gdbarch *gdbarch, int core_reg_section_encodes_pid);
+
/* Supported register notes in a core file. */
extern struct core_regset_section * gdbarch_core_regset_sections (struct gdbarch *gdbarch);
@@ -804,7 +813,7 @@ extern int gdbarch_target_signal_to_host
extern void set_gdbarch_target_signal_to_host (struct gdbarch *gdbarch, gdbarch_target_signal_to_host_ftype *target_signal_to_host);
/* Extra signal info inspection.
-
+
Return a type suitable to inspect extra signal information. */
extern int gdbarch_get_siginfo_type_p (struct gdbarch *gdbarch);
Index: src/gdb/i386-sol2-tdep.c
===================================================================
--- src.orig/gdb/i386-sol2-tdep.c 2009-02-16 00:24:24.000000000 +0000
+++ src/gdb/i386-sol2-tdep.c 2009-02-16 01:17:48.000000000 +0000
@@ -135,6 +135,10 @@ i386_sol2_init_abi (struct gdbarch_info
set_gdbarch_skip_solib_resolver (gdbarch, sol2_skip_solib_resolver);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+ /* Solaris encodes the pid of the inferior in regset section
+ names. */
+ set_gdbarch_core_reg_section_encodes_pid (gdbarch, 1);
}
Index: src/gdb/sparc-sol2-tdep.c
===================================================================
--- src.orig/gdb/sparc-sol2-tdep.c 2009-02-16 00:24:10.000000000 +0000
+++ src/gdb/sparc-sol2-tdep.c 2009-02-16 01:19:38.000000000 +0000
@@ -231,6 +231,10 @@ sparc32_sol2_init_abi (struct gdbarch_in
set_gdbarch_software_single_step (gdbarch, NULL);
frame_unwind_append_unwinder (gdbarch, &sparc32_sol2_sigtramp_frame_unwind);
+
+ /* Solaris encodes the pid of the inferior in regset section
+ names. */
+ set_gdbarch_core_reg_section_encodes_pid (gdbarch, 1);
}
Index: src/gdb/sparc64-sol2-tdep.c
===================================================================
--- src.orig/gdb/sparc64-sol2-tdep.c 2009-02-16 00:24:07.000000000 +0000
+++ src/gdb/sparc64-sol2-tdep.c 2009-02-16 01:19:52.000000000 +0000
@@ -180,6 +180,10 @@ sparc64_sol2_init_abi (struct gdbarch_in
/* Solaris has kernel-assisted single-stepping support. */
set_gdbarch_software_single_step (gdbarch, NULL);
+
+ /* Solaris encodes the pid of the inferior in regset section
+ names. */
+ set_gdbarch_core_reg_section_encodes_pid (gdbarch, 1);
}