2013-02-04 Sergio Durigan Junior <sergiodj@redhat.com>
Denys Vlasenko <dvlasenk@redhat.com> Pedro Alves <palves@redhat.com> * gdbarch.sh (elfcore_write_linux_prpsinfo): New F hook. (struct elf_internal_linux_prpsinfo): Forward declare. * gdbarch.h, gdbarch.c: Regenerate. * linux-tdep.c: Include `cli/cli-utils.h'. (linux_fill_prpsinfo): New function. (linux_make_corefile_notes): Use linux_fill_prpsinfo. If there's an elfcore_write_linux_prpsinfo hook, use it, otherwise, use elfcore_write_linux_prpsinfo32 or elfcore_write_linux_prpsinfo64 depending on gdbarch pointer bitness. * ppc-linux-tdep.c: Include elf-bfd.h. (ppc_linux_init_abi): Hook in elfcore_write_ppc_linux_prpsinfo32 on 32-bit.
This commit is contained in:
parent
70a38d42c5
commit
b3ac9c7756
@ -1,3 +1,20 @@
|
||||
2013-02-04 Sergio Durigan Junior <sergiodj@redhat.com>
|
||||
Denys Vlasenko <dvlasenk@redhat.com>
|
||||
Pedro Alves <palves@redhat.com>
|
||||
|
||||
* gdbarch.sh (elfcore_write_linux_prpsinfo): New F hook.
|
||||
(struct elf_internal_linux_prpsinfo): Forward declare.
|
||||
* gdbarch.h, gdbarch.c: Regenerate.
|
||||
* linux-tdep.c: Include `cli/cli-utils.h'.
|
||||
(linux_fill_prpsinfo): New function.
|
||||
(linux_make_corefile_notes): Use linux_fill_prpsinfo. If there's
|
||||
an elfcore_write_linux_prpsinfo hook, use it, otherwise, use
|
||||
elfcore_write_linux_prpsinfo32 or elfcore_write_linux_prpsinfo64
|
||||
depending on gdbarch pointer bitness.
|
||||
* ppc-linux-tdep.c: Include elf-bfd.h.
|
||||
(ppc_linux_init_abi): Hook in elfcore_write_ppc_linux_prpsinfo32
|
||||
on 32-bit.
|
||||
|
||||
2013-02-04 Jim MacArthur <jim.macarthur@arm.com>
|
||||
Marcus Shawcroft <marcus.shawcroft@arm.com>
|
||||
Nigel Stephens <nigel.stephens@arm.com>
|
||||
|
@ -238,6 +238,7 @@ struct gdbarch
|
||||
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
|
||||
struct core_regset_section * core_regset_sections;
|
||||
gdbarch_make_corefile_notes_ftype *make_corefile_notes;
|
||||
gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo;
|
||||
gdbarch_find_memory_regions_ftype *find_memory_regions;
|
||||
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
|
||||
gdbarch_core_pid_to_str_ftype *core_pid_to_str;
|
||||
@ -408,6 +409,7 @@ struct gdbarch startup_gdbarch =
|
||||
0, /* regset_from_core_section */
|
||||
0, /* core_regset_sections */
|
||||
0, /* make_corefile_notes */
|
||||
0, /* elfcore_write_linux_prpsinfo */
|
||||
0, /* find_memory_regions */
|
||||
0, /* core_xfer_shared_libraries */
|
||||
0, /* core_pid_to_str */
|
||||
@ -709,6 +711,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
||||
/* Skip verify of fetch_pointer_argument, has predicate. */
|
||||
/* Skip verify of regset_from_core_section, has predicate. */
|
||||
/* Skip verify of make_corefile_notes, has predicate. */
|
||||
/* Skip verify of elfcore_write_linux_prpsinfo, has predicate. */
|
||||
/* Skip verify of find_memory_regions, has predicate. */
|
||||
/* Skip verify of core_xfer_shared_libraries, has predicate. */
|
||||
/* Skip verify of core_pid_to_str, has predicate. */
|
||||
@ -954,6 +957,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: elf_make_msymbol_special = <%s>\n",
|
||||
host_address_to_string (gdbarch->elf_make_msymbol_special));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: gdbarch_elfcore_write_linux_prpsinfo_p() = %d\n",
|
||||
gdbarch_elfcore_write_linux_prpsinfo_p (gdbarch));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: elfcore_write_linux_prpsinfo = <%s>\n",
|
||||
host_address_to_string (gdbarch->elfcore_write_linux_prpsinfo));
|
||||
fprintf_unfiltered (file,
|
||||
"gdbarch_dump: fast_tracepoint_valid_at = <%s>\n",
|
||||
host_address_to_string (gdbarch->fast_tracepoint_valid_at));
|
||||
@ -3367,6 +3376,30 @@ set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch,
|
||||
gdbarch->make_corefile_notes = make_corefile_notes;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_elfcore_write_linux_prpsinfo_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
return gdbarch->elfcore_write_linux_prpsinfo != NULL;
|
||||
}
|
||||
|
||||
char *
|
||||
gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info)
|
||||
{
|
||||
gdb_assert (gdbarch != NULL);
|
||||
gdb_assert (gdbarch->elfcore_write_linux_prpsinfo != NULL);
|
||||
if (gdbarch_debug >= 2)
|
||||
fprintf_unfiltered (gdb_stdlog, "gdbarch_elfcore_write_linux_prpsinfo called\n");
|
||||
return gdbarch->elfcore_write_linux_prpsinfo (obfd, note_data, note_size, info);
|
||||
}
|
||||
|
||||
void
|
||||
set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch,
|
||||
gdbarch_elfcore_write_linux_prpsinfo_ftype elfcore_write_linux_prpsinfo)
|
||||
{
|
||||
gdbarch->elfcore_write_linux_prpsinfo = elfcore_write_linux_prpsinfo;
|
||||
}
|
||||
|
||||
int
|
||||
gdbarch_find_memory_regions_p (struct gdbarch *gdbarch)
|
||||
{
|
||||
|
@ -57,6 +57,7 @@ struct agent_expr;
|
||||
struct axs_value;
|
||||
struct stap_parse_info;
|
||||
struct ravenscar_arch_ops;
|
||||
struct elf_internal_linux_prpsinfo;
|
||||
|
||||
/* The architecture associated with the inferior through the
|
||||
connection to the target.
|
||||
@ -736,6 +737,18 @@ typedef char * (gdbarch_make_corefile_notes_ftype) (struct gdbarch *gdbarch, bfd
|
||||
extern char * gdbarch_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size);
|
||||
extern void set_gdbarch_make_corefile_notes (struct gdbarch *gdbarch, gdbarch_make_corefile_notes_ftype *make_corefile_notes);
|
||||
|
||||
/* The elfcore writer hook to use to write Linux prpsinfo notes to core
|
||||
files. Most Linux architectures use the same prpsinfo32 or
|
||||
prpsinfo64 layouts, and so won't need to provide this hook, as we
|
||||
call the Linux generic routines in bfd to write prpsinfo notes by
|
||||
default. */
|
||||
|
||||
extern int gdbarch_elfcore_write_linux_prpsinfo_p (struct gdbarch *gdbarch);
|
||||
|
||||
typedef char * (gdbarch_elfcore_write_linux_prpsinfo_ftype) (bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info);
|
||||
extern char * gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, bfd *obfd, char *note_data, int *note_size, const struct elf_internal_linux_prpsinfo *info);
|
||||
extern void set_gdbarch_elfcore_write_linux_prpsinfo (struct gdbarch *gdbarch, gdbarch_elfcore_write_linux_prpsinfo_ftype *elfcore_write_linux_prpsinfo);
|
||||
|
||||
/* Find core file memory regions */
|
||||
|
||||
extern int gdbarch_find_memory_regions_p (struct gdbarch *gdbarch);
|
||||
|
@ -641,6 +641,13 @@ v:struct core_regset_section *:core_regset_sections:const char *name, int len:::
|
||||
# Create core file notes
|
||||
M:char *:make_corefile_notes:bfd *obfd, int *note_size:obfd, note_size
|
||||
|
||||
# The elfcore writer hook to use to write Linux prpsinfo notes to core
|
||||
# files. Most Linux architectures use the same prpsinfo32 or
|
||||
# prpsinfo64 layouts, and so won't need to provide this hook, as we
|
||||
# call the Linux generic routines in bfd to write prpsinfo 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
|
||||
|
||||
# Find core file memory regions
|
||||
M:int:find_memory_regions:find_memory_region_ftype func, void *data:func, data
|
||||
|
||||
@ -1082,6 +1089,7 @@ struct agent_expr;
|
||||
struct axs_value;
|
||||
struct stap_parse_info;
|
||||
struct ravenscar_arch_ops;
|
||||
struct elf_internal_linux_prpsinfo;
|
||||
|
||||
/* The architecture associated with the inferior through the
|
||||
connection to the target.
|
||||
|
235
gdb/linux-tdep.c
235
gdb/linux-tdep.c
@ -32,6 +32,7 @@
|
||||
#include "cli/cli-utils.h"
|
||||
#include "arch-utils.h"
|
||||
#include "gdb_obstack.h"
|
||||
#include "cli/cli-utils.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
@ -1153,6 +1154,206 @@ linux_corefile_thread_callback (struct thread_info *info, void *data)
|
||||
return !args->note_data;
|
||||
}
|
||||
|
||||
/* Fill the PRPSINFO structure with information about the process being
|
||||
debugged. Returns 1 in case of success, 0 for failures. Please note that
|
||||
even if the structure cannot be entirely filled (e.g., GDB was unable to
|
||||
gather information about the process UID/GID), this function will still
|
||||
return 1 since some information was already recorded. It will only return
|
||||
0 iff nothing can be gathered. */
|
||||
|
||||
static int
|
||||
linux_fill_prpsinfo (struct elf_internal_linux_prpsinfo *p)
|
||||
{
|
||||
/* The filename which we will use to obtain some info about the process.
|
||||
We will basically use this to store the `/proc/PID/FILENAME' file. */
|
||||
char filename[100];
|
||||
/* The full name of the program which generated the corefile. */
|
||||
char *fname;
|
||||
/* The basename of the executable. */
|
||||
const char *basename;
|
||||
/* The arguments of the program. */
|
||||
char *psargs;
|
||||
char *infargs;
|
||||
/* The contents of `/proc/PID/stat' and `/proc/PID/status' files. */
|
||||
char *proc_stat, *proc_status;
|
||||
/* Temporary buffer. */
|
||||
char *tmpstr;
|
||||
/* The valid states of a process, according to the Linux kernel. */
|
||||
const char valid_states[] = "RSDTZW";
|
||||
/* The program state. */
|
||||
const char *prog_state;
|
||||
/* The state of the process. */
|
||||
char pr_sname;
|
||||
/* The PID of the program which generated the corefile. */
|
||||
pid_t pid;
|
||||
/* Process flags. */
|
||||
unsigned int pr_flag;
|
||||
/* Process nice value. */
|
||||
long pr_nice;
|
||||
/* The number of fields read by `sscanf'. */
|
||||
int n_fields = 0;
|
||||
/* Cleanups. */
|
||||
struct cleanup *c;
|
||||
int i;
|
||||
|
||||
gdb_assert (p != NULL);
|
||||
|
||||
/* Obtaining PID and filename. */
|
||||
pid = ptid_get_pid (inferior_ptid);
|
||||
xsnprintf (filename, sizeof (filename), "/proc/%d/cmdline", (int) pid);
|
||||
fname = target_fileio_read_stralloc (filename);
|
||||
|
||||
if (fname == NULL || *fname == '\0')
|
||||
{
|
||||
/* No program name was read, so we won't be able to retrieve more
|
||||
information about the process. */
|
||||
xfree (fname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
c = make_cleanup (xfree, fname);
|
||||
memset (p, 0, sizeof (*p));
|
||||
|
||||
/* Defining the PID. */
|
||||
p->pr_pid = pid;
|
||||
|
||||
/* Copying the program name. Only the basename matters. */
|
||||
basename = lbasename (fname);
|
||||
strncpy (p->pr_fname, basename, sizeof (p->pr_fname));
|
||||
p->pr_fname[sizeof (p->pr_fname) - 1] = '\0';
|
||||
|
||||
infargs = get_inferior_args ();
|
||||
|
||||
psargs = xstrdup (fname);
|
||||
if (infargs != NULL)
|
||||
psargs = reconcat (psargs, psargs, " ", infargs, NULL);
|
||||
|
||||
make_cleanup (xfree, psargs);
|
||||
|
||||
strncpy (p->pr_psargs, psargs, sizeof (p->pr_psargs));
|
||||
p->pr_psargs[sizeof (p->pr_psargs) - 1] = '\0';
|
||||
|
||||
xsnprintf (filename, sizeof (filename), "/proc/%d/stat", (int) pid);
|
||||
proc_stat = target_fileio_read_stralloc (filename);
|
||||
make_cleanup (xfree, proc_stat);
|
||||
|
||||
if (proc_stat == NULL || *proc_stat == '\0')
|
||||
{
|
||||
/* Despite being unable to read more information about the
|
||||
process, we return 1 here because at least we have its
|
||||
command line, PID and arguments. */
|
||||
do_cleanups (c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Ok, we have the stats. It's time to do a little parsing of the
|
||||
contents of the buffer, so that we end up reading what we want.
|
||||
|
||||
The following parsing mechanism is strongly based on the
|
||||
information generated by the `fs/proc/array.c' file, present in
|
||||
the Linux kernel tree. More details about how the information is
|
||||
displayed can be obtained by seeing the manpage of proc(5),
|
||||
specifically under the entry of `/proc/[pid]/stat'. */
|
||||
|
||||
/* Getting rid of the PID, since we already have it. */
|
||||
while (isdigit (*proc_stat))
|
||||
++proc_stat;
|
||||
|
||||
proc_stat = skip_spaces (proc_stat);
|
||||
|
||||
/* Getting rid of the executable name, since we already have it. We
|
||||
know that this name will be in parentheses, so we can safely look
|
||||
for the close-paren. */
|
||||
while (*proc_stat != ')')
|
||||
++proc_stat;
|
||||
++proc_stat;
|
||||
|
||||
proc_stat = skip_spaces (proc_stat);
|
||||
|
||||
n_fields = sscanf (proc_stat,
|
||||
"%c" /* Process state. */
|
||||
"%d%d%d" /* Parent PID, group ID, session ID. */
|
||||
"%*d%*d" /* tty_nr, tpgid (not used). */
|
||||
"%u" /* Flags. */
|
||||
"%*s%*s%*s%*s" /* minflt, cminflt, majflt,
|
||||
cmajflt (not used). */
|
||||
"%*s%*s%*s%*s" /* utime, stime, cutime,
|
||||
cstime (not used). */
|
||||
"%*s" /* Priority (not used). */
|
||||
"%ld", /* Nice. */
|
||||
&pr_sname,
|
||||
&p->pr_ppid, &p->pr_pgrp, &p->pr_sid,
|
||||
&pr_flag,
|
||||
&pr_nice);
|
||||
|
||||
if (n_fields != 6)
|
||||
{
|
||||
/* Again, we couldn't read the complementary information about
|
||||
the process state. However, we already have minimal
|
||||
information, so we just return 1 here. */
|
||||
do_cleanups (c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Filling the structure fields. */
|
||||
prog_state = strchr (valid_states, pr_sname);
|
||||
if (prog_state != NULL)
|
||||
p->pr_state = prog_state - valid_states;
|
||||
else
|
||||
{
|
||||
/* Zero means "Running". */
|
||||
p->pr_state = 0;
|
||||
}
|
||||
|
||||
p->pr_sname = p->pr_state > 5 ? '.' : pr_sname;
|
||||
p->pr_zomb = p->pr_sname == 'Z';
|
||||
p->pr_nice = pr_nice;
|
||||
p->pr_flag = pr_flag;
|
||||
|
||||
/* Finally, obtaining the UID and GID. For that, we read and parse the
|
||||
contents of the `/proc/PID/status' file. */
|
||||
xsnprintf (filename, sizeof (filename), "/proc/%d/status", (int) pid);
|
||||
proc_status = target_fileio_read_stralloc (filename);
|
||||
make_cleanup (xfree, proc_status);
|
||||
|
||||
if (proc_status == NULL || *proc_status == '\0')
|
||||
{
|
||||
/* Returning 1 since we already have a bunch of information. */
|
||||
do_cleanups (c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Extracting the UID. */
|
||||
tmpstr = strstr (proc_status, "Uid:");
|
||||
if (tmpstr != NULL)
|
||||
{
|
||||
/* Advancing the pointer to the beginning of the UID. */
|
||||
tmpstr += sizeof ("Uid:");
|
||||
while (*tmpstr != '\0' && !isdigit (*tmpstr))
|
||||
++tmpstr;
|
||||
|
||||
if (isdigit (*tmpstr))
|
||||
p->pr_uid = strtol (tmpstr, &tmpstr, 10);
|
||||
}
|
||||
|
||||
/* Extracting the GID. */
|
||||
tmpstr = strstr (proc_status, "Gid:");
|
||||
if (tmpstr != NULL)
|
||||
{
|
||||
/* Advancing the pointer to the beginning of the GID. */
|
||||
tmpstr += sizeof ("Gid:");
|
||||
while (*tmpstr != '\0' && !isdigit (*tmpstr))
|
||||
++tmpstr;
|
||||
|
||||
if (isdigit (*tmpstr))
|
||||
p->pr_gid = strtol (tmpstr, &tmpstr, 10);
|
||||
}
|
||||
|
||||
do_cleanups (c);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Fills the "to_make_corefile_note" target vector. Builds the note
|
||||
section for a corefile, and returns it in a malloc buffer. */
|
||||
|
||||
@ -1161,26 +1362,30 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size,
|
||||
linux_collect_thread_registers_ftype collect)
|
||||
{
|
||||
struct linux_corefile_thread_data thread_args;
|
||||
struct elf_internal_linux_prpsinfo prpsinfo;
|
||||
char *note_data = NULL;
|
||||
gdb_byte *auxv;
|
||||
int auxv_len;
|
||||
|
||||
/* Process information. */
|
||||
if (get_exec_file (0))
|
||||
if (linux_fill_prpsinfo (&prpsinfo))
|
||||
{
|
||||
const char *fname = lbasename (get_exec_file (0));
|
||||
char *psargs = xstrdup (fname);
|
||||
|
||||
if (get_inferior_args ())
|
||||
psargs = reconcat (psargs, psargs, " ", get_inferior_args (),
|
||||
(char *) NULL);
|
||||
|
||||
note_data = elfcore_write_prpsinfo (obfd, note_data, note_size,
|
||||
fname, psargs);
|
||||
xfree (psargs);
|
||||
|
||||
if (!note_data)
|
||||
return NULL;
|
||||
if (gdbarch_elfcore_write_linux_prpsinfo_p (gdbarch))
|
||||
{
|
||||
note_data = gdbarch_elfcore_write_linux_prpsinfo (gdbarch, obfd,
|
||||
note_data, note_size,
|
||||
&prpsinfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (gdbarch_ptr_bit (gdbarch) == 64)
|
||||
note_data = elfcore_write_linux_prpsinfo64 (obfd,
|
||||
note_data, note_size,
|
||||
&prpsinfo);
|
||||
else
|
||||
note_data = elfcore_write_linux_prpsinfo32 (obfd,
|
||||
note_data, note_size,
|
||||
&prpsinfo);
|
||||
}
|
||||
}
|
||||
|
||||
/* Thread register information. */
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include "parser-defs.h"
|
||||
#include "user-regs.h"
|
||||
#include <ctype.h>
|
||||
#include "elf-bfd.h" /* for elfcore_write_* */
|
||||
|
||||
#include "features/rs6000/powerpc-32l.c"
|
||||
#include "features/rs6000/powerpc-altivec32l.c"
|
||||
@ -1368,6 +1369,13 @@ ppc_linux_init_abi (struct gdbarch_info info,
|
||||
set_gdbarch_core_regset_sections (gdbarch,
|
||||
ppc64_linux_fp_regset_sections);
|
||||
}
|
||||
|
||||
/* PPC32 uses a different prpsinfo32 compared to most other Linux
|
||||
archs. */
|
||||
if (tdep->wordsize == 4)
|
||||
set_gdbarch_elfcore_write_linux_prpsinfo (gdbarch,
|
||||
elfcore_write_ppc_linux_prpsinfo32);
|
||||
|
||||
set_gdbarch_regset_from_core_section (gdbarch,
|
||||
ppc_linux_regset_from_core_section);
|
||||
set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description);
|
||||
|
Loading…
Reference in New Issue
Block a user