Add the ability for GDB to printout the thread name along with other

thread specific informations.

In order to do that, and in order to avoid KBI breakage with existing
infrastructure the following semantic is implemented:
- For live programs, a new member to the PT_LWPINFO is added (pl_tdname)
- For cores, a new ELF note is added (NT_THRMISC) that can be used for
  storing thread specific, miscellaneous, informations. Right now it is
  just popluated with a thread name.

GDB, then, retrieves the correct informations from the corefile via the
BFD interface, as it groks the ELF notes and create appropriate
pseudo-sections.

Sponsored by:	Sandvine Incorporated
Tested by:	gianni
Discussed with:	dim, kan, kib
MFC after:	2 weeks
This commit is contained in:
Attilio Rao 2010-11-22 14:42:13 +00:00
parent 7a3923c00e
commit 7f08176ee8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=215679
14 changed files with 131 additions and 3 deletions

View File

@ -1673,6 +1673,8 @@ extern char * elfcore_write_pstatus
(bfd *, char *, int *, long, int, const void *); (bfd *, char *, int *, long, int, const void *);
extern char *elfcore_write_prfpreg extern char *elfcore_write_prfpreg
(bfd *, char *, int *, const void *, int); (bfd *, char *, int *, const void *, int);
extern char *elfcore_write_thrmisc
(bfd *, char *, int *, const char *, int);
extern char *elfcore_write_prxfpreg extern char *elfcore_write_prxfpreg
(bfd *, char *, int *, const void *, int); (bfd *, char *, int *, const void *, int);
extern char *elfcore_write_lwpstatus extern char *elfcore_write_lwpstatus

View File

@ -6316,6 +6316,12 @@ _bfd_elf_rel_vtable_reloc_fn
#ifdef HAVE_SYS_PROCFS_H #ifdef HAVE_SYS_PROCFS_H
# include <sys/procfs.h> # include <sys/procfs.h>
/* Define HAVE_THRMISC_T for consistency with other similar GNU-type stubs. */
#undef HAVE_THRMISC_T
#if defined (THRMISC_VERSION)
#define HAVE_THRMISC_T 1
#endif
#endif #endif
/* FIXME: this is kinda wrong, but it's what gdb wants. */ /* FIXME: this is kinda wrong, but it's what gdb wants. */
@ -6497,6 +6503,16 @@ elfcore_grok_prxfpreg (bfd *abfd, Elf_Internal_Note *note)
return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note); return elfcore_make_note_pseudosection (abfd, ".reg-xfp", note);
} }
#if defined (HAVE_THRMISC_T)
static bfd_boolean
elfcore_grok_thrmisc (bfd *abfd, Elf_Internal_Note *note)
{
return elfcore_make_note_pseudosection (abfd, ".tname", note);
}
#endif /* defined (HAVE_THRMISC_T) */
#if defined (HAVE_PRPSINFO_T) #if defined (HAVE_PRPSINFO_T)
typedef prpsinfo_t elfcore_psinfo_t; typedef prpsinfo_t elfcore_psinfo_t;
#if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */ #if defined (HAVE_PRPSINFO32_T) /* Sparc64 cross Sparc32 */
@ -6863,6 +6879,12 @@ elfcore_grok_note (bfd *abfd, Elf_Internal_Note *note)
return TRUE; return TRUE;
} }
#if defined (HAVE_THRMISC_T)
case NT_THRMISC:
return elfcore_grok_thrmisc (abfd, note);
#endif
} }
} }
@ -7244,6 +7266,22 @@ elfcore_write_prfpreg (bfd *abfd,
note_name, NT_FPREGSET, fpregs, size); note_name, NT_FPREGSET, fpregs, size);
} }
char *
elfcore_write_thrmisc (bfd *abfd,
char *buf,
int *bufsiz,
const char *tname,
int size)
{
#if defined (HAVE_THRMISC_T)
char *note_name = "CORE";
return elfcore_write_note (abfd, buf, bufsiz,
note_name, NT_THRMISC, tname, size);
#else
return buf;
#endif
}
char * char *
elfcore_write_prxfpreg (bfd *abfd, elfcore_write_prxfpreg (bfd *abfd,
char *buf, char *buf,

View File

@ -9908,6 +9908,7 @@ get_note_type (unsigned e_type)
case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)"); case NT_PSTATUS: return _("NT_PSTATUS (pstatus structure)");
case NT_FPREGS: return _("NT_FPREGS (floating point registers)"); case NT_FPREGS: return _("NT_FPREGS (floating point registers)");
case NT_PSINFO: return _("NT_PSINFO (psinfo structure)"); case NT_PSINFO: return _("NT_PSINFO (psinfo structure)");
case NT_THRMISC: return _("NT_THRMISC (thrmisc structure)");
case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)"); case NT_LWPSTATUS: return _("NT_LWPSTATUS (lwpstatus_t structure)");
case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)"); case NT_LWPSINFO: return _("NT_LWPSINFO (lwpsinfo_t structure)");
case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus structure)"); case NT_WIN32PSTATUS: return _("NT_WIN32PSTATUS (win32_pstatus structure)");

View File

@ -366,6 +366,7 @@
#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ #define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */
#define NT_TASKSTRUCT 4 /* Contains copy of task struct */ #define NT_TASKSTRUCT 4 /* Contains copy of task struct */
#define NT_AUXV 6 /* Contains copy of Elfxx_auxv_t */ #define NT_AUXV 6 /* Contains copy of Elfxx_auxv_t */
#define NT_THRMISC 7 /* Contains copy of thrmisc struct */
#define NT_PRXFPREG 0x46e62b7f /* Contains a user_xfpregs_struct; */ #define NT_PRXFPREG 0x46e62b7f /* Contains a user_xfpregs_struct; */
/* note name must be "LINUX". */ /* note name must be "LINUX". */

View File

@ -224,6 +224,7 @@ typedef struct {
#define NT_TASKSTRUCT 4 #define NT_TASKSTRUCT 4
#define NT_PLATFORM 5 #define NT_PLATFORM 5
#define NT_AUXV 6 #define NT_AUXV 6
#define NT_THRMISC 7
/* Note types used in executables */ /* Note types used in executables */
/* NetBSD executables (name = "NetBSD") */ /* NetBSD executables (name = "NetBSD") */

View File

@ -124,6 +124,7 @@ fbsd_make_corefile_notes (bfd *obfd, int *note_size)
fpregset_t fpregs; fpregset_t fpregs;
char *note_data = NULL; char *note_data = NULL;
Elf_Internal_Ehdr *i_ehdrp; Elf_Internal_Ehdr *i_ehdrp;
char fakename;
/* Put a "FreeBSD" label in the ELF header. */ /* Put a "FreeBSD" label in the ELF header. */
i_ehdrp = elf_elfheader (obfd); i_ehdrp = elf_elfheader (obfd);
@ -138,6 +139,10 @@ fbsd_make_corefile_notes (bfd *obfd, int *note_size)
note_data = elfcore_write_prfpreg (obfd, note_data, note_size, note_data = elfcore_write_prfpreg (obfd, note_data, note_size,
&fpregs, sizeof (fpregs)); &fpregs, sizeof (fpregs));
fakename = '\0';
note_data = elfcore_write_thrmisc (obfd, note_data, note_size,
&fakename, sizeof (fakename));
if (get_exec_file (0)) if (get_exec_file (0))
{ {
char *fname = strrchr (get_exec_file (0), '/') + 1; char *fname = strrchr (get_exec_file (0), '/') + 1;

View File

@ -426,6 +426,46 @@ fbsd_thread_deactivate (void)
init_thread_list (); init_thread_list ();
} }
static char *
fbsd_thread_get_name (lwpid_t lwpid)
{
static char last_thr_name[MAXCOMLEN + 1];
char section_name[32];
struct ptrace_lwpinfo lwpinfo;
bfd_size_type size;
struct bfd_section *section;
if (target_has_execution)
{
if (ptrace (PT_LWPINFO, lwpid, (caddr_t)&lwpinfo, sizeof (lwpinfo)) == -1)
goto fail;
strncpy (last_thr_name, lwpinfo.pl_tdname, sizeof (last_thr_name) - 1);
}
else
{
snprintf (section_name, sizeof (section_name), ".tname/%u", lwpid);
section = bfd_get_section_by_name (core_bfd, section_name);
if (! section)
goto fail;
/* Section size fix-up. */
size = bfd_section_size (core_bfd, section);
if (size > sizeof (last_thr_name))
size = sizeof (last_thr_name);
if (! bfd_get_section_contents (core_bfd, section, last_thr_name,
(file_ptr)0, size))
goto fail;
if (last_thr_name[0] == '\0')
goto fail;
}
last_thr_name[sizeof (last_thr_name) - 1] = '\0';
return last_thr_name;
fail:
strcpy (last_thr_name, "<unknown>");
return last_thr_name;
}
static void static void
fbsd_thread_new_objfile (struct objfile *objfile) fbsd_thread_new_objfile (struct objfile *objfile)
{ {
@ -1158,7 +1198,7 @@ fbsd_thread_find_new_threads (void)
static char * static char *
fbsd_thread_pid_to_str (ptid_t ptid) fbsd_thread_pid_to_str (ptid_t ptid)
{ {
static char buf[64]; static char buf[64 + MAXCOMLEN];
if (IS_THREAD (ptid)) if (IS_THREAD (ptid))
{ {
@ -1178,8 +1218,9 @@ fbsd_thread_pid_to_str (ptid_t ptid)
if (ti.ti_lid != 0) if (ti.ti_lid != 0)
{ {
snprintf (buf, sizeof (buf), "Thread %llx (LWP %d)", snprintf (buf, sizeof (buf), "Thread %llx (LWP %d/%s)",
(unsigned long long)th.th_thread, ti.ti_lid); (unsigned long long)th.th_thread, ti.ti_lid,
fbsd_thread_get_name (ti.ti_lid));
} }
else else
{ {

View File

@ -240,6 +240,11 @@ struct prpsinfo32 {
char pr_psargs[PRARGSZ+1]; char pr_psargs[PRARGSZ+1];
}; };
struct thrmisc32 {
char pr_tname[MAXCOMLEN+1];
u_int _pad;
};
struct mq_attr32 { struct mq_attr32 {
int mq_flags; int mq_flags;
int mq_maxmsg; int mq_maxmsg;

View File

@ -1316,12 +1316,14 @@ typedef struct prpsinfo32 elf_prpsinfo_t;
typedef struct fpreg32 elf_prfpregset_t; typedef struct fpreg32 elf_prfpregset_t;
typedef struct fpreg32 elf_fpregset_t; typedef struct fpreg32 elf_fpregset_t;
typedef struct reg32 elf_gregset_t; typedef struct reg32 elf_gregset_t;
typedef struct thrmisc32 elf_thrmisc_t;
#else #else
typedef prstatus_t elf_prstatus_t; typedef prstatus_t elf_prstatus_t;
typedef prpsinfo_t elf_prpsinfo_t; typedef prpsinfo_t elf_prpsinfo_t;
typedef prfpregset_t elf_prfpregset_t; typedef prfpregset_t elf_prfpregset_t;
typedef prfpregset_t elf_fpregset_t; typedef prfpregset_t elf_fpregset_t;
typedef gregset_t elf_gregset_t; typedef gregset_t elf_gregset_t;
typedef thrmisc_t elf_thrmisc_t;
#endif #endif
static void static void
@ -1331,10 +1333,12 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
elf_prstatus_t status; elf_prstatus_t status;
elf_prfpregset_t fpregset; elf_prfpregset_t fpregset;
elf_prpsinfo_t psinfo; elf_prpsinfo_t psinfo;
elf_thrmisc_t thrmisc;
} *tempdata; } *tempdata;
elf_prstatus_t *status; elf_prstatus_t *status;
elf_prfpregset_t *fpregset; elf_prfpregset_t *fpregset;
elf_prpsinfo_t *psinfo; elf_prpsinfo_t *psinfo;
elf_thrmisc_t *thrmisc;
struct proc *p; struct proc *p;
struct thread *thr; struct thread *thr;
size_t ehoff, noteoff, notesz, phoff; size_t ehoff, noteoff, notesz, phoff;
@ -1357,11 +1361,13 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
status = &tempdata->status; status = &tempdata->status;
fpregset = &tempdata->fpregset; fpregset = &tempdata->fpregset;
psinfo = &tempdata->psinfo; psinfo = &tempdata->psinfo;
thrmisc = &tempdata->thrmisc;
} else { } else {
tempdata = NULL; tempdata = NULL;
status = NULL; status = NULL;
fpregset = NULL; fpregset = NULL;
psinfo = NULL; psinfo = NULL;
thrmisc = NULL;
} }
if (dst != NULL) { if (dst != NULL) {
@ -1401,11 +1407,15 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs)
fill_regs(thr, &status->pr_reg); fill_regs(thr, &status->pr_reg);
fill_fpregs(thr, fpregset); fill_fpregs(thr, fpregset);
#endif #endif
memset(&thrmisc->_pad, 0, sizeof (thrmisc->_pad));
strcpy(thrmisc->pr_tname, thr->td_name);
} }
__elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status,
sizeof *status); sizeof *status);
__elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset, __elfN(putnote)(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
sizeof *fpregset); sizeof *fpregset);
__elfN(putnote)(dst, off, "FreeBSD", NT_THRMISC, thrmisc,
sizeof *thrmisc);
/* /*
* Allow for MD specific notes, as well as any MD * Allow for MD specific notes, as well as any MD
* specific preparations for writing MI notes. * specific preparations for writing MI notes.

View File

@ -93,6 +93,7 @@ struct ptrace_lwpinfo32 {
sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */ sigset_t pl_siglist; /* LWP pending signal */
struct siginfo32 pl_siginfo; /* siginfo for signal */ struct siginfo32 pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name. */
}; };
#endif #endif
@ -520,6 +521,7 @@ ptrace_lwpinfo_to32(const struct ptrace_lwpinfo *pl,
pl32->pl_sigmask = pl->pl_sigmask; pl32->pl_sigmask = pl->pl_sigmask;
pl32->pl_siglist = pl->pl_siglist; pl32->pl_siglist = pl->pl_siglist;
siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo); siginfo_to_siginfo32(&pl->pl_siginfo, &pl32->pl_siginfo);
strcpy(pl32->pl_tdname, pl->pl_tdname);
} }
#endif /* COMPAT_FREEBSD32 */ #endif /* COMPAT_FREEBSD32 */
@ -1164,6 +1166,7 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
pl->pl_flags |= PL_FLAG_EXEC; pl->pl_flags |= PL_FLAG_EXEC;
pl->pl_sigmask = td2->td_sigmask; pl->pl_sigmask = td2->td_sigmask;
pl->pl_siglist = td2->td_siglist; pl->pl_siglist = td2->td_siglist;
strcpy(pl->pl_tdname, td2->td_name);
#ifdef COMPAT_FREEBSD32 #ifdef COMPAT_FREEBSD32
if (wrap32) if (wrap32)
ptrace_lwpinfo_to32(pl, pl32); ptrace_lwpinfo_to32(pl, pl32);

View File

@ -479,6 +479,7 @@ typedef struct {
#define NT_PRSTATUS 1 /* Process status. */ #define NT_PRSTATUS 1 /* Process status. */
#define NT_FPREGSET 2 /* Floating point registers. */ #define NT_FPREGSET 2 /* Floating point registers. */
#define NT_PRPSINFO 3 /* Process state info. */ #define NT_PRPSINFO 3 /* Process state info. */
#define NT_THRMISC 7 /* Thread miscellaneous info. */
/* Symbol Binding - ELFNN_ST_BIND - st_info */ /* Symbol Binding - ELFNN_ST_BIND - st_info */
#define STB_LOCAL 0 /* Local symbol */ #define STB_LOCAL 0 /* Local symbol */

View File

@ -80,6 +80,13 @@ typedef struct prpsinfo {
char pr_psargs[PRARGSZ+1]; /* Arguments, null terminated (1) */ char pr_psargs[PRARGSZ+1]; /* Arguments, null terminated (1) */
} prpsinfo_t; } prpsinfo_t;
#define THRMISC_VERSION 1 /* Current version of thrmisc_t */
typedef struct thrmisc {
char pr_tname[MAXCOMLEN+1]; /* Thread name, null terminated (1) */
u_int _pad; /* Convenience pad, 0-filled (1) */
} thrmisc_t;
typedef uint64_t psaddr_t; /* An address in the target process. */ typedef uint64_t psaddr_t; /* An address in the target process. */
#endif /* _SYS_PROCFS_H_ */ #endif /* _SYS_PROCFS_H_ */

View File

@ -34,6 +34,7 @@
#define _SYS_PTRACE_H_ #define _SYS_PTRACE_H_
#include <sys/signal.h> #include <sys/signal.h>
#include <sys/param.h>
#include <machine/reg.h> #include <machine/reg.h>
#define PT_TRACE_ME 0 /* child declares it's being traced */ #define PT_TRACE_ME 0 /* child declares it's being traced */
@ -106,6 +107,7 @@ struct ptrace_lwpinfo {
sigset_t pl_sigmask; /* LWP signal mask */ sigset_t pl_sigmask; /* LWP signal mask */
sigset_t pl_siglist; /* LWP pending signal */ sigset_t pl_siglist; /* LWP pending signal */
struct __siginfo pl_siginfo; /* siginfo for signal */ struct __siginfo pl_siginfo; /* siginfo for signal */
char pl_tdname[MAXCOMLEN + 1]; /* LWP name */
}; };
/* Argument structure for PT_VM_ENTRY. */ /* Argument structure for PT_VM_ENTRY. */

View File

@ -284,10 +284,12 @@ elf_getstatus(pid_t pid, prpsinfo_t *psinfo)
static void static void
elf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs) elf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs)
{ {
struct ptrace_lwpinfo lwpinfo;
struct { struct {
prstatus_t status; prstatus_t status;
prfpregset_t fpregset; prfpregset_t fpregset;
prpsinfo_t psinfo; prpsinfo_t psinfo;
thrmisc_t thrmisc;
} *tempdata; } *tempdata;
size_t ehoff; size_t ehoff;
size_t phoff; size_t phoff;
@ -300,6 +302,7 @@ elf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs)
prstatus_t *status; prstatus_t *status;
prfpregset_t *fpregset; prfpregset_t *fpregset;
prpsinfo_t *psinfo; prpsinfo_t *psinfo;
thrmisc_t *thrmisc;
ehoff = *off; ehoff = *off;
*off += sizeof(Elf_Ehdr); *off += sizeof(Elf_Ehdr);
@ -315,11 +318,13 @@ elf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs)
status = &tempdata->status; status = &tempdata->status;
fpregset = &tempdata->fpregset; fpregset = &tempdata->fpregset;
psinfo = &tempdata->psinfo; psinfo = &tempdata->psinfo;
thrmisc = &tempdata->thrmisc;
} else { } else {
tempdata = NULL; tempdata = NULL;
status = NULL; status = NULL;
fpregset = NULL; fpregset = NULL;
psinfo = NULL; psinfo = NULL;
thrmisc = NULL;
} }
errno = 0; errno = 0;
@ -356,11 +361,17 @@ elf_puthdr(pid_t pid, vm_map_entry_t map, void *dst, size_t *off, int numsegs)
ptrace(PT_GETREGS, tids[i], (void *)&status->pr_reg, 0); ptrace(PT_GETREGS, tids[i], (void *)&status->pr_reg, 0);
ptrace(PT_GETFPREGS, tids[i], (void *)fpregset, 0); ptrace(PT_GETFPREGS, tids[i], (void *)fpregset, 0);
ptrace(PT_LWPINFO, tids[i], (void *)&lwpinfo,
sizeof(lwpinfo));
memset(&thrmisc->_pad, 0, sizeof(thrmisc->_pad));
strcpy(thrmisc->pr_tname, lwpinfo.pl_tdname);
} }
elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status, elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
sizeof *status); sizeof *status);
elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset, elf_putnote(dst, off, "FreeBSD", NT_FPREGSET, fpregset,
sizeof *fpregset); sizeof *fpregset);
elf_putnote(dst, off, "FreeBSD", NT_THRMISC, thrmisc,
sizeof *thrmisc);
} }
notesz = *off - noteoff; notesz = *off - noteoff;