From d26e3629bbf1122feb8400bdeb8da32931c24d61 Mon Sep 17 00:00:00 2001 From: Kwok Yeung Date: Thu, 21 Jul 2011 23:46:12 +0000 Subject: [PATCH] 2011-07-22 Kwok Cheung Yeung gdb/ * defs.h: Add guard against inclusion in gdbserver. (struct ptid, ptid_t): Move to common/ptid.h. (xfree, xzalloc, xasprintf, xvasprintf, xstrprintf, xstrvprintf, xsnprintf, internal_error): Move to common/common-utils.h. (nomem): Delete. * gdb_assert.h: Move into common/ sub-directory. * gdb_locale.h: Ditto. * gdb_dirent.h: Ditto. * inferior.h (minus_one_ptid, null_ptid, ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid): Move into common/ptid.h. * xml-support.c (xml_escape_text): Move into common/xml-utils.c. (gdb_xml_create_parser_and_cleanup_1, xml_fetch_context_from_file): Change nomem to malloc_failure. * xml-support.h (xml_escape_text): Move into common/xml-utils.h. * utils.c (nomem): Rename to malloc_failure. (xmalloc, xzalloc, xrealloc, xcalloc, xfree, xstrprintf, xasprintf, xvasprintf, xstrvprintf, xsnprintf): Move to common/common-utils.c. (gdb_buildargv): Change nomem to malloc_failure. * infrun.c (null_ptid, minus_one_ptid, ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid): Move into common/ptid.c. (initialize_infrun): Delete initialization of null_ptid and minus_one_ptid. * linux-nat.c (linux_nat_xfer_osdata): Defer to linux_common_xfer_osdata. * Makefile.in (SFILES): Add common/common-utils.c, common/xml-utils.c, common/ptid.c and common/buffer.c. (HFILES_NO_SRCDIR): Add common/common-utils.h, common/xml-utils.h, common/ptid.h, common/buffer.h and common/linux-osdata.h. (COMMON_OBS): Add xml-utils.o, common-utils.o, buffer.o and ptid.o. (common-utils.o, xml-utils.o, ptid.o, buffer.o, linux-osdata.o): New rules. * common/gdb_assert.h: New. * common/gdb_dirent.h: New. * common/gdb_locale.h: New. * common/buffer.c: New. * common/buffer.h: New. * common/ptid.c: New. * common/ptid.h: New. * common/xml-utils.c: New. * common/xml-utils.h: New. * common/common-utils.c: New. * common/common-utils.h: New. * common/linux-osdata.c: New. * common/linux-osdata.h: New. * config/alpha/alpha-linux.mh (NATDEPFILES): Add linux-osdata.o. * config/arm/linux.mh (NATDEPFILES): Ditto. * config/i386/linux.mh (NATDEPFILES): Ditto. * config/i386/linux64.mh (NATDEPFILES): Ditto. * config/ia64/linux.mh (NATDEPFILES): Ditto. * config/m32r/linux.mh (NATDEPFILES): Ditto. * config/m68k/linux.mh (NATDEPFILES): Ditto. * config/mips/linux.mh (NATDEPFILES): Ditto. * config/pa/linux.mh (NATDEPFILES): Ditto. * config/powerpc/linux.mh (NATDEPFILES): Ditto. * config/powerpc/ppc64-linux.mh (NATDEPFILES): Ditto. * config/s390/s390.mh (NATDEPFILES): Ditto. * config/sparc/linux.mh (NATDEPFILES): Ditto. * config/sparc/linux64.mh (NATDEPFILES): Ditto. * config/xtensa/linux.mh (NATDEPFILES): Ditto. gdbserver/ * linux-low.c (compare_ints, unique, list_threads, show_process, linux_core_of_thread): Delete. (linux_target_ops): Change linux_core_of_thread to linux_common_core_of_thread. (linux_qxfer_osdata): Defer to linux_common_xfer_osdata. * utils.c (malloc_failure): Change type of argument. (xmalloc, xrealloc, xcalloc, xsnprintf): Delete. * Makefile.in (SFILES): Add common/common-utils.c, common/xml-utils.c, common/linux-osdata.c, common/ptid.c and common/buffer.c. (OBS): Add xml-utils.o, common-utils.o, ptid.o and buffer.o. (IPA_OBJS): Add common-utils-ipa.o. (ptid_h, linux_osdata_h): New macros. (server_h): Add common/common-utils.h, common/xml-utils.h, common/buffer.h, common/gdb_assert.h, common/gdb_locale.h and common/ptid.h. (common-utils-ipa.o, common-utils.o, xml-utils.o, linux-osdata.o, ptid.o, buffer.o): New rules. (linux-low.o): Add common/linux-osdata.h as a dependency. * configure.srv (srv_tgtobj): Add linux-osdata.o to Linux targets. * configure.ac: Add AC_HEADER_DIRENT check. * config.in: Regenerate. * configure: Regenerate. * remote-utils.c (xml_escape_text): Delete. (buffer_grow, buffer_free, buffer_init, buffer_finish, buffer_xml_printf): Move to common/buffer.c. * server.c (main): Remove call to initialize_inferiors. * server.h (struct ptid, ptid_t, minus_one_ptid, null_ptid, ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid, initialize_inferiors, xml_escape_text, internal_error, gdb_assert, gdb_assert_fail): Delete. (struct buffer, buffer_grow, buffer_free, buffer_init, buffer_finish, buffer_xml_printf, buffer_grow_str, buffer_grow_str0): Move to common/buffer.h. * inferiors.c (null_ptid, minus_one_ptid, ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid, initialize_inferiors): Delete. --- gdb/ChangeLog | 64 ++++ gdb/Makefile.in | 34 +- gdb/common/buffer.c | 144 ++++++++ gdb/common/buffer.h | 63 ++++ gdb/common/common-utils.c | 170 +++++++++ gdb/common/common-utils.h | 59 +++ gdb/{ => common}/gdb_assert.h | 0 gdb/{ => common}/gdb_dirent.h | 0 gdb/{ => common}/gdb_locale.h | 0 gdb/common/linux-osdata.c | 586 ++++++++++++++++++++++++++++++ gdb/common/linux-osdata.h | 29 ++ gdb/common/ptid.c | 94 +++++ gdb/common/ptid.h | 87 +++++ gdb/common/xml-utils.c | 91 +++++ gdb/common/xml-utils.h | 29 ++ gdb/config/alpha/alpha-linux.mh | 2 +- gdb/config/arm/linux.mh | 3 +- gdb/config/i386/linux.mh | 2 +- gdb/config/i386/linux64.mh | 3 +- gdb/config/ia64/linux.mh | 3 +- gdb/config/m32r/linux.mh | 2 +- gdb/config/m68k/linux.mh | 3 +- gdb/config/mips/linux.mh | 2 +- gdb/config/pa/linux.mh | 4 +- gdb/config/powerpc/linux.mh | 2 +- gdb/config/powerpc/ppc64-linux.mh | 2 +- gdb/config/s390/s390.mh | 3 +- gdb/config/sparc/linux.mh | 2 +- gdb/config/sparc/linux64.mh | 2 +- gdb/config/xtensa/linux.mh | 3 +- gdb/defs.h | 70 +--- gdb/gdbserver/ChangeLog | 39 ++ gdb/gdbserver/Makefile.in | 35 +- gdb/gdbserver/config.in | 15 + gdb/gdbserver/configure | 159 ++++++++ gdb/gdbserver/configure.ac | 1 + gdb/gdbserver/configure.srv | 32 +- gdb/gdbserver/inferiors.c | 82 ----- gdb/gdbserver/linux-low.c | 316 +--------------- gdb/gdbserver/remote-utils.c | 164 --------- gdb/gdbserver/server.c | 1 - gdb/gdbserver/server.h | 136 +------ gdb/gdbserver/utils.c | 77 +--- gdb/inferior.h | 32 +- gdb/infrun.c | 73 ---- gdb/linux-nat.c | 142 +------- gdb/utils.c | 146 +------- gdb/xml-support.c | 66 +--- gdb/xml-support.h | 6 +- 49 files changed, 1759 insertions(+), 1321 deletions(-) create mode 100644 gdb/common/buffer.c create mode 100644 gdb/common/buffer.h create mode 100644 gdb/common/common-utils.c create mode 100644 gdb/common/common-utils.h rename gdb/{ => common}/gdb_assert.h (100%) rename gdb/{ => common}/gdb_dirent.h (100%) rename gdb/{ => common}/gdb_locale.h (100%) create mode 100644 gdb/common/linux-osdata.c create mode 100644 gdb/common/linux-osdata.h create mode 100644 gdb/common/ptid.c create mode 100644 gdb/common/ptid.h create mode 100644 gdb/common/xml-utils.c create mode 100644 gdb/common/xml-utils.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index a75f83191ed..14e2a7f8f7a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,67 @@ +2011-07-22 Kwok Cheung Yeung + + * defs.h: Add guard against inclusion in gdbserver. + (struct ptid, ptid_t): Move to common/ptid.h. + (xfree, xzalloc, xasprintf, xvasprintf, xstrprintf, xstrvprintf, + xsnprintf, internal_error): Move to common/common-utils.h. + (nomem): Delete. + * gdb_assert.h: Move into common/ sub-directory. + * gdb_locale.h: Ditto. + * gdb_dirent.h: Ditto. + * inferior.h (minus_one_ptid, null_ptid, ptid_build, pid_to_ptid, + ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid): + Move into common/ptid.h. + * xml-support.c (xml_escape_text): Move into common/xml-utils.c. + (gdb_xml_create_parser_and_cleanup_1, xml_fetch_context_from_file): + Change nomem to malloc_failure. + * xml-support.h (xml_escape_text): Move into common/xml-utils.h. + * utils.c (nomem): Rename to malloc_failure. + (xmalloc, xzalloc, xrealloc, xcalloc, xfree, xstrprintf, xasprintf, + xvasprintf, xstrvprintf, xsnprintf): Move to common/common-utils.c. + (gdb_buildargv): Change nomem to malloc_failure. + * infrun.c (null_ptid, minus_one_ptid, ptid_build, pid_to_ptid, + ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, + ptid_is_pid): Move into common/ptid.c. + (initialize_infrun): Delete initialization of null_ptid and + minus_one_ptid. + * linux-nat.c (linux_nat_xfer_osdata): Defer to + linux_common_xfer_osdata. + * Makefile.in (SFILES): Add common/common-utils.c, common/xml-utils.c, + common/ptid.c and common/buffer.c. + (HFILES_NO_SRCDIR): Add common/common-utils.h, common/xml-utils.h, + common/ptid.h, common/buffer.h and common/linux-osdata.h. + (COMMON_OBS): Add xml-utils.o, common-utils.o, buffer.o and ptid.o. + (common-utils.o, xml-utils.o, ptid.o, buffer.o, linux-osdata.o): New + rules. + * common/gdb_assert.h: New. + * common/gdb_dirent.h: New. + * common/gdb_locale.h: New. + * common/buffer.c: New. + * common/buffer.h: New. + * common/ptid.c: New. + * common/ptid.h: New. + * common/xml-utils.c: New. + * common/xml-utils.h: New. + * common/common-utils.c: New. + * common/common-utils.h: New. + * common/linux-osdata.c: New. + * common/linux-osdata.h: New. + * config/alpha/alpha-linux.mh (NATDEPFILES): Add linux-osdata.o. + * config/arm/linux.mh (NATDEPFILES): Ditto. + * config/i386/linux.mh (NATDEPFILES): Ditto. + * config/i386/linux64.mh (NATDEPFILES): Ditto. + * config/ia64/linux.mh (NATDEPFILES): Ditto. + * config/m32r/linux.mh (NATDEPFILES): Ditto. + * config/m68k/linux.mh (NATDEPFILES): Ditto. + * config/mips/linux.mh (NATDEPFILES): Ditto. + * config/pa/linux.mh (NATDEPFILES): Ditto. + * config/powerpc/linux.mh (NATDEPFILES): Ditto. + * config/powerpc/ppc64-linux.mh (NATDEPFILES): Ditto. + * config/s390/s390.mh (NATDEPFILES): Ditto. + * config/sparc/linux.mh (NATDEPFILES): Ditto. + * config/sparc/linux64.mh (NATDEPFILES): Ditto. + * config/xtensa/linux.mh (NATDEPFILES): Ditto. + 2011-07-21 Matt Rice * NEWS: Add info macros and info definitions commands. diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 494f24f449e..46593e3745f 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -737,7 +737,9 @@ SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \ jit.c \ xml-syscall.c \ annotate.c common/signals.c copying.c dfp.c gdb.c inf-child.c \ - regset.c sol-thread.c windows-termcap.c + regset.c sol-thread.c windows-termcap.c \ + common/common-utils.c common/xml-utils.c \ + common/ptid.c common/buffer.c LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c @@ -816,7 +818,9 @@ osdata.h procfs.h python/py-event.h python/py-events.h python/py-stopevent.h \ python/python-internal.h python/python.h ravenscar-thread.h record.h \ solib-darwin.h solib-ia64-hpux.h solib-spu.h windows-nat.h xcoffread.h \ gnulib/extra/arg-nonnull.h gnulib/extra/c++defs.h gnulib/extra/warn-on-use.h \ -gnulib/stddef.in.h inline-frame.h +gnulib/stddef.in.h inline-frame.h \ +common/common-utils.h common/xml-utils.h common/buffer.h common/ptid.h \ +common/linux-osdata.h # Header files that already have srcdir in them, or which are in objdir. @@ -898,10 +902,12 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ trad-frame.o \ tramp-frame.o \ solib.o solib-target.o \ - prologue-value.o memory-map.o memrange.o xml-support.o xml-syscall.o \ + prologue-value.o memory-map.o memrange.o \ + xml-support.o xml-syscall.o xml-utils.o \ target-descriptions.o target-memory.o xml-tdesc.o xml-builtin.o \ inferior.o osdata.o gdb_usleep.o record.o gcore.o \ - jit.o progspace.o + jit.o progspace.o \ + common-utils.o buffer.o ptid.o TSOBS = inflow.o @@ -1933,6 +1939,26 @@ signals.o: $(srcdir)/common/signals.c $(COMPILE) $(srcdir)/common/signals.c $(POSTCOMPILE) +common-utils.o: ${srcdir}/common/common-utils.c + $(COMPILE) $(srcdir)/common/common-utils.c + $(POSTCOMPILE) + +xml-utils.o: ${srcdir}/common/xml-utils.c + $(COMPILE) $(srcdir)/common/xml-utils.c + $(POSTCOMPILE) + +ptid.o: ${srcdir}/common/ptid.c + $(COMPILE) $(srcdir)/common/ptid.c + $(POSTCOMPILE) + +buffer.o: ${srcdir}/common/buffer.c + $(COMPILE) $(srcdir)/common/buffer.c + $(POSTCOMPILE) + +linux-osdata.o: ${srcdir}/common/linux-osdata.c + $(COMPILE) $(srcdir)/common/linux-osdata.c + $(POSTCOMPILE) + # # gdb/tui/ dependencies # diff --git a/gdb/common/buffer.c b/gdb/common/buffer.c new file mode 100644 index 00000000000..4ada0bc2d12 --- /dev/null +++ b/gdb/common/buffer.c @@ -0,0 +1,144 @@ +/* A simple growing buffer for GDB. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "xml-utils.h" +#include "buffer.h" + +#include +#include +#include + +void +buffer_grow (struct buffer *buffer, const char *data, size_t size) +{ + char *new_buffer; + size_t new_buffer_size; + + if (size == 0) + return; + + new_buffer_size = buffer->buffer_size; + + if (new_buffer_size == 0) + new_buffer_size = 1; + + while (buffer->used_size + size > new_buffer_size) + new_buffer_size *= 2; + new_buffer = xrealloc (buffer->buffer, new_buffer_size); + if (!new_buffer) + abort (); + memcpy (new_buffer + buffer->used_size, data, size); + buffer->buffer = new_buffer; + buffer->buffer_size = new_buffer_size; + buffer->used_size += size; +} + +void +buffer_free (struct buffer *buffer) +{ + if (!buffer) + return; + + xfree (buffer->buffer); + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->used_size = 0; +} + +void +buffer_init (struct buffer *buffer) +{ + memset (buffer, 0, sizeof (*buffer)); +} + +char* +buffer_finish (struct buffer *buffer) +{ + char *ret = buffer->buffer; + buffer->buffer = NULL; + buffer->buffer_size = 0; + buffer->used_size = 0; + return ret; +} + +void +buffer_xml_printf (struct buffer *buffer, const char *format, ...) +{ + va_list ap; + const char *f; + const char *prev; + int percent = 0; + + va_start (ap, format); + + prev = format; + for (f = format; *f; f++) + { + if (percent) + { + char buf[32]; + char *p; + char *str = buf; + + switch (*f) + { + case 's': + str = va_arg (ap, char *); + break; + case 'd': + sprintf (str, "%d", va_arg (ap, int)); + break; + case 'u': + sprintf (str, "%u", va_arg (ap, unsigned int)); + break; + case 'x': + sprintf (str, "%x", va_arg (ap, unsigned int)); + break; + case 'o': + sprintf (str, "%o", va_arg (ap, unsigned int)); + break; + default: + str = 0; + break; + } + + if (str) + { + buffer_grow (buffer, prev, f - prev - 1); + p = xml_escape_text (str); + buffer_grow_str (buffer, p); + xfree (p); + prev = f + 1; + } + percent = 0; + } + else if (*f == '%') + percent = 1; + } + + buffer_grow_str (buffer, prev); + va_end (ap); +} + diff --git a/gdb/common/buffer.h b/gdb/common/buffer.h new file mode 100644 index 00000000000..84a9caab734 --- /dev/null +++ b/gdb/common/buffer.h @@ -0,0 +1,63 @@ +/* A simple growing buffer for GDB. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef BUFFER_H +#define BUFFER_H + +#include +#include +#include "ansidecl.h" + +struct buffer +{ + char *buffer; + size_t buffer_size; /* allocated size */ + size_t used_size; /* actually used size */ +}; + +/* Append DATA of size SIZE to the end of BUFFER. Grows the buffer to + accommodate the new data. */ +void buffer_grow (struct buffer *buffer, const char *data, size_t size); + +/* Release any memory held by BUFFER. */ +void buffer_free (struct buffer *buffer); + +/* Initialize BUFFER. BUFFER holds no memory afterwards. */ +void buffer_init (struct buffer *buffer); + +/* Return a pointer into BUFFER data, effectivelly transfering + ownership of the buffer memory to the caller. Calling buffer_free + afterwards has no effect on the returned data. */ +char* buffer_finish (struct buffer *buffer); + +/* Simple printf to buffer function. Current implemented formatters: + %s - grow an xml escaped text in BUFFER. + %d - grow an signed integer in BUFFER. + %u - grow an unsigned integer in BUFFER. + %x - grow an unsigned integer formatted in hexadecimal in BUFFER. + %o - grow an unsigned integer formatted in octal in BUFFER. */ +void buffer_xml_printf (struct buffer *buffer, const char *format, ...) + ATTRIBUTE_PRINTF (2, 3); + +#define buffer_grow_str(BUFFER,STRING) \ + buffer_grow (BUFFER, STRING, strlen (STRING)) +#define buffer_grow_str0(BUFFER,STRING) \ + buffer_grow (BUFFER, STRING, strlen (STRING) + 1) + +#endif diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c new file mode 100644 index 00000000000..198b21c76b2 --- /dev/null +++ b/gdb/common/common-utils.c @@ -0,0 +1,170 @@ +/* Shared general utility routines for GDB, the GNU debugger. + + Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "gdb_assert.h" + +#include +#include + +/* The xmalloc() (libiberty.h) family of memory management routines. + + These are like the ISO-C malloc() family except that they implement + consistent semantics and guard against typical memory management + problems. */ + +/* NOTE: These are declared using PTR to ensure consistency with + "libiberty.h". xfree() is GDB local. */ + +PTR /* ARI: PTR */ +xmalloc (size_t size) +{ + void *val; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (size == 0) + size = 1; + + val = malloc (size); /* ARI: malloc */ + if (val == NULL) + malloc_failure (size); + + return val; +} + +PTR /* ARI: PTR */ +xrealloc (PTR ptr, size_t size) /* ARI: PTR */ +{ + void *val; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (size == 0) + size = 1; + + if (ptr != NULL) + val = realloc (ptr, size); /* ARI: realloc */ + else + val = malloc (size); /* ARI: malloc */ + if (val == NULL) + malloc_failure (size); + + return val; +} + +PTR /* ARI: PTR */ +xcalloc (size_t number, size_t size) +{ + void *mem; + + /* See libiberty/xmalloc.c. This function need's to match that's + semantics. It never returns NULL. */ + if (number == 0 || size == 0) + { + number = 1; + size = 1; + } + + mem = calloc (number, size); /* ARI: xcalloc */ + if (mem == NULL) + malloc_failure (number * size); + + return mem; +} + +void * +xzalloc (size_t size) +{ + return xcalloc (1, size); +} + +void +xfree (void *ptr) +{ + if (ptr != NULL) + free (ptr); /* ARI: free */ +} + +/* Like asprintf/vasprintf but get an internal_error if the call + fails. */ + +char * +xstrprintf (const char *format, ...) +{ + char *ret; + va_list args; + + va_start (args, format); + ret = xstrvprintf (format, args); + va_end (args); + return ret; +} + +char * +xstrvprintf (const char *format, va_list ap) +{ + char *ret = NULL; + int status = vasprintf (&ret, format, ap); + + /* NULL is returned when there was a memory allocation problem, or + any other error (for instance, a bad format string). A negative + status (the printed length) with a non-NULL buffer should never + happen, but just to be sure. */ + if (ret == NULL || status < 0) + internal_error (__FILE__, __LINE__, _("vasprintf call failed")); + return ret; +} + +void +xasprintf (char **ret, const char *format, ...) +{ + va_list args; + + va_start (args, format); + (*ret) = xstrvprintf (format, args); + va_end (args); +} + +void +xvasprintf (char **ret, const char *format, va_list ap) +{ + (*ret) = xstrvprintf (format, ap); +} + +int +xsnprintf (char *str, size_t size, const char *format, ...) +{ + va_list args; + int ret; + + va_start (args, format); + ret = vsnprintf (str, size, format, args); + gdb_assert (ret < size); + va_end (args); + + return ret; +} diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h new file mode 100644 index 00000000000..a49e201dd87 --- /dev/null +++ b/gdb/common/common-utils.h @@ -0,0 +1,59 @@ +/* Shared general utility routines for GDB, the GNU debugger. + + Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef COMMON_UTILS_H +#define COMMON_UTILS_H + +#include "config.h" +#include "ansidecl.h" +#include +#include + +extern void malloc_failure (long size) ATTRIBUTE_NORETURN; +extern void internal_error (const char *file, int line, const char *, ...) + ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 4); + +/* xmalloc(), xrealloc() and xcalloc() have already been declared in + "libiberty.h". */ + +/* Like xmalloc, but zero the memory. */ +void *xzalloc (size_t); + +void xfree (void *); + +/* Like asprintf and vasprintf, but return the string, throw an error + if no memory. */ +char *xstrprintf (const char *format, ...) ATTRIBUTE_PRINTF (1, 2); +char *xstrvprintf (const char *format, va_list ap) + ATTRIBUTE_PRINTF (1, 0); + +/* Like asprintf/vasprintf but get an internal_error if the call + fails. */ +void xasprintf (char **ret, const char *format, ...) + ATTRIBUTE_PRINTF (2, 3); +void xvasprintf (char **ret, const char *format, va_list ap) + ATTRIBUTE_PRINTF (2, 0); + +/* Like snprintf, but throw an error if the output buffer is too small. */ +int xsnprintf (char *str, size_t size, const char *format, ...) + ATTRIBUTE_PRINTF (3, 4); + +#endif diff --git a/gdb/gdb_assert.h b/gdb/common/gdb_assert.h similarity index 100% rename from gdb/gdb_assert.h rename to gdb/common/gdb_assert.h diff --git a/gdb/gdb_dirent.h b/gdb/common/gdb_dirent.h similarity index 100% rename from gdb/gdb_dirent.h rename to gdb/common/gdb_dirent.h diff --git a/gdb/gdb_locale.h b/gdb/common/gdb_locale.h similarity index 100% rename from gdb/gdb_locale.h rename to gdb/common/gdb_locale.h diff --git a/gdb/common/linux-osdata.c b/gdb/common/linux-osdata.c new file mode 100644 index 00000000000..78659d4d947 --- /dev/null +++ b/gdb/common/linux-osdata.c @@ -0,0 +1,586 @@ +/* Linux-specific functions to retrieve OS data. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "linux-osdata.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xml-utils.h" +#include "buffer.h" +#include "gdb_assert.h" +#include "gdb_dirent.h" + +int +linux_common_core_of_thread (ptid_t ptid) +{ + char filename[sizeof ("/proc//task//stat") + + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */ + + 1]; + FILE *f; + char *content = NULL; + char *p; + char *ts = 0; + int content_read = 0; + int i; + int core; + + sprintf (filename, "/proc/%d/task/%ld/stat", + ptid_get_pid (ptid), ptid_get_lwp (ptid)); + f = fopen (filename, "r"); + if (!f) + return -1; + + for (;;) + { + int n; + content = xrealloc (content, content_read + 1024); + n = fread (content + content_read, 1, 1024, f); + content_read += n; + if (n < 1024) + { + content[content_read] = '\0'; + break; + } + } + + p = strchr (content, '('); + + /* Skip ")". */ + if (p != NULL) + p = strchr (p, ')'); + if (p != NULL) + p++; + + /* If the first field after program name has index 0, then core number is + the field with index 36. There's no constant for that anywhere. */ + if (p != NULL) + p = strtok_r (p, " ", &ts); + for (i = 0; p != NULL && i != 36; ++i) + p = strtok_r (NULL, " ", &ts); + + if (p == NULL || sscanf (p, "%d", &core) == 0) + core = -1; + + xfree (content); + fclose (f); + + return core; +} + +static void +command_from_pid (char *command, int maxlen, pid_t pid) +{ + char *stat_path = xstrprintf ("/proc/%d/stat", pid); + FILE *fp = fopen (stat_path, "r"); + + command[0] = '\0'; + + if (fp) + { + /* sizeof (cmd) should be greater or equal to TASK_COMM_LEN (in + include/linux/sched.h in the Linux kernel sources) plus two + (for the brackets). */ + char cmd[32]; + pid_t stat_pid; + int items_read = fscanf (fp, "%d %32s", &stat_pid, cmd); + + if (items_read == 2 && pid == stat_pid) + { + cmd[strlen (cmd) - 1] = '\0'; /* Remove trailing parenthesis. */ + strncpy (command, cmd + 1, maxlen); /* Ignore leading parenthesis. */ + } + + fclose (fp); + } + else + { + /* Return the PID if a /proc entry for the process cannot be found. */ + snprintf (command, maxlen, "%d", pid); + } + + command[maxlen - 1] = '\0'; /* Ensure string is null-terminated. */ + + xfree (stat_path); +} + +/* Returns the command-line of the process with the given PID. The returned + string needs to be freed using xfree after use. */ + +static char * +commandline_from_pid (pid_t pid) +{ + char *pathname = xstrprintf ("/proc/%d/cmdline", pid); + char *commandline = NULL; + FILE *f = fopen (pathname, "r"); + + if (f) + { + size_t len = 0; + + while (!feof (f)) + { + char buf[1024]; + size_t read_bytes = fread (buf, 1, sizeof (buf), f); + + if (read_bytes) + { + commandline = (char *) xrealloc (commandline, len + read_bytes + 1); + memcpy (commandline + len, buf, read_bytes); + len += read_bytes; + } + } + + fclose (f); + + if (commandline) + { + size_t i; + + /* Replace null characters with spaces. */ + for (i = 0; i < len; ++i) + if (commandline[i] == '\0') + commandline[i] = ' '; + + commandline[len] = '\0'; + } + else + { + /* Return the command in square brackets if the command-line is empty. */ + commandline = (char *) xmalloc (32); + commandline[0] = '['; + command_from_pid (commandline + 1, 31, pid); + + len = strlen (commandline); + if (len < 31) + strcat (commandline, "]"); + } + } + + xfree (pathname); + + return commandline; +} + +static void +user_from_uid (char *user, int maxlen, uid_t uid) +{ + struct passwd *pwentry = getpwuid (uid); + + if (pwentry) + { + strncpy (user, pwentry->pw_name, maxlen); + user[maxlen - 1] = '\0'; /* Ensure that the user name is null-terminated. */ + } + else + user[0] = '\0'; +} + +static int +get_process_owner (uid_t *owner, pid_t pid) +{ + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; + + sprintf (procentry, "/proc/%d", pid); + + if (stat (procentry, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + { + *owner = statbuf.st_uid; + return 0; + } + else + return -1; +} + +static int +get_number_of_cpu_cores (void) +{ + int cores = 0; + FILE *f = fopen ("/proc/cpuinfo", "r"); + + while (!feof (f)) + { + char buf[512]; + char *p = fgets (buf, sizeof (buf), f); + + if (p && strncmp (buf, "processor", 9) == 0) + ++cores; + } + + fclose (f); + + return cores; +} + +/* CORES points to an array of at least get_number_of_cpu_cores () elements. */ + +static int +get_cores_used_by_process (pid_t pid, int *cores) +{ + char taskdir[sizeof ("/proc/4294967295/task")]; + DIR *dir; + struct dirent *dp; + int task_count = 0; + + sprintf (taskdir, "/proc/%d/task", pid); + dir = opendir (taskdir); + + while ((dp = readdir (dir)) != NULL) + { + pid_t tid; + int core; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + tid = atoi (dp->d_name); + core = linux_common_core_of_thread (ptid_build (pid, tid, 0)); + + if (core >= 0) + { + ++cores[core]; + ++task_count; + } + } + + closedir (dir); + + return task_count; +} + +static LONGEST +linux_xfer_osdata_processes (gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + /* We make the process list snapshot when the object starts to be read. */ + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + DIR *dirp; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + dirp = opendir ("/proc"); + if (dirp) + { + const int num_cores = get_number_of_cpu_cores (); + struct dirent *dp; + + while ((dp = readdir (dirp)) != NULL) + { + pid_t pid; + uid_t owner; + char user[UT_NAMESIZE]; + char *command_line; + int *cores; + int task_count; + char *cores_str; + int i; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + sscanf (dp->d_name, "%d", &pid); + command_line = commandline_from_pid (pid); + + if (get_process_owner (&owner, pid) == 0) + user_from_uid (user, sizeof (user), owner); + else + strcpy (user, "?"); + + /* Find CPU cores used by the process. */ + cores = (int *) xcalloc (num_cores, sizeof (int)); + task_count = get_cores_used_by_process (pid, cores); + cores_str = (char *) xcalloc (task_count, sizeof ("4294967295") + 1); + + for (i = 0; i < num_cores && task_count > 0; ++i) + if (cores[i]) + { + char core_str[sizeof ("4294967205")]; + + sprintf (core_str, "%d", i); + strcat (cores_str, core_str); + + task_count -= cores[i]; + if (task_count > 0) + strcat (cores_str, ","); + } + + xfree (cores); + + buffer_xml_printf ( + &buffer, + "" + "%d" + "%s" + "%s" + "%s" + "", + pid, + user, + command_line ? command_line : "", + cores_str); + + xfree (command_line); + xfree (cores_str); + } + + closedir (dirp); + } + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; +} + +static LONGEST +linux_xfer_osdata_threads (gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + /* We make the process list snapshot when the object starts to be read. */ + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + DIR *dirp; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + dirp = opendir ("/proc"); + if (dirp) + { + struct dirent *dp; + + while ((dp = readdir (dirp)) != NULL) + { + struct stat statbuf; + char procentry[sizeof ("/proc/4294967295")]; + + if (!isdigit (dp->d_name[0]) + || NAMELEN (dp) > sizeof ("4294967295") - 1) + continue; + + sprintf (procentry, "/proc/%s", dp->d_name); + if (stat (procentry, &statbuf) == 0 + && S_ISDIR (statbuf.st_mode)) + { + DIR *dirp2; + char *pathname; + pid_t pid; + char command[32]; + + pathname = xstrprintf ("/proc/%s/task", dp->d_name); + + pid = atoi (dp->d_name); + command_from_pid (command, sizeof (command), pid); + + dirp2 = opendir (pathname); + + if (dirp2) + { + struct dirent *dp2; + + while ((dp2 = readdir (dirp2)) != NULL) + { + pid_t tid; + int core; + + if (!isdigit (dp2->d_name[0]) + || NAMELEN (dp2) > sizeof ("4294967295") - 1) + continue; + + tid = atoi (dp2->d_name); + core = linux_common_core_of_thread (ptid_build (pid, tid, 0)); + + buffer_xml_printf ( + &buffer, + "" + "%d" + "%s" + "%d" + "%d" + "", + pid, + command, + tid, + core); + } + + closedir (dirp2); + } + + xfree (pathname); + } + } + + closedir (dirp); + } + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; +} + +struct osdata_type { + char *type; + char *description; + LONGEST (*getter) (gdb_byte *readbuf, ULONGEST offset, LONGEST len); +} osdata_table[] = { + { "processes", "Listing of all processes", linux_xfer_osdata_processes }, + { "threads", "Listing of all threads", linux_xfer_osdata_threads }, + { NULL, NULL, NULL } +}; + +LONGEST +linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, LONGEST len) +{ + if (!annex || *annex == '\0') + { + static const char *buf; + static LONGEST len_avail = -1; + static struct buffer buffer; + + if (offset == 0) + { + int i; + + if (len_avail != -1 && len_avail != 0) + buffer_free (&buffer); + len_avail = 0; + buf = NULL; + buffer_init (&buffer); + buffer_grow_str (&buffer, "\n"); + + for (i = 0; osdata_table[i].type; ++i) + buffer_xml_printf ( + &buffer, + "" + "%s" + "%s" + "", + osdata_table[i].type, + osdata_table[i].description); + + buffer_grow_str0 (&buffer, "\n"); + buf = buffer_finish (&buffer); + len_avail = strlen (buf); + } + + if (offset >= len_avail) + { + /* Done. Get rid of the buffer. */ + buffer_free (&buffer); + buf = NULL; + len_avail = 0; + return 0; + } + + if (len > len_avail - offset) + len = len_avail - offset; + memcpy (readbuf, buf + offset, len); + + return len; + } + else + { + int i; + + for (i = 0; osdata_table[i].type; ++i) + { + if (strcmp (annex, osdata_table[i].type) == 0) + { + gdb_assert (readbuf); + + return (osdata_table[i].getter) (readbuf, offset, len); + } + } + + return 0; + } +} + diff --git a/gdb/common/linux-osdata.h b/gdb/common/linux-osdata.h new file mode 100644 index 00000000000..b8bac53995b --- /dev/null +++ b/gdb/common/linux-osdata.h @@ -0,0 +1,29 @@ +/* Linux-specific functions to retrieve OS data. + + Copyright (C) 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef COMMON_LINUX_OSDATA_H +#define COMMON_LINUX_OSDATA_H + +#include "ptid.h" + +extern int linux_common_core_of_thread (ptid_t ptid); +extern LONGEST linux_common_xfer_osdata (const char *annex, gdb_byte *readbuf, + ULONGEST offset, LONGEST len); + +#endif diff --git a/gdb/common/ptid.c b/gdb/common/ptid.c new file mode 100644 index 00000000000..389d2b34d7f --- /dev/null +++ b/gdb/common/ptid.c @@ -0,0 +1,94 @@ +/* The ptid_t type and common functions operating on it. + + Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "ptid.h" + +/* Oft used ptids */ +ptid_t null_ptid = { 0, 0, 0 }; +ptid_t minus_one_ptid = { -1, 0, 0 }; + +/* Create a ptid given the necessary PID, LWP, and TID components. */ + +ptid_t +ptid_build (int pid, long lwp, long tid) +{ + ptid_t ptid; + + ptid.pid = pid; + ptid.lwp = lwp; + ptid.tid = tid; + return ptid; +} + +/* Create a ptid from just a pid. */ + +ptid_t +pid_to_ptid (int pid) +{ + return ptid_build (pid, 0, 0); +} + +/* Fetch the pid (process id) component from a ptid. */ + +int +ptid_get_pid (ptid_t ptid) +{ + return ptid.pid; +} + +/* Fetch the lwp (lightweight process) component from a ptid. */ + +long +ptid_get_lwp (ptid_t ptid) +{ + return ptid.lwp; +} + +/* Fetch the tid (thread id) component from a ptid. */ + +long +ptid_get_tid (ptid_t ptid) +{ + return ptid.tid; +} + +/* ptid_equal() is used to test equality of two ptids. */ + +int +ptid_equal (ptid_t ptid1, ptid_t ptid2) +{ + return (ptid1.pid == ptid2.pid + && ptid1.lwp == ptid2.lwp + && ptid1.tid == ptid2.tid); +} + +/* Returns true if PTID represents a process. */ + +int +ptid_is_pid (ptid_t ptid) +{ + if (ptid_equal (minus_one_ptid, ptid)) + return 0; + if (ptid_equal (null_ptid, ptid)) + return 0; + + return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0); +} diff --git a/gdb/common/ptid.h b/gdb/common/ptid.h new file mode 100644 index 00000000000..e750a81bc1d --- /dev/null +++ b/gdb/common/ptid.h @@ -0,0 +1,87 @@ +/* The ptid_t type and common functions operating on it. + + Copyright (C) 1986, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, + 2009, 2010, 2011 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef PTID_H +#define PTID_H + +/* The ptid struct is a collection of the various "ids" necessary + for identifying the inferior. This consists of the process id + (pid), thread id (tid), and other fields necessary for uniquely + identifying the inferior process/thread being debugged. When + manipulating ptids, the constructors, accessors, and predicate + declared in server.h should be used. These are as follows: + + ptid_build - Make a new ptid from a pid, lwp, and tid. + pid_to_ptid - Make a new ptid from just a pid. + ptid_get_pid - Fetch the pid component of a ptid. + ptid_get_lwp - Fetch the lwp component of a ptid. + ptid_get_tid - Fetch the tid component of a ptid. + ptid_equal - Test to see if two ptids are equal. + + Please do NOT access the struct ptid members directly (except, of + course, in the implementation of the above ptid manipulation + functions). */ + +struct ptid + { + /* Process id */ + int pid; + + /* Lightweight process id */ + long lwp; + + /* Thread id */ + long tid; + }; + +typedef struct ptid ptid_t; + +/* The null or zero ptid, often used to indicate no process. */ +extern ptid_t null_ptid; + +/* The -1 ptid, often used to indicate either an error condition + or a "don't care" condition, i.e, "run all threads." */ +extern ptid_t minus_one_ptid; + +/* Attempt to find and return an existing ptid with the given PID, LWP, + and TID components. If none exists, create a new one and return + that. */ +ptid_t ptid_build (int pid, long lwp, long tid); + +/* Find/Create a ptid from just a pid. */ +ptid_t pid_to_ptid (int pid); + +/* Fetch the pid (process id) component from a ptid. */ +int ptid_get_pid (ptid_t ptid); + +/* Fetch the lwp (lightweight process) component from a ptid. */ +long ptid_get_lwp (ptid_t ptid); + +/* Fetch the tid (thread id) component from a ptid. */ +long ptid_get_tid (ptid_t ptid); + +/* Compare two ptids to see if they are equal */ +int ptid_equal (ptid_t p1, ptid_t p2); + +/* Return true if PTID represents a process id. */ +int ptid_is_pid (ptid_t ptid); + +#endif diff --git a/gdb/common/xml-utils.c b/gdb/common/xml-utils.c new file mode 100644 index 00000000000..1d0057fb7df --- /dev/null +++ b/gdb/common/xml-utils.c @@ -0,0 +1,91 @@ +/* Shared helper routines for manipulating XML. + + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifdef GDBSERVER +#include "server.h" +#else +#include "defs.h" +#endif + +#include "xml-utils.h" + +#include + +/* Return a malloc allocated string with special characters from TEXT + replaced by entity references. */ + +char * +xml_escape_text (const char *text) +{ + char *result; + int i, special; + + /* Compute the length of the result. */ + for (i = 0, special = 0; text[i] != '\0'; i++) + switch (text[i]) + { + case '\'': + case '\"': + special += 5; + break; + case '&': + special += 4; + break; + case '<': + case '>': + special += 3; + break; + default: + break; + } + + /* Expand the result. */ + result = xmalloc (i + special + 1); + for (i = 0, special = 0; text[i] != '\0'; i++) + switch (text[i]) + { + case '\'': + strcpy (result + i + special, "'"); + special += 5; + break; + case '\"': + strcpy (result + i + special, """); + special += 5; + break; + case '&': + strcpy (result + i + special, "&"); + special += 4; + break; + case '<': + strcpy (result + i + special, "<"); + special += 3; + break; + case '>': + strcpy (result + i + special, ">"); + special += 3; + break; + default: + result[i + special] = text[i]; + break; + } + result[i + special] = '\0'; + + return result; +} diff --git a/gdb/common/xml-utils.h b/gdb/common/xml-utils.h new file mode 100644 index 00000000000..f4d903ee7e9 --- /dev/null +++ b/gdb/common/xml-utils.h @@ -0,0 +1,29 @@ +/* Shared helper routines for manipulating XML. + + Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef XML_UTILS_H +#define XML_UTILS_H + +/* Return a malloc allocated string with special characters from TEXT + replaced by entity references. */ + +extern char *xml_escape_text (const char *text); + +#endif diff --git a/gdb/config/alpha/alpha-linux.mh b/gdb/config/alpha/alpha-linux.mh index 5074f1e0fb9..1a6949d8bb0 100644 --- a/gdb/config/alpha/alpha-linux.mh +++ b/gdb/config/alpha/alpha-linux.mh @@ -2,7 +2,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o corelow.o alpha-linux-nat.o \ fork-child.o proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The dynamically loaded libthread_db needs access to symbols in the diff --git a/gdb/config/arm/linux.mh b/gdb/config/arm/linux.mh index aa6d08ab22e..c5e93f3cbc6 100644 --- a/gdb/config/arm/linux.mh +++ b/gdb/config/arm/linux.mh @@ -2,7 +2,8 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o arm-linux-nat.o \ - proc-service.o linux-thread-db.o linux-nat.o linux-fork.o + proc-service.o linux-thread-db.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES= -ldl $(RDYNAMIC) diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh index 5590f578771..3d7745bb5d0 100644 --- a/gdb/config/i386/linux.mh +++ b/gdb/config/i386/linux.mh @@ -4,7 +4,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ i386-nat.o i386-linux-nat.o \ proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The dynamically loaded libthread_db needs access to symbols in the diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh index 3e593009946..c826dc9ab67 100644 --- a/gdb/config/i386/linux64.mh +++ b/gdb/config/i386/linux64.mh @@ -1,6 +1,7 @@ # Host: GNU/Linux x86-64 NATDEPFILES= inf-ptrace.o fork-child.o \ - i386-nat.o amd64-nat.o amd64-linux-nat.o linux-nat.o \ + i386-nat.o amd64-nat.o amd64-linux-nat.o \ + linux-nat.o linux-osdata.o \ proc-service.o linux-thread-db.o linux-fork.o NAT_FILE= config/nm-linux.h NAT_CDEPS = $(srcdir)/proc-service.list diff --git a/gdb/config/ia64/linux.mh b/gdb/config/ia64/linux.mh index a069b5b0a21..df45b974392 100644 --- a/gdb/config/ia64/linux.mh +++ b/gdb/config/ia64/linux.mh @@ -3,7 +3,8 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \ core-regset.o ia64-linux-nat.o \ - proc-service.o linux-thread-db.o linux-nat.o linux-fork.o + proc-service.o linux-thread-db.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/config/m32r/linux.mh b/gdb/config/m32r/linux.mh index b3f1c5f447d..241520d198f 100644 --- a/gdb/config/m32r/linux.mh +++ b/gdb/config/m32r/linux.mh @@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \ m32r-linux-nat.o proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES= -ldl $(RDYNAMIC) diff --git a/gdb/config/m68k/linux.mh b/gdb/config/m68k/linux.mh index 4a95208301c..b54921c533e 100644 --- a/gdb/config/m68k/linux.mh +++ b/gdb/config/m68k/linux.mh @@ -3,7 +3,8 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ corelow.o m68klinux-nat.o \ - proc-service.o linux-thread-db.o linux-nat.o linux-fork.o + proc-service.o linux-thread-db.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The dynamically loaded libthread_db needs access to symbols in the diff --git a/gdb/config/mips/linux.mh b/gdb/config/mips/linux.mh index 5e9dbb66858..4f735ba6e43 100644 --- a/gdb/config/mips/linux.mh +++ b/gdb/config/mips/linux.mh @@ -2,7 +2,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o mips-linux-nat.o \ linux-thread-db.o proc-service.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/config/pa/linux.mh b/gdb/config/pa/linux.mh index 293964fba26..e49c91e2233 100644 --- a/gdb/config/pa/linux.mh +++ b/gdb/config/pa/linux.mh @@ -1,8 +1,8 @@ # Host: Hewlett-Packard PA-RISC machine, running Linux NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o corelow.o \ - hppa-linux-nat.o proc-service.o linux-thread-db.o linux-nat.o \ - linux-fork.o + hppa-linux-nat.o proc-service.o linux-thread-db.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/config/powerpc/linux.mh b/gdb/config/powerpc/linux.mh index 501f2d670a8..49fac1d5c12 100644 --- a/gdb/config/powerpc/linux.mh +++ b/gdb/config/powerpc/linux.mh @@ -5,7 +5,7 @@ XM_CLIBS= NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ ppc-linux-nat.o proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/config/powerpc/ppc64-linux.mh b/gdb/config/powerpc/ppc64-linux.mh index 5675fdca378..c822e83e731 100644 --- a/gdb/config/powerpc/ppc64-linux.mh +++ b/gdb/config/powerpc/ppc64-linux.mh @@ -5,7 +5,7 @@ XM_CLIBS= NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o \ ppc-linux-nat.o proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The PowerPC has severe limitations on TOC size, and uses them even diff --git a/gdb/config/s390/s390.mh b/gdb/config/s390/s390.mh index 9e62904efff..499203503ff 100644 --- a/gdb/config/s390/s390.mh +++ b/gdb/config/s390/s390.mh @@ -1,6 +1,7 @@ # Host: S390, running Linux NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o corelow.o s390-nat.o \ - linux-thread-db.o proc-service.o linux-nat.o linux-fork.o + linux-thread-db.o proc-service.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/config/sparc/linux.mh b/gdb/config/sparc/linux.mh index 32d1b6abb54..fe8e1e71285 100644 --- a/gdb/config/sparc/linux.mh +++ b/gdb/config/sparc/linux.mh @@ -3,7 +3,7 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= sparc-nat.o sparc-linux-nat.o \ corelow.o core-regset.o fork-child.o inf-ptrace.o \ proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The dynamically loaded libthread_db needs access to symbols in the diff --git a/gdb/config/sparc/linux64.mh b/gdb/config/sparc/linux64.mh index b54c3b76cba..639e3d0150e 100644 --- a/gdb/config/sparc/linux64.mh +++ b/gdb/config/sparc/linux64.mh @@ -4,7 +4,7 @@ NATDEPFILES= sparc-nat.o sparc64-nat.o sparc64-linux-nat.o \ corelow.o core-regset.o \ fork-child.o inf-ptrace.o \ proc-service.o linux-thread-db.o \ - linux-nat.o linux-fork.o + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list # The dynamically loaded libthread_db needs access to symbols in the diff --git a/gdb/config/xtensa/linux.mh b/gdb/config/xtensa/linux.mh index c83eac0e162..4abd242f004 100644 --- a/gdb/config/xtensa/linux.mh +++ b/gdb/config/xtensa/linux.mh @@ -3,7 +3,8 @@ NAT_FILE= config/nm-linux.h NATDEPFILES= inf-ptrace.o fork-child.o xtensa-linux-nat.o \ - linux-thread-db.o proc-service.o linux-nat.o linux-fork.o + linux-thread-db.o proc-service.o \ + linux-nat.o linux-osdata.o linux-fork.o NAT_CDEPS = $(srcdir)/proc-service.list LOADLIBES = -ldl $(RDYNAMIC) diff --git a/gdb/defs.h b/gdb/defs.h index 71b7cd291d6..eaf9c2a5f37 100644 --- a/gdb/defs.h +++ b/gdb/defs.h @@ -23,6 +23,10 @@ #ifndef DEFS_H #define DEFS_H +#ifdef GDBSERVER +# error gdbserver should not include gdb/defs.h +#endif + #include "config.h" /* Generated by configure. */ #include @@ -142,6 +146,8 @@ typedef bfd_vma CORE_ADDR; #define max(a, b) ((a) > (b) ? (a) : (b)) #endif +#include "ptid.h" + /* Check if a character is one of the commonly used C++ marker characters. */ extern int is_cplus_marker (int); @@ -753,41 +759,6 @@ enum val_prettyprint Val_pretty_default }; -/* The ptid struct is a collection of the various "ids" necessary - for identifying the inferior. This consists of the process id - (pid), thread id (tid), and other fields necessary for uniquely - identifying the inferior process/thread being debugged. When - manipulating ptids, the constructors, accessors, and predicate - declared in inferior.h should be used. These are as follows: - - ptid_build - Make a new ptid from a pid, lwp, and tid. - pid_to_ptid - Make a new ptid from just a pid. - ptid_get_pid - Fetch the pid component of a ptid. - ptid_get_lwp - Fetch the lwp component of a ptid. - ptid_get_tid - Fetch the tid component of a ptid. - ptid_equal - Test to see if two ptids are equal. - ptid_is_pid - Test to see if this ptid represents a process id. - - Please do NOT access the struct ptid members directly (except, of - course, in the implementation of the above ptid manipulation - functions). */ - -struct ptid - { - /* Process id */ - int pid; - - /* Lightweight process id */ - long lwp; - - /* Thread id */ - long tid; - }; - -typedef struct ptid ptid_t; - - - /* Optional native machine support. Non-native (and possibly pure multi-arch) targets do not need a "nm.h" file. This will be a symlink to one of the nm-*.h files, built by the `configure' @@ -851,13 +822,6 @@ extern int longest_to_int (LONGEST); extern char *savestring (const char *, size_t); -/* xmalloc(), xrealloc() and xcalloc() have already been declared in - "libiberty.h". */ -extern void xfree (void *); - -/* Like xmalloc, but zero the memory. */ -extern void *xzalloc (size_t); - /* Utility macros to allocate typed memory. Avoids errors like: struct foo *foo = xmalloc (sizeof struct bar); and memset (foo, sizeof (struct foo), 0). */ @@ -865,22 +829,7 @@ extern void *xzalloc (size_t); #define XMALLOC(TYPE) ((TYPE*) xmalloc (sizeof (TYPE))) #define XCALLOC(NMEMB, TYPE) ((TYPE*) xcalloc ((NMEMB), sizeof (TYPE))) -/* Like asprintf/vasprintf but get an internal_error if the call - fails. */ -extern void xasprintf (char **ret, const char *format, ...) - ATTRIBUTE_PRINTF (2, 3); -extern void xvasprintf (char **ret, const char *format, va_list ap) - ATTRIBUTE_PRINTF (2, 0); - -/* Like asprintf and vasprintf, but return the string, throw an error - if no memory. */ -extern char *xstrprintf (const char *format, ...) ATTRIBUTE_PRINTF (1, 2); -extern char *xstrvprintf (const char *format, va_list ap) - ATTRIBUTE_PRINTF (1, 0); - -/* Like snprintf, but throw an error if the output buffer is too small. */ -extern int xsnprintf (char *str, size_t size, const char *format, ...) - ATTRIBUTE_PRINTF (3, 4); +#include "common-utils.h" extern int parse_escape (struct gdbarch *, char **); @@ -914,9 +863,6 @@ extern void internal_verror (const char *file, int line, const char *, va_list ap) ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 0); -extern void internal_error (const char *file, int line, const char *, ...) - ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (3, 4); - extern void internal_vwarning (const char *file, int line, const char *, va_list ap) ATTRIBUTE_PRINTF (3, 0); @@ -924,8 +870,6 @@ extern void internal_vwarning (const char *file, int line, extern void internal_warning (const char *file, int line, const char *, ...) ATTRIBUTE_PRINTF (3, 4); -extern void nomem (long) ATTRIBUTE_NORETURN; - extern void warning (const char *, ...) ATTRIBUTE_PRINTF (1, 2); extern void vwarning (const char *, va_list args) ATTRIBUTE_PRINTF (1, 0); diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 5926a790e02..d0a914faaca 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,42 @@ +2011-07-22 Kwok Cheung Yeung + + * linux-low.c (compare_ints, unique, list_threads, show_process, + linux_core_of_thread): Delete. + (linux_target_ops): Change linux_core_of_thread to + linux_common_core_of_thread. + (linux_qxfer_osdata): Defer to linux_common_xfer_osdata. + * utils.c (malloc_failure): Change type of argument. + (xmalloc, xrealloc, xcalloc, xsnprintf): Delete. + * Makefile.in (SFILES): Add common/common-utils.c, common/xml-utils.c, + common/linux-osdata.c, common/ptid.c and common/buffer.c. + (OBS): Add xml-utils.o, common-utils.o, ptid.o and buffer.o. + (IPA_OBJS): Add common-utils-ipa.o. + (ptid_h, linux_osdata_h): New macros. + (server_h): Add common/common-utils.h, common/xml-utils.h, + common/buffer.h, common/gdb_assert.h, common/gdb_locale.h and + common/ptid.h. + (common-utils-ipa.o, common-utils.o, xml-utils.o, linux-osdata.o, + ptid.o, buffer.o): New rules. + (linux-low.o): Add common/linux-osdata.h as a dependency. + * configure.srv (srv_tgtobj): Add linux-osdata.o to Linux targets. + * configure.ac: Add AC_HEADER_DIRENT check. + * config.in: Regenerate. + * configure: Regenerate. + * remote-utils.c (xml_escape_text): Delete. + (buffer_grow, buffer_free, buffer_init, buffer_finish, + buffer_xml_printf): Move to common/buffer.c. + * server.c (main): Remove call to initialize_inferiors. + * server.h (struct ptid, ptid_t, minus_one_ptid, null_ptid, + ptid_build, pid_to_ptid, ptid_get_pid, ptid_get_lwp, ptid_get_tid, + ptid_equal, ptid_is_pid, initialize_inferiors, xml_escape_text, + internal_error, gdb_assert, gdb_assert_fail): Delete. + (struct buffer, buffer_grow, buffer_free, buffer_init, buffer_finish, + buffer_xml_printf, buffer_grow_str, buffer_grow_str0): Move to + common/buffer.h. + * inferiors.c (null_ptid, minus_one_ptid, ptid_build, pid_to_ptid, + ptid_get_pid, ptid_get_lwp, ptid_get_tid, ptid_equal, ptid_is_pid, + initialize_inferiors): Delete. + 2011-07-20 Pedro Alves * tracepoint.c (tracepoint_look_up_symbols): Return upon the first diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 095c706c80b..079721d98a3 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -124,7 +124,10 @@ SFILES= $(srcdir)/gdbreplay.c $(srcdir)/inferiors.c \ $(srcdir)/linux-xtensa-low.c \ $(srcdir)/win32-arm-low.c $(srcdir)/win32-i386-low.c \ $(srcdir)/win32-low.c $(srcdir)/wincecompat.c \ - $(srcdir)/hostio.c $(srcdir)/hostio-errno.c + $(srcdir)/hostio.c $(srcdir)/hostio-errno.c \ + $(srcdir)/common/common-utils.c $(srcdir)/common/xml-utils.c \ + $(srcdir)/common/linux-osdata.c $(srcdir)/common/ptid.c \ + $(srcdir)/common/buffer.c DEPFILES = @GDBSERVER_DEPFILES@ @@ -136,6 +139,7 @@ TAGFILES = $(SOURCES) ${HFILES} ${ALLPARAM} ${POSSLIBS} OBS = inferiors.o regcache.o remote-utils.o server.o signals.o target.o \ utils.o version.o \ mem-break.o hostio.o event-loop.o tracepoint.o \ + xml-utils.o common-utils.o ptid.o buffer.o \ $(XML_BUILTIN) \ $(DEPFILES) $(LIBOBJS) GDBREPLAY_OBS = gdbreplay.o version.o @@ -234,7 +238,7 @@ gdbreplay$(EXEEXT): $(GDBREPLAY_OBS) ${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \ $(XM_CLIBS) -IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o ${IPA_DEPFILES} +IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o common-utils-ipa.o ${IPA_DEPFILES} IPA_LIB=libinproctrace.so @@ -331,8 +335,16 @@ regdef_h = $(srcdir)/../regformats/regdef.h regcache_h = $(srcdir)/regcache.h signals_def = $(srcdir)/../../include/gdb/signals.def signals_h = $(srcdir)/../../include/gdb/signals.h $(signals_def) +ptid_h = $(srcdir)/../common/ptid.h +linux_osdata_h = $(srcdir)/../common/linux-osdata.h server_h = $(srcdir)/server.h $(regcache_h) config.h $(srcdir)/target.h \ $(srcdir)/mem-break.h $(srcdir)/../common/gdb_signals.h \ + $(srcdir)/../common/common-utils.h \ + $(srcdir)/../common/xml-utils.h \ + $(srcdir)/../common/buffer.h \ + $(srcdir)/../common/gdb_assert.h \ + $(srcdir)/../common/gdb_locale.h \ + $(ptid_h) \ $(signals_h) linux_low_h = $(srcdir)/linux-low.h @@ -358,6 +370,8 @@ tracepoint-ipa.o: tracepoint.c $(server_h) $(srcdir)/../common/ax.def $(CC) -c $(IPAGENT_CFLAGS) $< -o tracepoint-ipa.o utils-ipa.o: utils.c $(server_h) $(CC) -c $(IPAGENT_CFLAGS) $< -o utils-ipa.o +common-utils-ipa.o: ../common/common-utils.c $(server_h) + $(CC) -c $(IPAGENT_CFLAGS) $< -o common-utils-ipa.o remote-utils-ipa.o: remote-utils.c $(server_h) $(CC) -c $(IPAGENT_CFLAGS) $< -o remote-utils-ipa.o regcache-ipa.o: regcache.c $(server_h) @@ -390,6 +404,21 @@ gdbreplay.o: gdbreplay.c config.h signals.o: ../common/signals.c $(server_h) $(signals_def) $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER +common-utils.o: ../common/common-utils.c $(server_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + +xml-utils.o: ../common/xml-utils.c $(server_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + +linux-osdata.o: ../common/linux-osdata.c $(server_h) $(linux_osdata_h) ../common/gdb_dirent.h + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + +ptid.o: ../common/ptid.c $(ptid_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + +buffer.o: ../common/buffer.c $(server_h) + $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< -DGDBSERVER + # We build memmem.c without -Werror because this file is not under # our control. On LynxOS, the compiler generates some warnings # because str-two-way.h uses a constant (MAX_SIZE) whose definition @@ -413,7 +442,7 @@ i386-low.o: i386-low.c $(i386_low_h) $(server_h) $(target_h) i387-fp.o: i387-fp.c $(server_h) -linux-low.o: linux-low.c $(linux_low_h) $(linux_ptrace_h) $(server_h) +linux-low.o: linux-low.c $(linux_low_h) $(linux_ptrace_h) $(server_h) $(linux_osdata_h) $(CC) -c $(CPPFLAGS) $(INTERNAL_CFLAGS) $< @USE_THREAD_DB@ linux-arm-low.o: linux-arm-low.c $(linux_low_h) $(server_h) \ diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index 909dcb969c2..65aa1ab098e 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -38,6 +38,10 @@ don't. */ #undef HAVE_DECL_VSNPRINTF +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + /* Define to 1 if you have the `dladdr' function. */ #undef HAVE_DLADDR @@ -80,6 +84,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + /* Define to 1 if you have the header file. */ #undef HAVE_NETDB_H @@ -138,12 +145,20 @@ /* Define to 1 if the target supports __sync_*_compare_and_swap */ #undef HAVE_SYNC_BUILTINS +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_FILE_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_IOCTL_H +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PROCFS_H diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index aaa73fced50..c350159e23e 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -3799,6 +3799,165 @@ $as_echo "#define STDC_HEADERS 1" >>confdefs.h fi +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +eval as_val=\$$as_ac_Header + if test "x$as_val" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then : + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if test "${ac_cv_search_opendir+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if test "${ac_cv_search_opendir+set}" = set; then : + break +fi +done +if test "${ac_cv_search_opendir+set}" = set; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works # for constant arguments. Useless! diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac index 07ac26a0000..567d3ea7e81 100644 --- a/gdb/gdbserver/configure.ac +++ b/gdb/gdbserver/configure.ac @@ -35,6 +35,7 @@ AC_PROG_INSTALL AC_ARG_PROGRAM AC_HEADER_STDC +AC_HEADER_DIRENT AC_FUNC_ALLOCA AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 55dd4cf733f..378b56ed150 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -46,7 +46,7 @@ case "${target}" in srv_regobj="${srv_regobj} arm-with-vfpv2.o" srv_regobj="${srv_regobj} arm-with-vfpv3.o" srv_regobj="${srv_regobj} arm-with-neon.o" - srv_tgtobj="linux-low.o linux-arm-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-arm-low.o" srv_xmlfiles="arm-with-iwmmxt.xml" srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml" srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv3.xml" @@ -68,17 +68,17 @@ case "${target}" in srv_mingwce=yes ;; bfin-*-*linux*) srv_regobj=reg-bfin.o - srv_tgtobj="linux-low.o linux-bfin-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-bfin-low.o" srv_linux_usrregs=yes srv_linux_thread_db=yes ;; crisv32-*-linux*) srv_regobj=reg-crisv32.o - srv_tgtobj="linux-low.o linux-crisv32-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-crisv32-low.o" srv_linux_regsets=yes srv_linux_thread_db=yes ;; cris-*-linux*) srv_regobj=reg-cris.o - srv_tgtobj="linux-low.o linux-cris-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-cris-low.o" srv_linux_usrregs=yes srv_linux_thread_db=yes ;; @@ -92,7 +92,7 @@ case "${target}" in srv_regobj="$srv_regobj $srv_amd64_linux_regobj" srv_xmlfiles="${srv_xmlfiles} $srv_amd64_linux_xmlfiles" fi - srv_tgtobj="linux-low.o linux-x86-low.o i386-low.o i387-fp.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes @@ -123,11 +123,11 @@ case "${target}" in srv_qnx="yes" ;; ia64-*-linux*) srv_regobj=reg-ia64.o - srv_tgtobj="linux-low.o linux-ia64-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-ia64-low.o" srv_linux_usrregs=yes ;; m32r*-*-linux*) srv_regobj=reg-m32r.o - srv_tgtobj="linux-low.o linux-m32r-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-m32r-low.o" srv_linux_usrregs=yes srv_linux_thread_db=yes ;; @@ -136,7 +136,7 @@ case "${target}" in else srv_regobj=reg-m68k.o fi - srv_tgtobj="linux-low.o linux-m68k-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes @@ -146,13 +146,13 @@ case "${target}" in else srv_regobj=reg-m68k.o fi - srv_tgtobj="linux-low.o linux-m68k-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes ;; mips*-*-linux*) srv_regobj="mips-linux.o mips64-linux.o" - srv_tgtobj="linux-low.o linux-mips-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o" srv_xmlfiles="mips-linux.xml" srv_xmlfiles="${srv_xmlfiles} mips-cpu.xml" srv_xmlfiles="${srv_xmlfiles} mips-cp0.xml" @@ -180,7 +180,7 @@ case "${target}" in srv_regobj="${srv_regobj} powerpc-isa205-64l.o" srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o" srv_regobj="${srv_regobj} powerpc-isa205-vsx64l.o" - srv_tgtobj="linux-low.o linux-ppc-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-ppc-low.o" srv_xmlfiles="rs6000/powerpc-32l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml" srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml" @@ -216,7 +216,7 @@ case "${target}" in s390*-*-linux*) srv_regobj="s390-linux32.o" srv_regobj="${srv_regobj} s390-linux64.o" srv_regobj="${srv_regobj} s390x-linux64.o" - srv_tgtobj="linux-low.o linux-s390-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o" srv_xmlfiles="s390-linux32.xml" srv_xmlfiles="${srv_xmlfiles} s390-linux64.xml" srv_xmlfiles="${srv_xmlfiles} s390x-linux64.xml" @@ -230,13 +230,13 @@ case "${target}" in srv_linux_thread_db=yes ;; sh*-*-linux*) srv_regobj=reg-sh.o - srv_tgtobj="linux-low.o linux-sh-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-sh-low.o" srv_linux_usrregs=yes srv_linux_regsets=yes srv_linux_thread_db=yes ;; sparc*-*-linux*) srv_regobj=reg-sparc64.o - srv_tgtobj="linux-low.o linux-sparc-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-sparc-low.o" srv_linux_regsets=yes srv_linux_thread_db=yes ;; @@ -244,7 +244,7 @@ case "${target}" in srv_tgtobj="spu-low.o" ;; x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj" - srv_tgtobj="linux-low.o linux-x86-low.o i386-low.o i387-fp.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o" srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles" srv_linux_usrregs=yes # This is for i386 progs. srv_linux_regsets=yes @@ -258,7 +258,7 @@ case "${target}" in ;; xtensa*-*-linux*) srv_regobj=reg-xtensa.o - srv_tgtobj="linux-low.o linux-xtensa-low.o" + srv_tgtobj="linux-low.o linux-osdata.o linux-xtensa-low.o" srv_linux_regsets=yes ;; *) echo "Error: target not supported by gdbserver." diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c index 2e3d1fe462a..a7e1a83927a 100644 --- a/gdb/gdbserver/inferiors.c +++ b/gdb/gdbserver/inferiors.c @@ -30,81 +30,6 @@ int dlls_changed; struct thread_info *current_inferior; - -/* Oft used ptids */ -ptid_t null_ptid; -ptid_t minus_one_ptid; - -/* Create a ptid given the necessary PID, LWP, and TID components. */ - -ptid_t -ptid_build (int pid, long lwp, long tid) -{ - ptid_t ptid; - - ptid.pid = pid; - ptid.lwp = lwp; - ptid.tid = tid; - return ptid; -} - -/* Create a ptid from just a pid. */ - -ptid_t -pid_to_ptid (int pid) -{ - return ptid_build (pid, 0, 0); -} - -/* Fetch the pid (process id) component from a ptid. */ - -int -ptid_get_pid (ptid_t ptid) -{ - return ptid.pid; -} - -/* Fetch the lwp (lightweight process) component from a ptid. */ - -long -ptid_get_lwp (ptid_t ptid) -{ - return ptid.lwp; -} - -/* Fetch the tid (thread id) component from a ptid. */ - -long -ptid_get_tid (ptid_t ptid) -{ - return ptid.tid; -} - -/* ptid_equal() is used to test equality of two ptids. */ - -int -ptid_equal (ptid_t ptid1, ptid_t ptid2) -{ - return (ptid1.pid == ptid2.pid - && ptid1.lwp == ptid2.lwp - && ptid1.tid == ptid2.tid); -} - -/* Return true if this ptid represents a process. */ - -int -ptid_is_pid (ptid_t ptid) -{ - if (ptid_equal (minus_one_ptid, ptid)) - return 0; - if (ptid_equal (null_ptid, ptid)) - return 0; - - return (ptid_get_pid (ptid) != 0 - && ptid_get_lwp (ptid) == 0 - && ptid_get_tid (ptid) == 0); -} - #define get_thread(inf) ((struct thread_info *)(inf)) #define get_dll(inf) ((struct dll_info *)(inf)) @@ -518,10 +443,3 @@ current_process (void) return get_thread_process (current_inferior); } - -void -initialize_inferiors (void) -{ - null_ptid = ptid_build (0, 0, 0); - minus_one_ptid = ptid_build (-1, 0, 0); -} diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index d84fd680b73..a9cdacac51a 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -19,6 +19,7 @@ #include "server.h" #include "linux-low.h" +#include "linux-osdata.h" #include #include @@ -118,7 +119,6 @@ static int linux_wait_for_event (ptid_t ptid, int *wstat, int options); static void *add_lwp (ptid_t ptid); static int linux_stopped_by_watchpoint (void); static void mark_lwp_dead (struct lwp_info *lwp, int wstat); -static int linux_core_of_thread (ptid_t ptid); static void proceed_all_lwps (void); static int finish_step_over (struct lwp_info *lwp); static CORE_ADDR get_stop_pc (struct lwp_info *lwp); @@ -4386,265 +4386,12 @@ linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p) } #endif -static int -compare_ints (const void *xa, const void *xb) -{ - int a = *(const int *)xa; - int b = *(const int *)xb; - - return a - b; -} - -static int * -unique (int *b, int *e) -{ - int *d = b; - while (++b != e) - if (*d != *b) - *++d = *b; - return ++d; -} - -/* Given PID, iterates over all threads in that process. - - Information about each thread, in a format suitable for qXfer:osdata:thread - is printed to BUFFER, if it's not NULL. BUFFER is assumed to be already - initialized, and the caller is responsible for finishing and appending '\0' - to it. - - The list of cores that threads are running on is assigned to *CORES, if it - is not NULL. If no cores are found, *CORES will be set to NULL. Caller - should free *CORES. */ - -static void -list_threads (int pid, struct buffer *buffer, char **cores) -{ - int count = 0; - int allocated = 10; - int *core_numbers = xmalloc (sizeof (int) * allocated); - char pathname[128]; - DIR *dir; - struct dirent *dp; - struct stat statbuf; - - sprintf (pathname, "/proc/%d/task", pid); - if (stat (pathname, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) - { - dir = opendir (pathname); - if (!dir) - { - free (core_numbers); - return; - } - - while ((dp = readdir (dir)) != NULL) - { - unsigned long lwp = strtoul (dp->d_name, NULL, 10); - - if (lwp != 0) - { - unsigned core = linux_core_of_thread (ptid_build (pid, lwp, 0)); - - if (core != -1) - { - char s[sizeof ("4294967295")]; - sprintf (s, "%u", core); - - if (count == allocated) - { - allocated *= 2; - core_numbers = realloc (core_numbers, - sizeof (int) * allocated); - } - core_numbers[count++] = core; - if (buffer) - buffer_xml_printf (buffer, - "" - "%d" - "%s" - "%s" - "", pid, dp->d_name, s); - } - else - { - if (buffer) - buffer_xml_printf (buffer, - "" - "%d" - "%s" - "", pid, dp->d_name); - } - } - } - closedir (dir); - } - - if (cores) - { - *cores = NULL; - if (count > 0) - { - struct buffer buffer2; - int *b; - int *e; - qsort (core_numbers, count, sizeof (int), compare_ints); - - /* Remove duplicates. */ - b = core_numbers; - e = unique (b, core_numbers + count); - - buffer_init (&buffer2); - - for (b = core_numbers; b != e; ++b) - { - char number[sizeof ("4294967295")]; - sprintf (number, "%u", *b); - buffer_xml_printf (&buffer2, "%s%s", - (b == core_numbers) ? "" : ",", number); - } - buffer_grow_str0 (&buffer2, ""); - - *cores = buffer_finish (&buffer2); - } - } - free (core_numbers); -} - -static void -show_process (int pid, const char *username, struct buffer *buffer) -{ - char pathname[128]; - FILE *f; - char cmd[MAXPATHLEN + 1]; - - sprintf (pathname, "/proc/%d/cmdline", pid); - - if ((f = fopen (pathname, "r")) != NULL) - { - size_t len = fread (cmd, 1, sizeof (cmd) - 1, f); - if (len > 0) - { - char *cores = 0; - int i; - for (i = 0; i < len; i++) - if (cmd[i] == '\0') - cmd[i] = ' '; - cmd[len] = '\0'; - - buffer_xml_printf (buffer, - "" - "%d" - "%s" - "%s", - pid, - username, - cmd); - - /* This only collects core numbers, and does not print threads. */ - list_threads (pid, NULL, &cores); - - if (cores) - { - buffer_xml_printf (buffer, - "%s", cores); - free (cores); - } - - buffer_xml_printf (buffer, ""); - } - fclose (f); - } -} - static int linux_qxfer_osdata (const char *annex, unsigned char *readbuf, unsigned const char *writebuf, CORE_ADDR offset, int len) { - /* We make the process list snapshot when the object starts to be - read. */ - static const char *buf; - static long len_avail = -1; - static struct buffer buffer; - int processes = 0; - int threads = 0; - - DIR *dirp; - - if (strcmp (annex, "processes") == 0) - processes = 1; - else if (strcmp (annex, "threads") == 0) - threads = 1; - else - return 0; - - if (!readbuf || writebuf) - return 0; - - if (offset == 0) - { - if (len_avail != -1 && len_avail != 0) - buffer_free (&buffer); - len_avail = 0; - buf = NULL; - buffer_init (&buffer); - if (processes) - buffer_grow_str (&buffer, ""); - else if (threads) - buffer_grow_str (&buffer, ""); - - dirp = opendir ("/proc"); - if (dirp) - { - struct dirent *dp; - while ((dp = readdir (dirp)) != NULL) - { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; - - if (!isdigit (dp->d_name[0]) - || strlen (dp->d_name) > sizeof ("4294967295") - 1) - continue; - - sprintf (procentry, "/proc/%s", dp->d_name); - if (stat (procentry, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) - { - int pid = (int) strtoul (dp->d_name, NULL, 10); - - if (processes) - { - struct passwd *entry = getpwuid (statbuf.st_uid); - show_process (pid, entry ? entry->pw_name : "?", &buffer); - } - else if (threads) - { - list_threads (pid, &buffer, NULL); - } - } - } - - closedir (dirp); - } - buffer_grow_str0 (&buffer, "\n"); - buf = buffer_finish (&buffer); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the data. */ - buffer_free (&buffer); - buf = NULL; - len_avail = 0; - return 0; - } - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; + return linux_common_xfer_osdata (annex, readbuf, offset, len); } /* Convert a native/host siginfo object, into/from the siginfo in the @@ -4907,63 +4654,6 @@ linux_qxfer_spu (const char *annex, unsigned char *readbuf, return ret; } -static int -linux_core_of_thread (ptid_t ptid) -{ - char filename[sizeof ("/proc//task//stat") - + 2 * 20 /* decimal digits for 2 numbers, max 2^64 bit each */ - + 1]; - FILE *f; - char *content = NULL; - char *p; - char *ts = 0; - int content_read = 0; - int i; - int core; - - sprintf (filename, "/proc/%d/task/%ld/stat", - ptid_get_pid (ptid), ptid_get_lwp (ptid)); - f = fopen (filename, "r"); - if (!f) - return -1; - - for (;;) - { - int n; - content = realloc (content, content_read + 1024); - n = fread (content + content_read, 1, 1024, f); - content_read += n; - if (n < 1024) - { - content[content_read] = '\0'; - break; - } - } - - p = strchr (content, '('); - - /* Skip ")". */ - if (p != NULL) - p = strchr (p, ')'); - if (p != NULL) - p++; - - /* If the first field after program name has index 0, then core number is - the field with index 36. There's no constant for that anywhere. */ - if (p != NULL) - p = strtok_r (p, " ", &ts); - for (i = 0; p != NULL && i != 36; ++i) - p = strtok_r (NULL, " ", &ts); - - if (p == NULL || sscanf (p, "%d", &core) == 0) - core = -1; - - free (content); - fclose (f); - - return core; -} - static void linux_process_qsupported (const char *query) { @@ -5111,7 +4801,7 @@ static struct target_ops linux_target_ops = { #else NULL, #endif - linux_core_of_thread, + linux_common_core_of_thread, linux_process_qsupported, linux_supports_tracepoints, linux_read_pc, diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c index da9018dc817..8832417dc3e 100644 --- a/gdb/gdbserver/remote-utils.c +++ b/gdb/gdbserver/remote-utils.c @@ -1714,168 +1714,4 @@ monitor_output (const char *msg) free (buf); } -/* Return a malloc allocated string with special characters from TEXT - replaced by entity references. */ - -char * -xml_escape_text (const char *text) -{ - char *result; - int i, special; - - /* Compute the length of the result. */ - for (i = 0, special = 0; text[i] != '\0'; i++) - switch (text[i]) - { - case '\'': - case '\"': - special += 5; - break; - case '&': - special += 4; - break; - case '<': - case '>': - special += 3; - break; - default: - break; - } - - /* Expand the result. */ - result = xmalloc (i + special + 1); - for (i = 0, special = 0; text[i] != '\0'; i++) - switch (text[i]) - { - case '\'': - strcpy (result + i + special, "'"); - special += 5; - break; - case '\"': - strcpy (result + i + special, """); - special += 5; - break; - case '&': - strcpy (result + i + special, "&"); - special += 4; - break; - case '<': - strcpy (result + i + special, "<"); - special += 3; - break; - case '>': - strcpy (result + i + special, ">"); - special += 3; - break; - default: - result[i + special] = text[i]; - break; - } - result[i + special] = '\0'; - - return result; -} - -void -buffer_grow (struct buffer *buffer, const char *data, size_t size) -{ - char *new_buffer; - size_t new_buffer_size; - - if (size == 0) - return; - - new_buffer_size = buffer->buffer_size; - - if (new_buffer_size == 0) - new_buffer_size = 1; - - while (buffer->used_size + size > new_buffer_size) - new_buffer_size *= 2; - new_buffer = realloc (buffer->buffer, new_buffer_size); - if (!new_buffer) - abort (); - memcpy (new_buffer + buffer->used_size, data, size); - buffer->buffer = new_buffer; - buffer->buffer_size = new_buffer_size; - buffer->used_size += size; -} - -void -buffer_free (struct buffer *buffer) -{ - if (!buffer) - return; - - free (buffer->buffer); - buffer->buffer = NULL; - buffer->buffer_size = 0; - buffer->used_size = 0; -} - -void -buffer_init (struct buffer *buffer) -{ - memset (buffer, 0, sizeof (*buffer)); -} - -char* -buffer_finish (struct buffer *buffer) -{ - char *ret = buffer->buffer; - buffer->buffer = NULL; - buffer->buffer_size = 0; - buffer->used_size = 0; - return ret; -} - -void -buffer_xml_printf (struct buffer *buffer, const char *format, ...) -{ - va_list ap; - const char *f; - const char *prev; - int percent = 0; - - va_start (ap, format); - - prev = format; - for (f = format; *f; f++) - { - if (percent) - { - switch (*f) - { - case 's': - { - char *p; - char *a = va_arg (ap, char *); - buffer_grow (buffer, prev, f - prev - 1); - p = xml_escape_text (a); - buffer_grow_str (buffer, p); - free (p); - prev = f + 1; - } - break; - case 'd': - { - int i = va_arg (ap, int); - char b[sizeof ("4294967295")]; - - buffer_grow (buffer, prev, f - prev - 1); - sprintf (b, "%d", i); - buffer_grow_str (buffer, b); - prev = f + 1; - } - } - percent = 0; - } - else if (*f == '%') - percent = 1; - } - - buffer_grow_str (buffer, prev); - va_end (ap); -} - #endif diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index fd06c8f9a2a..a87aef558a1 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -2582,7 +2582,6 @@ main (int argc, char *argv[]) exit (1); } - initialize_inferiors (); initialize_async_io (); initialize_low (); if (target_supports_tracepoints ()) diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h index f1147d6939a..8d8b7f9efdd 100644 --- a/gdb/gdbserver/server.h +++ b/gdb/gdbserver/server.h @@ -105,6 +105,11 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap); /* A type used for binary buffers. */ typedef unsigned char gdb_byte; +#include "ptid.h" +#include "buffer.h" +#include "xml-utils.h" +#include "gdb_locale.h" + /* FIXME: This should probably be autoconf'd for. It's an integer type at least the size of a (void *). */ typedef long long CORE_ADDR; @@ -112,68 +117,6 @@ typedef long long CORE_ADDR; typedef long long LONGEST; typedef unsigned long long ULONGEST; -/* The ptid struct is a collection of the various "ids" necessary - for identifying the inferior. This consists of the process id - (pid), thread id (tid), and other fields necessary for uniquely - identifying the inferior process/thread being debugged. When - manipulating ptids, the constructors, accessors, and predicate - declared in server.h should be used. These are as follows: - - ptid_build - Make a new ptid from a pid, lwp, and tid. - pid_to_ptid - Make a new ptid from just a pid. - ptid_get_pid - Fetch the pid component of a ptid. - ptid_get_lwp - Fetch the lwp component of a ptid. - ptid_get_tid - Fetch the tid component of a ptid. - ptid_equal - Test to see if two ptids are equal. - - Please do NOT access the struct ptid members directly (except, of - course, in the implementation of the above ptid manipulation - functions). */ - -struct ptid - { - /* Process id */ - int pid; - - /* Lightweight process id */ - long lwp; - - /* Thread id */ - long tid; - }; - -typedef struct ptid ptid_t; - -/* The -1 ptid, often used to indicate either an error condition or a - "don't care" condition, i.e, "run all threads". */ -extern ptid_t minus_one_ptid; - -/* The null or zero ptid, often used to indicate no process. */ -extern ptid_t null_ptid; - -/* Attempt to find and return an existing ptid with the given PID, - LWP, and TID components. If none exists, create a new one and - return that. */ -ptid_t ptid_build (int pid, long lwp, long tid); - -/* Create a ptid from just a pid. */ -ptid_t pid_to_ptid (int pid); - -/* Fetch the pid (process id) component from a ptid. */ -int ptid_get_pid (ptid_t ptid); - -/* Fetch the lwp (lightweight process) component from a ptid. */ -long ptid_get_lwp (ptid_t ptid); - -/* Fetch the tid (thread id) component from a ptid. */ -long ptid_get_tid (ptid_t ptid); - -/* Compare two ptids to see if they are equal. */ -extern int ptid_equal (ptid_t p1, ptid_t p2); - -/* Return true if this ptid represents a process id. */ -extern int ptid_is_pid (ptid_t ptid); - /* Generic information for tracking a list of ``inferiors'' - threads, processes, etc. */ struct inferior_list @@ -294,8 +237,6 @@ extern struct inferior_list all_threads; extern struct inferior_list all_dlls; extern int dlls_changed; -void initialize_inferiors (void); - void add_inferior_to_list (struct inferior_list *list, struct inferior_list_entry *new_inferior); void for_each_inferior (struct inferior_list *list, @@ -454,43 +395,8 @@ int relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc); void monitor_output (const char *msg); -char *xml_escape_text (const char *text); - -/* Simple growing buffer. */ - -struct buffer -{ - char *buffer; - size_t buffer_size; /* allocated size */ - size_t used_size; /* actually used size */ -}; - -/* Append DATA of size SIZE to the end of BUFFER. Grows the buffer to - accommodate the new data. */ -void buffer_grow (struct buffer *buffer, const char *data, size_t size); - -/* Release any memory held by BUFFER. */ -void buffer_free (struct buffer *buffer); - -/* Initialize BUFFER. BUFFER holds no memory afterwards. */ -void buffer_init (struct buffer *buffer); - -/* Return a pointer into BUFFER data, effectivelly transfering - ownership of the buffer memory to the caller. Calling buffer_free - afterwards has no effect on the returned data. */ -char* buffer_finish (struct buffer *buffer); - -/* Simple printf to BUFFER function. Current implemented formatters: - %s - grow an xml escaped text in OBSTACK. */ -void buffer_xml_printf (struct buffer *buffer, const char *format, ...) - ATTR_FORMAT (printf, 2, 3); - -#define buffer_grow_str(BUFFER,STRING) \ - buffer_grow (BUFFER, STRING, strlen (STRING)) -#define buffer_grow_str0(BUFFER,STRING) \ - buffer_grow (BUFFER, STRING, strlen (STRING) + 1) - /* Functions from utils.c */ +#include "common-utils.h" void *xmalloc (size_t) ATTR_MALLOC; void *xrealloc (void *, size_t); @@ -502,8 +408,6 @@ void freeargv (char **argv); void perror_with_name (const char *string); void error (const char *string,...) ATTR_NORETURN ATTR_FORMAT (printf, 1, 2); void fatal (const char *string,...) ATTR_NORETURN ATTR_FORMAT (printf, 1, 2); -void internal_error (const char *file, int line, const char *, ...) - ATTR_NORETURN ATTR_FORMAT (printf, 3, 4); void warning (const char *string,...) ATTR_FORMAT (printf, 1, 2); char *paddress (CORE_ADDR addr); char *pulongest (ULONGEST u); @@ -511,33 +415,7 @@ char *plongest (LONGEST l); char *phex_nz (ULONGEST l, int sizeof_l); char *pfildes (gdb_fildes_t fd); -#define gdb_assert(expr) \ - ((void) ((expr) ? 0 : \ - (gdb_assert_fail (#expr, __FILE__, __LINE__, ASSERT_FUNCTION), 0))) - -/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__' - which contains the name of the function currently being defined. - This is broken in G++ before version 2.6. - C9x has a similar variable called __func__, but prefer the GCC one since - it demangles C++ function names. */ -#if (GCC_VERSION >= 2004) -#define ASSERT_FUNCTION __PRETTY_FUNCTION__ -#else -#if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L -#define ASSERT_FUNCTION __func__ -#endif -#endif - -/* This prints an "Assertion failed" message, and exits. */ -#if defined (ASSERT_FUNCTION) -#define gdb_assert_fail(assertion, file, line, function) \ - internal_error (file, line, "%s: Assertion `%s' failed.", \ - function, assertion) -#else -#define gdb_assert_fail(assertion, file, line, function) \ - internal_error (file, line, "Assertion `%s' failed.", \ - assertion) -#endif +#include "gdb_assert.h" /* Maximum number of bytes to read/write at once. The value here is chosen to fill up a packet (the headers account for the 32). */ diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c index 78ae6f7fcee..f804ced1ea1 100644 --- a/gdb/gdbserver/utils.c +++ b/gdb/gdbserver/utils.c @@ -35,10 +35,8 @@ /* Generally useful subroutines used throughout the program. */ -static void malloc_failure (size_t size) ATTR_NORETURN; - -static void -malloc_failure (size_t size) +void +malloc_failure (long size) { fprintf (stderr, PREFIX "ran out of memory while trying to allocate %lu bytes\n", @@ -46,61 +44,6 @@ malloc_failure (size_t size) exit (1); } -/* Allocate memory without fail. - If malloc fails, this will print a message to stderr and exit. */ - -void * -xmalloc (size_t size) -{ - void *newmem; - - if (size == 0) - size = 1; - newmem = malloc (size); - if (!newmem) - malloc_failure (size); - - return newmem; -} - -/* Reallocate memory without fail. This works like xmalloc. */ - -void * -xrealloc (void *ptr, size_t size) -{ - void *val; - - if (size == 0) - size = 1; - - if (ptr != NULL) - val = realloc (ptr, size); /* OK: realloc */ - else - val = malloc (size); /* OK: malloc */ - if (val == NULL) - malloc_failure (size); - - return val; -} - -/* Allocate memory without fail and set it to zero. - If malloc fails, this will print a message to stderr and exit. */ - -void * -xcalloc (size_t nelem, size_t elsize) -{ - void *newmem; - - if (nelem == 0 || elsize == 0) - nelem = elsize = 1; - - newmem = calloc (nelem, elsize); - if (!newmem) - malloc_failure (nelem * elsize); - - return newmem; -} - /* Copy a string into a memory buffer. If malloc fails, this will print a message to stderr and exit. */ @@ -239,22 +182,6 @@ get_cell (void) return buf[cell]; } -/* Stdarg wrapper around vsnprintf. - SIZE is the size of the buffer pointed to by STR. */ - -int -xsnprintf (char *str, size_t size, const char *format, ...) -{ - va_list args; - int ret; - - va_start (args, format); - ret = vsnprintf (str, size, format, args); - va_end (args); - - return ret; -} - static char * decimal2str (char *sign, ULONGEST addr) { diff --git a/gdb/inferior.h b/gdb/inferior.h index 346bb87a02d..cf747a650cd 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -32,6 +32,8 @@ struct regcache; struct ui_out; struct terminal_info; +#include "ptid.h" + /* For bpstat. */ #include "breakpoint.h" @@ -63,36 +65,6 @@ extern void discard_infcall_control_state (struct infcall_control_state *); extern struct regcache * get_infcall_suspend_state_regcache (struct infcall_suspend_state *); -/* The -1 ptid, often used to indicate either an error condition - or a "don't care" condition, i.e, "run all threads." */ -extern ptid_t minus_one_ptid; - -/* The null or zero ptid, often used to indicate no process. */ -extern ptid_t null_ptid; - -/* Attempt to find and return an existing ptid with the given PID, LWP, - and TID components. If none exists, create a new one and return - that. */ -ptid_t ptid_build (int pid, long lwp, long tid); - -/* Find/Create a ptid from just a pid. */ -ptid_t pid_to_ptid (int pid); - -/* Fetch the pid (process id) component from a ptid. */ -int ptid_get_pid (ptid_t ptid); - -/* Fetch the lwp (lightweight process) component from a ptid. */ -long ptid_get_lwp (ptid_t ptid); - -/* Fetch the tid (thread id) component from a ptid. */ -long ptid_get_tid (ptid_t ptid); - -/* Compare two ptids to see if they are equal. */ -extern int ptid_equal (ptid_t p1, ptid_t p2); - -/* Return true if PTID represents a process id. */ -extern int ptid_is_pid (ptid_t ptid); - /* Returns true if PTID matches filter FILTER. FILTER can be the wild card MINUS_ONE_PTID (all ptid match it); can be a ptid representing a process (ptid_is_pid returns true), in which case, all lwps and diff --git a/gdb/infrun.c b/gdb/infrun.c index 91e0fc27e77..f92bc9b20dc 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -6803,77 +6803,6 @@ inferior_has_called_syscall (ptid_t pid, int *syscall_number) return 1; } -/* Oft used ptids */ -ptid_t null_ptid; -ptid_t minus_one_ptid; - -/* Create a ptid given the necessary PID, LWP, and TID components. */ - -ptid_t -ptid_build (int pid, long lwp, long tid) -{ - ptid_t ptid; - - ptid.pid = pid; - ptid.lwp = lwp; - ptid.tid = tid; - return ptid; -} - -/* Create a ptid from just a pid. */ - -ptid_t -pid_to_ptid (int pid) -{ - return ptid_build (pid, 0, 0); -} - -/* Fetch the pid (process id) component from a ptid. */ - -int -ptid_get_pid (ptid_t ptid) -{ - return ptid.pid; -} - -/* Fetch the lwp (lightweight process) component from a ptid. */ - -long -ptid_get_lwp (ptid_t ptid) -{ - return ptid.lwp; -} - -/* Fetch the tid (thread id) component from a ptid. */ - -long -ptid_get_tid (ptid_t ptid) -{ - return ptid.tid; -} - -/* ptid_equal() is used to test equality of two ptids. */ - -int -ptid_equal (ptid_t ptid1, ptid_t ptid2) -{ - return (ptid1.pid == ptid2.pid && ptid1.lwp == ptid2.lwp - && ptid1.tid == ptid2.tid); -} - -/* Returns true if PTID represents a process. */ - -int -ptid_is_pid (ptid_t ptid) -{ - if (ptid_equal (minus_one_ptid, ptid)) - return 0; - if (ptid_equal (null_ptid, ptid)) - return 0; - - return (ptid_get_lwp (ptid) == 0 && ptid_get_tid (ptid) == 0); -} - int ptid_match (ptid_t ptid, ptid_t filter) { @@ -7263,8 +7192,6 @@ Tells gdb whether to detach the child of a fork."), NULL, NULL, &setlist, &showlist); /* ptid initializations */ - null_ptid = ptid_build (0, 0, 0); - minus_one_ptid = ptid_build (-1, 0, 0); inferior_ptid = null_ptid; target_last_wait_ptid = minus_one_ptid; diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index ec4c7884400..c832902668b 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -57,6 +57,7 @@ #include "terminal.h" #include #include "solib.h" +#include "linux-osdata.h" #ifndef SPUFS_MAGIC #define SPUFS_MAGIC 0x23c9b64e @@ -5114,148 +5115,9 @@ linux_nat_xfer_osdata (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) { - /* We make the process list snapshot when the object starts to be - read. */ - static const char *buf; - static LONGEST len_avail = -1; - static struct obstack obstack; - - DIR *dirp; - gdb_assert (object == TARGET_OBJECT_OSDATA); - if (!annex) - { - if (offset == 0) - { - if (len_avail != -1 && len_avail != 0) - obstack_free (&obstack, NULL); - len_avail = 0; - buf = NULL; - obstack_init (&obstack); - obstack_grow_str (&obstack, "\n"); - - obstack_xml_printf (&obstack, - "" - "processes" - "" - "Listing of all processes" - ""); - - obstack_grow_str0 (&obstack, "\n"); - buf = obstack_finish (&obstack); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the obstack. */ - obstack_free (&obstack, NULL); - buf = NULL; - len_avail = 0; - return 0; - } - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; - } - - if (strcmp (annex, "processes") != 0) - return 0; - - gdb_assert (readbuf && !writebuf); - - if (offset == 0) - { - if (len_avail != -1 && len_avail != 0) - obstack_free (&obstack, NULL); - len_avail = 0; - buf = NULL; - obstack_init (&obstack); - obstack_grow_str (&obstack, "\n"); - - dirp = opendir ("/proc"); - if (dirp) - { - struct dirent *dp; - - while ((dp = readdir (dirp)) != NULL) - { - struct stat statbuf; - char procentry[sizeof ("/proc/4294967295")]; - - if (!isdigit (dp->d_name[0]) - || NAMELEN (dp) > sizeof ("4294967295") - 1) - continue; - - sprintf (procentry, "/proc/%s", dp->d_name); - if (stat (procentry, &statbuf) == 0 - && S_ISDIR (statbuf.st_mode)) - { - char *pathname; - FILE *f; - char cmd[MAXPATHLEN + 1]; - struct passwd *entry; - - pathname = xstrprintf ("/proc/%s/cmdline", dp->d_name); - entry = getpwuid (statbuf.st_uid); - - if ((f = fopen (pathname, "r")) != NULL) - { - size_t length = fread (cmd, 1, sizeof (cmd) - 1, f); - - if (length > 0) - { - int i; - - for (i = 0; i < length; i++) - if (cmd[i] == '\0') - cmd[i] = ' '; - cmd[length] = '\0'; - - obstack_xml_printf ( - &obstack, - "" - "%s" - "%s" - "%s" - "", - dp->d_name, - entry ? entry->pw_name : "?", - cmd); - } - fclose (f); - } - - xfree (pathname); - } - } - - closedir (dirp); - } - - obstack_grow_str0 (&obstack, "\n"); - buf = obstack_finish (&obstack); - len_avail = strlen (buf); - } - - if (offset >= len_avail) - { - /* Done. Get rid of the obstack. */ - obstack_free (&obstack, NULL); - buf = NULL; - len_avail = 0; - return 0; - } - - if (len > len_avail - offset) - len = len_avail - offset; - memcpy (readbuf, buf + offset, len); - - return len; + return linux_common_xfer_osdata (annex, readbuf, offset, len); } static LONGEST diff --git a/gdb/utils.c b/gdb/utils.c index d10669a72c9..13e99b4e15d 100644 --- a/gdb/utils.c +++ b/gdb/utils.c @@ -1210,7 +1210,7 @@ quit (void) memory requested in SIZE. */ void -nomem (long size) +malloc_failure (long size) { if (size > 0) { @@ -1224,146 +1224,6 @@ nomem (long size) } } -/* The xmalloc() (libiberty.h) family of memory management routines. - - These are like the ISO-C malloc() family except that they implement - consistent semantics and guard against typical memory management - problems. */ - -/* NOTE: These are declared using PTR to ensure consistency with - "libiberty.h". xfree() is GDB local. */ - -PTR /* ARI: PTR */ -xmalloc (size_t size) -{ - void *val; - - /* See libiberty/xmalloc.c. This function need's to match that's - semantics. It never returns NULL. */ - if (size == 0) - size = 1; - - val = malloc (size); /* ARI: malloc */ - if (val == NULL) - nomem (size); - - return (val); -} - -void * -xzalloc (size_t size) -{ - return xcalloc (1, size); -} - -PTR /* ARI: PTR */ -xrealloc (PTR ptr, size_t size) /* ARI: PTR */ -{ - void *val; - - /* See libiberty/xmalloc.c. This function need's to match that's - semantics. It never returns NULL. */ - if (size == 0) - size = 1; - - if (ptr != NULL) - val = realloc (ptr, size); /* ARI: realloc */ - else - val = malloc (size); /* ARI: malloc */ - if (val == NULL) - nomem (size); - - return (val); -} - -PTR /* ARI: PTR */ -xcalloc (size_t number, size_t size) -{ - void *mem; - - /* See libiberty/xmalloc.c. This function need's to match that's - semantics. It never returns NULL. */ - if (number == 0 || size == 0) - { - number = 1; - size = 1; - } - - mem = calloc (number, size); /* ARI: xcalloc */ - if (mem == NULL) - nomem (number * size); - - return mem; -} - -void -xfree (void *ptr) -{ - if (ptr != NULL) - free (ptr); /* ARI: free */ -} - - -/* Like asprintf/vasprintf but get an internal_error if the call - fails. */ - -char * -xstrprintf (const char *format, ...) -{ - char *ret; - va_list args; - - va_start (args, format); - ret = xstrvprintf (format, args); - va_end (args); - return ret; -} - -void -xasprintf (char **ret, const char *format, ...) -{ - va_list args; - - va_start (args, format); - (*ret) = xstrvprintf (format, args); - va_end (args); -} - -void -xvasprintf (char **ret, const char *format, va_list ap) -{ - (*ret) = xstrvprintf (format, ap); -} - -char * -xstrvprintf (const char *format, va_list ap) -{ - char *ret = NULL; - int status = vasprintf (&ret, format, ap); - - /* NULL is returned when there was a memory allocation problem, or - any other error (for instance, a bad format string). A negative - status (the printed length) with a non-NULL buffer should never - happen, but just to be sure. */ - if (ret == NULL || status < 0) - internal_error (__FILE__, __LINE__, _("vasprintf call failed")); - return ret; -} - -int -xsnprintf (char *str, size_t size, const char *format, ...) -{ - va_list args; - int ret; - - va_start (args, format); - ret = vsnprintf (str, size, format, args); - gdb_assert (ret < size); - va_end (args); - - return ret; -} - /* My replacement for the read system call. Used like `read' but keeps going if `read' returns too soon. */ @@ -1385,7 +1245,7 @@ myread (int desc, char *addr, int len) } return orglen; } - + /* Make a copy of the string at PTR with SIZE characters (and add a null character at the end in the copy). Uses malloc to get the space. Returns the address of the copy. */ @@ -3741,7 +3601,7 @@ gdb_buildargv (const char *s) char **argv = buildargv (s); if (s != NULL && argv == NULL) - nomem (0); + malloc_failure (0); return argv; } diff --git a/gdb/xml-support.c b/gdb/xml-support.c index e0ac8de68b9..2edc82cb2ea 100644 --- a/gdb/xml-support.c +++ b/gdb/xml-support.c @@ -458,7 +458,7 @@ gdb_xml_create_parser_and_cleanup_1 (const char *name, if (parser->expat_parser == NULL) { xfree (parser); - nomem (0); + malloc_failure (0); } parser->name = name; @@ -990,68 +990,6 @@ show_debug_xml (struct ui_file *file, int from_tty, fprintf_filtered (file, _("XML debugging is %s.\n"), value); } -/* Return a malloc allocated string with special characters from TEXT - replaced by entity references. */ - -char * -xml_escape_text (const char *text) -{ - char *result; - int i, special; - - /* Compute the length of the result. */ - for (i = 0, special = 0; text[i] != '\0'; i++) - switch (text[i]) - { - case '\'': - case '\"': - special += 5; - break; - case '&': - special += 4; - break; - case '<': - case '>': - special += 3; - break; - default: - break; - } - - /* Expand the result. */ - result = xmalloc (i + special + 1); - for (i = 0, special = 0; text[i] != '\0'; i++) - switch (text[i]) - { - case '\'': - strcpy (result + i + special, "'"); - special += 5; - break; - case '\"': - strcpy (result + i + special, """); - special += 5; - break; - case '&': - strcpy (result + i + special, "&"); - special += 4; - break; - case '<': - strcpy (result + i + special, "<"); - special += 3; - break; - case '>': - strcpy (result + i + special, ">"); - special += 3; - break; - default: - result[i + special] = text[i]; - break; - } - result[i + special] = '\0'; - - return result; -} - void obstack_xml_printf (struct obstack *obstack, const char *format, ...) { @@ -1106,7 +1044,7 @@ xml_fetch_content_from_file (const char *filename, void *baton) char *fullname = concat (dirname, "/", filename, (char *) NULL); if (fullname == NULL) - nomem (0); + malloc_failure (0); file = fopen (fullname, FOPEN_RT); xfree (fullname); } diff --git a/gdb/xml-support.h b/gdb/xml-support.h index 4d5df5c4fef..bc3a89d6776 100644 --- a/gdb/xml-support.h +++ b/gdb/xml-support.h @@ -24,6 +24,7 @@ #include "gdb_obstack.h" #include "vec.h" +#include "xml-utils.h" struct gdb_xml_parser; struct gdb_xml_element; @@ -48,11 +49,6 @@ LONGEST xml_builtin_xfer_partial (const char *filename, extern const char *xml_builtin[][2]; -/* Return a malloc allocated string with special characters from TEXT - replaced by entity references. */ - -char *xml_escape_text (const char *text); - /* Support for XInclude. */ /* Callback to fetch a new XML file, based on the provided HREF. */ -- 2.30.2