diff options
author | Tom Tromey <tromey@redhat.com> | 2012-11-08 21:16:43 +0000 |
---|---|---|
committer | Tom Tromey <tromey@redhat.com> | 2012-11-08 21:16:43 +0000 |
commit | 9015683b1c9a8d301cd846fcc8bf73726310bd4f (patch) | |
tree | fd705128b6fdec9dbea260b3181dbceca9b8ee80 /gdb/linux-tdep.c | |
parent | ea9f10bb87523d421e6c863a7ec66dfee41692b4 (diff) | |
download | gdb-9015683b1c9a8d301cd846fcc8bf73726310bd4f.zip gdb-9015683b1c9a8d301cd846fcc8bf73726310bd4f.tar.gz gdb-9015683b1c9a8d301cd846fcc8bf73726310bd4f.tar.bz2 |
gdb
* linux-tdep.c (linux_make_siginfo_note): New function.
(linux_make_corefile_notes): Use it.
* corelow.c (get_core_siginfo): New function.
(core_xfer_partial) <TARGET_OBJECT_SIGNAL_INFO>: New case.
gdb/testsuite
* gdb.base/siginfo-obj.exp: Create core file. Test siginfo from
core files, if possible.
* gdb.base/siginfo-thread.c: New file
* gdb.base/siginfo-thread.exp: New file
bfd
* elf.c (elfcore_grok_note) <NT_SIGINFO>: New case; make
pseudosection.
Diffstat (limited to 'gdb/linux-tdep.c')
-rw-r--r-- | gdb/linux-tdep.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index 65f5f97..f02d510 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -765,6 +765,44 @@ linux_collect_thread_registers (const struct regcache *regcache, return note_data; } +/* Fetch the siginfo data for the current thread, if it exists. If + there is no data, or we could not read it, return NULL. Otherwise, + return a newly malloc'd buffer holding the data and fill in *SIZE + with the size of the data. The caller is responsible for freeing + the data. */ + +static gdb_byte * +linux_get_siginfo_data (struct gdbarch *gdbarch, LONGEST *size) +{ + struct type *siginfo_type; + gdb_byte *buf; + LONGEST bytes_read; + struct cleanup *cleanups; + + if (!gdbarch_get_siginfo_type_p (gdbarch)) + return NULL; + + siginfo_type = gdbarch_get_siginfo_type (gdbarch); + + buf = xmalloc (TYPE_LENGTH (siginfo_type)); + cleanups = make_cleanup (xfree, buf); + + bytes_read = target_read (¤t_target, TARGET_OBJECT_SIGNAL_INFO, NULL, + buf, 0, TYPE_LENGTH (siginfo_type)); + if (bytes_read == TYPE_LENGTH (siginfo_type)) + { + discard_cleanups (cleanups); + *size = bytes_read; + } + else + { + do_cleanups (cleanups); + buf = NULL; + } + + return buf; +} + struct linux_corefile_thread_data { struct gdbarch *gdbarch; @@ -789,17 +827,35 @@ linux_corefile_thread_callback (struct thread_info *info, void *data) { struct cleanup *old_chain; struct regcache *regcache; + gdb_byte *siginfo_data; + LONGEST siginfo_size; + regcache = get_thread_arch_regcache (info->ptid, args->gdbarch); old_chain = save_inferior_ptid (); inferior_ptid = info->ptid; target_fetch_registers (regcache, -1); + siginfo_data = linux_get_siginfo_data (args->gdbarch, &siginfo_size); do_cleanups (old_chain); + old_chain = make_cleanup (xfree, siginfo_data); + args->note_data = args->collect (regcache, info->ptid, args->obfd, args->note_data, args->note_size, args->stop_signal); args->num_notes++; + + if (siginfo_data != NULL) + { + args->note_data = elfcore_write_note (args->obfd, + args->note_data, + args->note_size, + "CORE", NT_SIGINFO, + siginfo_data, siginfo_size); + args->num_notes++; + } + + do_cleanups (old_chain); } return !args->note_data; |