Re: [patch] gdbserver build-id in qxfer_libraries reply

Aleksandar Ristovski
2013-02-27T17:25:51Z

[-- Attachment #1: Type: text/plain, Size: 3704 bytes --]

On 13-02-26 07:01 AM, Pedro Alves wrote:
> Hi Aleksandar,
>
> Thanks for the patch.

Thanks for looking at the patch.

>
> On 02/22/2013 06:38 PM, Aleksandar Ristovski wrote:
>>>
>>> Majority of the patch is refactoring to reuse code.
>
> I'm reading the patch, but one immediate question I have
> is where did hex_encode/hex_decode and friends got refactored
> from? It seems we end up with multiple functions to do the same
> in both gdb and gdbserver, given the existence of bin2hex etc
> in gdb and unhexify/hexify in gdbserver?

apparently I was grepping *h files. I moved bin2hex and hex2bin to
common-utils. New patch attached, along with documentation patch.

Note there is a small change in linux-low.c in that new patch passes
exactly note size instead of using PT_NOTE pheaders p_memsz.

>
>> The real change is
>>> in gdbserver/linux-low.c.
>

---
Aleksandar

ChangeLog followed by doc/ChangeLog

DATE Aleksandar Ristovski <aristovski@qnx.com>

* Makefile.in (HFILES_NO_SRCDIR): Add linux-maps.h and linux-maps.c.

* common/common-utils.c (TARGET_CHAR_BIT): Define if not defined.
(HOST_CHAR_BIT): Ditto.
(ctype.h): Include.
(string.h): Include.
(assert.h): Include.
(HIGH_BYTE_POSN): Moved from utils.c.
(is_digit_in_base): Ditto.
(digit_to_int): Ditto.
(strtoulst): Ditto.
(fromhex): Moved from remote.c.
(hex2bin): Ditto.
(tohex): Ditto.
(bin2hex): Ditto.

* common/common-utils.h (strtoulst): Moved from utils.h.
(tohex): New declaration.
(fromhex): Ditto.
(hex2bin): Ditto.
(bin2hex): Ditto.

* common/xml-utils.h (xml_hex_encode_text): Declare.

* config/i386/linux.mk (NATDEPFILES): Add linux-maps.o.

* config/i386/linux64.mh (NATDEPFILES): Add linux-maps.o.

* features/library-list-svr4.dtd (build-id): New attribute.

* gdbserver/Makefile.in (linux-maps.o): New.

* gdbserver/configure.srv (srv_tgtobj): Add linux-maps.o.

* gdbserver/linux-low.c (linux-maps.h): Include.
(find_memory_region_callback_data): New structure definition.
(find_memory_region_callback): New forward declaration.
(find_memory_region_callback): New function.
(get_hex_build_id): New function.
(linux_qxfer_libraries_svr4): Add hex encoded build-id to the reply.

* remote-utils.c (common-utils.h): Include.
(fromhex): Moved to common-utils.c.
(unhexify): Use hex2bin.
(tohex): Moved to common-utils.c.
(hexify): Use bin2hex.

* linux-tdep.c (linux-maps.h): Include.
(read_mapping): Moved to linux-maps.c.
(linux_find_memory_region_ftype): Moved to linux-maps.h.
(linux_find_memory_regions_full): Moved to linux-maps.c.
(linux_find_memory_regions): Check for fake_pid_p to match
functionality of original linux_find_memory_regions_full.
(linux_make_mappings_corefile_notes): Ditto.

* remote.c (tohex): Remove forward declaration.
(fromhex): Ditto.
(hex2bin): Ditto.
(bin2hex): Ditto.
(fromhex): Move implementation to common-utils.c
(hex2bin): Ditto.
(tohex): Ditto.
(bin2hex): Ditto.

* tracepoint.c (hex2bin): Remove declaration.
(bin2hex): Ditto.

* utils.c (HIGH_BYTE_POSN): Moved to common-utils.c.
(is_digit_in_base): Ditto.
(digit_to_int): Ditto.
(strtoulst): Ditto.

* utils.h (strtoulst): Moved to common-utils.h.

doc/ChangeLog:
DATE Aleksandar Ristovski <aristovski@qnx.com>

* gdb.texinfo (Library List Format for SVR4 Targets): New
'build-id'
attribute, add it to the example and document it in DTD.

[-- Attachment #2: gdbserver-build-id-in-qxfer_libraries-reply-201302271218.patch --]
[-- Type: text/x-patch, Size: 42623 bytes --]

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index ed30db5..dae451b 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -771,7 +771,7 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c

HFILES_NO_SRCDIR = \
common/gdb_signals.h common/gdb_thread_db.h common/gdb_vecs.h \
-common/i386-xstate.h common/linux-ptrace.h \
+common/i386-xstate.h common/linux-maps.h common/linux-ptrace.h \
proc-utils.h aarch64-tdep.h arm-tdep.h ax-gdb.h ppcfbsd-tdep.h \
ppcnbsd-tdep.h cli-out.h gdb_expat.h breakpoint.h infcall.h obsd-tdep.h \
exec.h m32r-tdep.h osabi.h gdbcore.h solib-som.h amd64bsd-nat.h \
@@ -1945,6 +1945,10 @@ format.o: ${srcdir}/common/format.c
$(COMPILE) $(srcdir)/common/format.c
$(POSTCOMPILE)

+linux-maps.o: ${srcdir}/common/linux-maps.c
+ $(COMPILE) $(srcdir)/common/linux-maps.c
+ $(POSTCOMPILE)
+
linux-osdata.o: ${srcdir}/common/linux-osdata.c
$(COMPILE) $(srcdir)/common/linux-osdata.c
$(POSTCOMPILE)
diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c
index 4204abf..780ba09 100644
--- a/gdb/common/common-utils.c
+++ b/gdb/common/common-utils.c
@@ -19,6 +19,15 @@

#ifdef GDBSERVER
#include "server.h"
+
+#if !defined (TARGET_CHAR_BIT)
+#define TARGET_CHAR_BIT (sizeof (char) * 8)
+#endif /* ! TARGET_CHAR_BIT */
+
+#if !defined (HOST_CHAR_BIT)
+#define HOST_CHAR_BIT TARGET_CHAR_BIT
+#endif /* ! HOST_CHAR_BIT */
+
#else
#include "defs.h"
#endif
@@ -28,6 +37,9 @@

#include <stdlib.h>
#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <assert.h>

/* The xmalloc() (libiberty.h) family of memory management routines.

@@ -161,3 +173,175 @@ savestring (const char *ptr, size_t len)
p[len] = 0;
return p;
}
+
+\f
+/* The bit offset of the highest byte in a ULONGEST, for overflow
+ checking. */
+
+#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
+
+
+/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
+ where 2 <= BASE <= 36. */
+
+static int
+is_digit_in_base (unsigned char digit, int base)
+{
+ if (!isalnum (digit))
+ return 0;
+ if (base <= 10)
+ return (isdigit (digit) && digit < base + '0');
+ else
+ return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
+}
+
+static int
+digit_to_int (unsigned char c)
+{
+ if (isdigit (c))
+ return c - '0';
+ else
+ return tolower (c) - 'a' + 10;
+}
+
+/* As for strtoul, but for ULONGEST results. */
+
+ULONGEST
+strtoulst (const char *num, const char **trailer, int base)
+{
+ unsigned int high_part;
+ ULONGEST result;
+ int minus = 0;
+ int i = 0;
+
+ /* Skip leading whitespace. */
+ while (isspace (num[i]))
+ i++;
+
+ /* Handle prefixes. */
+ if (num[i] == '+')
+ i++;
+ else if (num[i] == '-')
+ {
+ minus = 1;
+ i++;
+ }
+
+ if (base == 0 || base == 16)
+ {
+ if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
+ {
+ i += 2;
+ if (base == 0)
+ base = 16;
+ }
+ }
+
+ if (base == 0 && num[i] == '0')
+ base = 8;
+
+ if (base == 0)
+ base = 10;
+
+ if (base < 2 || base > 36)
+ {
+ errno = EINVAL;
+ return 0;
+ }
+
+ result = high_part = 0;
+ for (; is_digit_in_base (num[i], base); i += 1)
+ {
+ result = result * base + digit_to_int (num[i]);
+ high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
+ result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
+ if (high_part > 0xff)
+ {
+ errno = ERANGE;
+ result = ~ (ULONGEST) 0;
+ high_part = 0;
+ minus = 0;
+ break;
+ }
+ }
+
+ if (trailer != NULL)
+ *trailer = &num[i];
+
+ result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
+ if (minus)
+ return -result;
+ else
+ return result;
+}
+
+\f
+/* Convert hex digit A to a number. */
+
+int
+fromhex (int a)
+{
+ if (a >= '0' && a <= '9')
+ return a - '0';
+ else if (a >= 'a' && a <= 'f')
+ return a - 'a' + 10;
+ else if (a >= 'A' && a <= 'F')
+ return a - 'A' + 10;
+ return -1;
+}
+
+size_t
+hex2bin (const char *hex, gdb_byte *bin, size_t count)
+{
+ size_t i;
+
+ for (i = 0; i < count; i++)
+ {
+ int hi, lo;
+
+ if (hex[0] == 0 || hex[1] == 0
+ || (hi = fromhex (hex[0])) < 0
+ || (lo = fromhex (hex[1])) < 0)
+ {
+ /* Hex string is short, or of uneven length or malformed.
+ Return the count that has been converted so far. */
+ warning (_("Malformed hex encoded string: '%s'\n"), hex);
+ return i;
+ }
+
+ *bin++ = hi * 16 + lo;
+ hex += 2;
+ }
+ return i;
+}
+
+
+/* Convert number NIB to a hex digit. */
+
+int
+tohex (int nib)
+{
+ if (nib < 10)
+ return '0' + nib;
+ else
+ return 'a' + nib - 10;
+}
+
+size_t
+bin2hex (const gdb_byte *bin, char *hex, size_t count)
+{
+ size_t i;
+
+ /* May use a length, or a nul-terminated string as input. */
+ if (count == 0)
+ count = strlen ((char *) bin);
+
+ for (i = 0; i < count; i++)
+ {
+ *hex++ = tohex ((*bin >> 4) & 0xf);
+ *hex++ = tohex (*bin++ & 0xf);
+ }
+ *hex = 0;
+ return i;
+}
+
diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
index 9b659d8..9ce5da2 100644
--- a/gdb/common/common-utils.h
+++ b/gdb/common/common-utils.h
@@ -53,4 +53,14 @@ int xsnprintf (char *str, size_t size, const char *format, ...)

char *savestring (const char *ptr, size_t len);

+extern ULONGEST strtoulst (const char *num, const char **trailer, int base);
+
+extern int tohex (int nib);
+
+extern int fromhex (int a);
+
+extern size_t hex2bin (const char *hex, gdb_byte *bin, size_t count);
+
+extern size_t bin2hex (const gdb_byte *bin, char *hex, size_t count);
+
#endif
diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c
new file mode 100644
index 0000000..c1af63d
--- /dev/null
+++ b/gdb/common/linux-maps.c
@@ -0,0 +1,217 @@
+/* Linux-specific memory maps manipulation routines.
+ Copyright (C) 2013 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 <http://www.gnu.org/licenses/>. */
+
+
+#ifdef GDBSERVER
+#include "server.h"
+#include "linux-maps.h"
+#include <fcntl.h>
+#include <unistd.h>
+#else /* ! GDBSERVER */
+#include "defs.h"
+#include "linux-maps.h"
+#include "target.h"
+#endif /* ! GDBSERVER */
+
+#include <ctype.h>
+
+
+#ifdef GDBSERVER
+static char *
+fileio_read_stralloc (const char *const filename)
+{
+ char *buf;
+ int fd;
+ size_t buf_alloc;
+ size_t buf_pos;
+ const size_t buf_alloc_inc = 2 * 4096;
+
+ fd = open (filename, O_RDONLY);
+ if (fd == -1)
+ return NULL;
+
+ buf_alloc = 4096;
+ buf = xmalloc (buf_alloc);
+ buf_pos = 0;
+
+ while (1)
+ {
+ ssize_t n;
+
+ n = pread (fd, &buf[buf_pos], buf_alloc - buf_pos, buf_pos);
+
+ if (n < 0)
+ {
+ xfree (buf);
+ buf = NULL;
+ break;
+ }
+ else if (n == 0)
+ {
+ if (buf_pos == 0)
+ {
+ xfree (buf);
+ buf = NULL;
+ }
+ break;
+ }
+ buf_pos += n;
+
+ if (buf_alloc < buf_pos + buf_alloc_inc)
+ {
+ buf_alloc += buf_alloc_inc;
+ buf = xrealloc (buf, buf_alloc);
+ }
+ }
+
+ if (close (fd) < 0)
+ warning (_("Error closing file descriptor: '%s'"), strerror (errno));
+
+ return buf;
+}
+
+#define target_fileio_read_stralloc(filename) fileio_read_stralloc (filename)
+
+#endif /* GDBSERVER */
+
+/* Service function for corefiles and info proc. */
+
+void
+read_mapping (const char *line,
+ ULONGEST *addr, ULONGEST *endaddr,
+ const char **permissions, size_t *permissions_len,
+ ULONGEST *offset,
+ const char **device, size_t *device_len,
+ ULONGEST *inode,
+ const char **filename)
+{
+ const char *p = line;
+
+ *addr = strtoulst (p, &p, 16);
+ if (*p == '-')
+ p++;
+ *endaddr = strtoulst (p, &p, 16);
+
+ while (*p && isspace (*p))
+ p++;
+ *permissions = p;
+ while (*p && !isspace (*p))
+ p++;
+ *permissions_len = p - *permissions;
+
+ *offset = strtoulst (p, &p, 16);
+
+ while (*p && isspace (*p))
+ p++;
+ *device = p;
+ while (*p && !isspace (*p))
+ p++;
+ *device_len = p - *device;
+
+ *inode = strtoulst (p, &p, 10);
+
+ while (*p && isspace (*p))
+ p++;
+ *filename = p;
+}
+
+/* List memory regions in the inferior.
+ Return nonzero on error. */
+
+int
+linux_find_memory_regions_full (pid_t pid,
+ linux_find_memory_region_ftype *func,
+ void *obfd)
+{
+ char filename[100];
+ char *data;
+
+ xsnprintf (filename, sizeof filename,
+ "/proc/%d/smaps", pid);
+ data = target_fileio_read_stralloc (filename);
+ if (data == NULL)
+ {
+ /* Older Linux kernels did not support /proc/PID/smaps. */
+ xsnprintf (filename, sizeof filename,
+ "/proc/%d/maps", pid);
+ data = target_fileio_read_stralloc (filename);
+ }
+ if (data)
+ {
+ char *line;
+
+ line = strtok (data, "\n");
+ while (line)
+ {
+ ULONGEST addr, endaddr, offset, inode;
+ const char *permissions, *device, *filename;
+ size_t permissions_len, device_len;
+ int read, write, exec;
+ int modified = 0, has_anonymous = 0;
+ int ret;
+
+ read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
+ &offset, &device, &device_len, &inode, &filename);
+
+ /* Decode permissions. */
+ read = (memchr (permissions, 'r', permissions_len) != 0);
+ write = (memchr (permissions, 'w', permissions_len) != 0);
+ exec = (memchr (permissions, 'x', permissions_len) != 0);
+
+ /* Try to detect if region was modified by parsing smaps counters. */
+ for (line = strtok (NULL, "\n");
+ line && line[0] >= 'A' && line[0] <= 'Z';
+ line = strtok (NULL, "\n"))
+ {
+ char keyword[64 + 1];
+ unsigned long number;
+
+ if (sscanf (line, "%64s%lu kB\n", keyword, &number) != 2)
+ {
+ warning (_("Error parsing {s,}maps file '%s'"), filename);
+ break;
+ }
+ if (strcmp (keyword, "Anonymous:") == 0)
+ has_anonymous = 1;
+ if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0
+ || strcmp (keyword, "Private_Dirty:") == 0
+ || strcmp (keyword, "Swap:") == 0
+ || strcmp (keyword, "Anonymous:") == 0))
+ modified = 1;
+ }
+
+ /* Older Linux kernels did not support the "Anonymous:" counter.
+ If it is missing, we can't be sure - dump all the pages. */
+ if (!has_anonymous)
+ modified = 1;
+
+ /* Invoke the callback function to create the corefile segment. */
+ ret = func (addr, endaddr - addr, offset, inode,
+ read, write, exec, modified, filename, obfd);
+ if (ret)
+ break;
+ }
+
+ xfree (data);
+ return 0;
+ }
+
+ return 1;
+}
+
+
diff --git a/gdb/common/linux-maps.h b/gdb/common/linux-maps.h
new file mode 100644
index 0000000..b8725ab
--- /dev/null
+++ b/gdb/common/linux-maps.h
@@ -0,0 +1,50 @@
+/* Linux-specific memory maps manipulation routines.
+ Copyright (C) 2013 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 <http://www.gnu.org/licenses/>. */
+
+#ifndef COMMON_LINUX_MAPS_H
+#define COMMON_LINUX_MAPS_H
+
+/* Function type for linux_find_memory_regions_full function.
+
+ Non zero returned breaks loop in linux_find_memory_regions_full. */
+
+typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
+ ULONGEST offset, ULONGEST inode,
+ int read, int write,
+ int exec, int modified,
+ const char *filename,
+ void *data);
+
+/* A structure for passing information through
+ linux_find_memory_regions_full. */
+
+extern int linux_find_memory_regions_full (
+ pid_t pid,
+ linux_find_memory_region_ftype *func,
+ void *obfd);
+
+extern void read_mapping (const char *line,
+ ULONGEST *addr, ULONGEST *endaddr,
+ const char **permissions, size_t *permissions_len,
+ ULONGEST *offset,
+ const char **device, size_t *device_len,
+ ULONGEST *inode,
+ const char **filename);
+
+
+#endif /* COMMON_LINUX_MAPS_H */
diff --git a/gdb/common/xml-utils.h b/gdb/common/xml-utils.h
index ea4ab53..3c42183 100644
--- a/gdb/common/xml-utils.h
+++ b/gdb/common/xml-utils.h
@@ -25,4 +25,9 @@

extern char *xml_escape_text (const char *text);

+/* Return a xmalloc allocated string with hex-encoded SIZE bytes from
+ TEXT. */
+
+extern char *xml_hex_encode_text (const unsigned char *text, size_t size);
+
#endif
diff --git a/gdb/config/i386/linux.mh b/gdb/config/i386/linux.mh
index 8316d87..dd5cbd8 100644
--- a/gdb/config/i386/linux.mh
+++ b/gdb/config/i386/linux.mh
@@ -3,7 +3,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 \
+ proc-service.o linux-thread-db.o linux-maps.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o
NAT_CDEPS = $(srcdir)/proc-service.list

diff --git a/gdb/config/i386/linux64.mh b/gdb/config/i386/linux64.mh
index d2b95fd..b1f83a8 100644
--- a/gdb/config/i386/linux64.mh
+++ b/gdb/config/i386/linux64.mh
@@ -1,7 +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 linux-osdata.o \
+ linux-maps.o linux-nat.o linux-osdata.o \
proc-service.o linux-thread-db.o linux-fork.o \
linux-procfs.o linux-ptrace.o
NAT_FILE= config/nm-linux.h
diff --git a/gdb/features/library-list-svr4.dtd b/gdb/features/library-list-svr4.dtd
index cae7fd8..5f4c956 100644
--- a/gdb/features/library-list-svr4.dtd
+++ b/gdb/features/library-list-svr4.dtd
@@ -14,3 +14,4 @@
<!ATTLIST library lm CDATA #REQUIRED>
<!ATTLIST library l_addr CDATA #REQUIRED>
<!ATTLIST library l_ld CDATA #REQUIRED>
+<!ATTLIST library build-id CDATA #IMPLIED>
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index dffe8ae..744af57 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -509,6 +509,9 @@ ax.o: ax.c
signals.o: ../common/signals.c
$(COMPILE) $<
$(POSTCOMPILE)
+linux-maps.o: ../common/linux-maps.c
+ $(COMPILE) $<
+ $(POSTCOMPILE)
linux-procfs.o: ../common/linux-procfs.c
$(COMPILE) $<
$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 93c499c..1fd2203 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -46,6 +46,7 @@ case "${target}" in
srv_regobj="aarch64.o aarch64-without-fpu.o"
srv_tgtobj="linux-aarch64-low.o"
srv_tgtobj="${srv_tgtobj} linux-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-maps.o"
srv_tgtobj="${srv_tgtobj} linux-osdata.o"
srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
@@ -61,7 +62,9 @@ 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-osdata.o linux-arm-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-arm-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="arm-with-iwmmxt.xml"
srv_xmlfiles="${srv_xmlfiles} arm-with-vfpv2.xml"
@@ -84,19 +87,25 @@ case "${target}" in
srv_mingwce=yes
;;
bfin-*-*linux*) srv_regobj=reg-bfin.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-bfin-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-bfin-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
crisv32-*-linux*) srv_regobj=reg-crisv32.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-crisv32-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-crisv32-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
;;
cris-*-linux*) srv_regobj=reg-cris.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-cris-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-cris-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
@@ -111,7 +120,10 @@ 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-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-x86-low.o"
+ srv_tgtobj="${srv_tgtobj} i386-low.o i387-fp.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
@@ -146,12 +158,16 @@ case "${target}" in
srv_qnx="yes"
;;
ia64-*-linux*) srv_regobj=reg-ia64.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-ia64-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-ia64-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
;;
m32r*-*-linux*) srv_regobj=reg-m32r.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-m32r-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-m32r-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_thread_db=yes
@@ -161,7 +177,9 @@ case "${target}" in
else
srv_regobj=reg-m68k.o
fi
- srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-m68k-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
@@ -172,7 +190,9 @@ case "${target}" in
else
srv_regobj=reg-m68k.o
fi
- srv_tgtobj="linux-low.o linux-osdata.o linux-m68k-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-m68k-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_usrregs=yes
srv_linux_regsets=yes
@@ -182,7 +202,10 @@ case "${target}" in
srv_regobj="${srv_regobj} mips-dsp-linux.o"
srv_regobj="${srv_regobj} mips64-linux.o"
srv_regobj="${srv_regobj} mips64-dsp-linux.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-mips-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o"
+ srv_tgtobj="${srv_tgtobj} linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-mips-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="mips-linux.xml"
srv_xmlfiles="${srv_xmlfiles} mips-dsp-linux.xml"
@@ -215,7 +238,9 @@ 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-osdata.o linux-ppc-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-ppc-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="rs6000/powerpc-32l.xml"
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
@@ -261,7 +286,9 @@ case "${target}" in
srv_regobj="${srv_regobj} s390x-linux64.o"
srv_regobj="${srv_regobj} s390x-linux64v1.o"
srv_regobj="${srv_regobj} s390x-linux64v2.o"
- srv_tgtobj="linux-low.o linux-osdata.o linux-s390-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-s390-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="s390-linux32.xml"
srv_xmlfiles="${srv_xmlfiles} s390-linux32v1.xml"
@@ -282,14 +309,18 @@ case "${target}" in
srv_linux_thread_db=yes
;;
sh*-*-linux*) srv_regobj=reg-sh.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-sh-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-sh-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.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-osdata.o linux-sparc-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-sparc-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
@@ -306,14 +337,19 @@ case "${target}" in
srv_xmlfiles="${srv_xmlfiles} tic6x-core.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-gp.xml"
srv_xmlfiles="${srv_xmlfiles} tic6x-c6xp.xml"
- srv_tgtobj="linux-low.o linux-osdata.o linux-tic6x-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-tic6x-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_regsets=yes
srv_linux_usrregs=yes
srv_linux_thread_db=yes
;;
x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj"
- srv_tgtobj="linux-low.o linux-osdata.o linux-x86-low.o i386-low.o i387-fp.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-x86-low.o"
+ srv_tgtobj="${srv_tgtobj} i386-low.o i387-fp.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_xmlfiles="$srv_i386_linux_xmlfiles $srv_amd64_linux_xmlfiles"
srv_linux_usrregs=yes # This is for i386 progs.
@@ -328,12 +364,17 @@ case "${target}" in
;;

xtensa*-*-linux*) srv_regobj=reg-xtensa.o
- srv_tgtobj="linux-low.o linux-osdata.o linux-xtensa-low.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-xtensa-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_regsets=yes
;;
tilegx-*-linux*) srv_regobj=reg-tilegx.o
- srv_tgtobj="linux-low.o linux-tile-low.o linux-osdata.o linux-procfs.o"
+ srv_tgtobj="linux-low.o linux-maps.o"
+ srv_tgtobj="${srv_tgtobj} linux-tile-low.o"
+ srv_tgtobj="${srv_tgtobj} linux-osdata.o"
+ srv_tgtobj="${srv_tgtobj} linux-procfs.o"
srv_tgtobj="${srv_tgtobj} linux-ptrace.o"
srv_linux_regsets=yes
srv_linux_thread_db=yes
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index c52cd2e..1b60821 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -20,6 +20,7 @@
#include "linux-low.h"
#include "linux-osdata.h"
#include "agent.h"
+#include "linux-maps.h"

#include "gdb_wait.h"
#include <stdio.h>
@@ -5633,6 +5634,154 @@ struct link_map_offsets
int l_prev_offset;
};

+
+
+
+
+struct find_memory_region_callback_data
+{
+ int is_elf64;
+ const char *soname;
+ CORE_ADDR l_addr;
+ size_t *build_idsz; /* Return. Meaningful iff *build_id != NULL. */
+ void **build_id; /* Return. malloc allocated memory. */
+};
+
+static linux_find_memory_region_ftype find_memory_region_callback;
+
+static int
+find_memory_region_callback (ULONGEST vaddr, ULONGEST size,
+ ULONGEST offset, ULONGEST inode,
+ int read, int write,
+ int exec, int modified,
+ const char *filename,
+ void *data)
+{
+ struct find_memory_region_callback_data *p = data;
+
+ if (filename != NULL && strcmp (filename, p->soname) == 0)
+ {
+ union ElfXX_Ehdr
+ {
+ Elf32_Ehdr _32;
+ Elf64_Ehdr _64;
+ } ehdr;
+ union ElfXX_Phdr
+ {
+ Elf32_Phdr _32;
+ Elf64_Phdr _64;
+ } phdr;
+ union ElfXX_Nhdr
+ {
+ Elf32_Nhdr _32;
+ Elf64_Nhdr _64;
+ } *nhdr = NULL;
+#ifdef HDR
+#error "HDR macro redefinition detected"
+#endif /* HDR */
+#define HDR(hdr, fld) ((p->is_elf64)? (hdr)._64.fld : (hdr)._32.fld)
+ if (linux_read_memory (vaddr, (unsigned char *)&ehdr, sizeof (ehdr))
+ == 0
+ && HDR(ehdr, e_ident[EI_MAG0]) == ELFMAG0
+ && HDR(ehdr, e_ident[EI_MAG1]) == ELFMAG1
+ && HDR(ehdr, e_ident[EI_MAG2]) == ELFMAG2
+ && HDR(ehdr, e_ident[EI_MAG3]) == ELFMAG3)
+ {
+ unsigned i;
+
+ for (i = 0; i != HDR (ehdr, e_phnum); ++i)
+ {
+ if (linux_read_memory (vaddr + HDR (ehdr, e_phoff)
+ + HDR (ehdr, e_phentsize) * i,
+ (unsigned char *) &phdr,
+ HDR (ehdr, e_phentsize)) != 0)
+ {
+ warning ("could not read program header");
+ break;
+ }
+ if (HDR(phdr, p_type) == PT_NOTE)
+ {
+ nhdr = xmalloc (HDR(phdr, p_memsz));
+
+ if (linux_read_memory (p->l_addr + HDR (phdr, p_vaddr),
+ (unsigned char *)nhdr,
+ HDR (phdr, p_memsz)) != 0)
+ {
+ warning ("could not read note");
+ break;
+ }
+ if (HDR (*nhdr, n_type) == NT_GNU_BUILD_ID)
+ {
+ *p->build_idsz = HDR (*nhdr, n_namesz)
+ + HDR (*nhdr, n_descsz)
+ + (p->is_elf64 ? sizeof (nhdr->_64)
+ : sizeof (nhdr->_32));
+ gdb_assert (*p->build_idsz <= HDR (phdr, p_memsz));
+ *p->build_id = (void*)nhdr;
+ break;
+ }
+ free (nhdr);
+ }
+ }
+ }
+ else
+ warning ("failed reading build-id\n");
+
+ return 1;
+ }
+#undef HDR
+ return 0;
+}
+
+
+/* Return malloc allocated buffer. User must free it.
+
+ NULL may be returned if build-id could not be
+ fetched. */
+
+static char *
+get_hex_build_id (const char *const soname, const int is_elf64,
+ const CORE_ADDR l_addr)
+{
+ struct find_memory_region_callback_data data;
+ void *raw_build_id = NULL;
+ size_t build_idsz = 0;
+ char *hex_build_id;
+ char *real_soname = realpath (soname, NULL);
+
+ if (real_soname == NULL)
+ {
+ fprintf (stderr, "Failed to get realpath of %s (%s)\n", soname,
+ strerror (errno));
+ return NULL;
+ }
+
+ data.is_elf64 = is_elf64;
+ data.soname = real_soname;
+ data.l_addr = l_addr;
+ data.build_idsz = &build_idsz;
+ data.build_id = &raw_build_id;
+
+ linux_find_memory_regions_full (lwpid_of (get_thread_lwp (current_inferior)),
+ find_memory_region_callback,
+ (void*)&data);
+ free (real_soname);
+ if (raw_build_id != NULL)
+ {
+ hex_build_id = xmalloc (build_idsz * 2 + 1);
+ if (bin2hex (raw_build_id, hex_build_id, build_idsz) != build_idsz)
+ {
+ fprintf (stderr, "Hex encoding of build-id failed\n");
+ xfree (hex_build_id);
+ hex_build_id = NULL;
+ }
+ }
+ else
+ hex_build_id = NULL;
+ free (raw_build_id);
+ return hex_build_id;
+}
+
/* Construct qXfer:libraries-svr4:read reply. */

static int
@@ -5754,6 +5903,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
/* 6x the size for xml_escape_text below. */
size_t len = 6 * strlen ((char *) libname);
char *name;
+ char *hex_enc_build_id;

if (!header_done)
{
@@ -5762,7 +5912,12 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
header_done = 1;
}

- while (allocated < p - document + len + 200)
+ name = xml_escape_text ((char *) libname);
+ hex_enc_build_id = get_hex_build_id (name, is_elf64, l_addr);
+
+ while (allocated < p - document + len + 215
+ + ((hex_enc_build_id != NULL)?
+ strlen (hex_enc_build_id) : 0))
{
/* Expand to guarantee sufficient storage. */
uintptr_t document_len = p - document;
@@ -5772,12 +5927,15 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
p = document + document_len;
}

- name = xml_escape_text ((char *) libname);
p += sprintf (p, "<library name=\"%s\" lm=\"0x%lx\" "
- "l_addr=\"0x%lx\" l_ld=\"0x%lx\"/>",
+ "l_addr=\"0x%lx\" l_ld=\"0x%lx\"",
name, (unsigned long) lm_addr,
(unsigned long) l_addr, (unsigned long) l_ld);
+ if (hex_enc_build_id != NULL)
+ p += sprintf (p, " build-id=\"%s\"", hex_enc_build_id);
+ p += sprintf(p, "%s", "/>");
free (name);
+ xfree (hex_enc_build_id);
}
else if (lm_prev == 0)
{
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 42c6a54..4828140 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -20,6 +20,7 @@
#include "terminal.h"
#include "target.h"
#include "gdbthread.h"
+#include "common-utils.h"
#include <stdio.h>
#include <string.h>
#if HAVE_SYS_IOCTL_H
@@ -418,18 +419,6 @@ remote_close (void)

/* Convert hex digit A to a number. */

-static int
-fromhex (int a)
-{
- if (a >= '0' && a <= '9')
- return a - '0';
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else
- error ("Reply contains invalid hex digit");
- return 0;
-}
-
#endif

static const char hexchars[] = "0123456789abcdef";
@@ -460,20 +449,7 @@ ishex (int ch, int *val)
int
unhexify (char *bin, const char *hex, int count)
{
- int i;
-
- for (i = 0; i < count; i++)
- {
- if (hex[0] == 0 || hex[1] == 0)
- {
- /* Hex string is short, or of uneven length.
- Return the count that has been converted so far. */
- return i;
- }
- *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
- hex += 2;
- }
- return i;
+ return hex2bin (hex, (gdb_byte*)bin, count);
}

void
@@ -511,35 +487,13 @@ decode_address_to_semicolon (CORE_ADDR *addrp, const char *start)

#endif

-/* Convert number NIB to a hex digit. */
-
-static int
-tohex (int nib)
-{
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
-}

#ifndef IN_PROCESS_AGENT

int
hexify (char *hex, const char *bin, int count)
{
- int i;
-
- /* May use a length, or a nul-terminated string as input. */
- if (count == 0)
- count = strlen (bin);
-
- for (i = 0; i < count; i++)
- {
- *hex++ = tohex ((*bin >> 4) & 0xf);
- *hex++ = tohex (*bin++ & 0xf);
- }
- *hex = 0;
- return i;
+ return bin2hex ((gdb_byte*)bin, hex, count);
}

/* Convert BUFFER, binary data at least LEN bytes long, into escaped
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 04afbb1..22dc4f0 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -33,6 +33,7 @@
#include "arch-utils.h"
#include "gdb_obstack.h"
#include "cli/cli-utils.h"
+#include "linux-maps.h"

#include <ctype.h>

@@ -207,46 +208,7 @@ linux_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
return normal_pid_to_str (ptid);
}

-/* Service function for corefiles and info proc. */

-static void
-read_mapping (const char *line,
- ULONGEST *addr, ULONGEST *endaddr,
- const char **permissions, size_t *permissions_len,
- ULONGEST *offset,
- const char **device, size_t *device_len,
- ULONGEST *inode,
- const char **filename)
-{
- const char *p = line;
-
- *addr = strtoulst (p, &p, 16);
- if (*p == '-')
- p++;
- *endaddr = strtoulst (p, &p, 16);
-
- while (*p && isspace (*p))
- p++;
- *permissions = p;
- while (*p && !isspace (*p))
- p++;
- *permissions_len = p - *permissions;
-
- *offset = strtoulst (p, &p, 16);
-
- while (*p && isspace (*p))
- p++;
- *device = p;
- while (*p && !isspace (*p))
- p++;
- *device_len = p - *device;
-
- *inode = strtoulst (p, &p, 10);
-
- while (*p && isspace (*p))
- p++;
- *filename = p;
-}

/* Implement the "info proc" command. */

@@ -666,101 +628,6 @@ linux_core_info_proc (struct gdbarch *gdbarch, char *args,
error (_("unable to handle request"));
}

-typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
- ULONGEST offset, ULONGEST inode,
- int read, int write,
- int exec, int modified,
- const char *filename,
- void *data);
-
-/* List memory regions in the inferior for a corefile. */
-
-static int
-linux_find_memory_regions_full (struct gdbarch *gdbarch,
- linux_find_memory_region_ftype *func,
- void *obfd)
-{
- char filename[100];
- gdb_byte *data;
-
- /* We need to know the real target PID to access /proc. */
- if (current_inferior ()->fake_pid_p)
- return 1;
-
- xsnprintf (filename, sizeof filename,
- "/proc/%d/smaps", current_inferior ()->pid);
- data = target_fileio_read_stralloc (filename);
- if (data == NULL)
- {
- /* Older Linux kernels did not support /proc/PID/smaps. */
- xsnprintf (filename, sizeof filename,
- "/proc/%d/maps", current_inferior ()->pid);
- data = target_fileio_read_stralloc (filename);
- }
- if (data)
- {
- struct cleanup *cleanup = make_cleanup (xfree, data);
- char *line;
-
- line = strtok (data, "\n");
- while (line)
- {
- ULONGEST addr, endaddr, offset, inode;
- const char *permissions, *device, *filename;
- size_t permissions_len, device_len;
- int read, write, exec;
- int modified = 0, has_anonymous = 0;
-
- read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
- &offset, &device, &device_len, &inode, &filename);
-
- /* Decode permissions. */
- read = (memchr (permissions, 'r', permissions_len) != 0);
- write = (memchr (permissions, 'w', permissions_len) != 0);
- exec = (memchr (permissions, 'x', permissions_len) != 0);
-
- /* Try to detect if region was modified by parsing smaps counters. */
- for (line = strtok (NULL, "\n");
- line && line[0] >= 'A' && line[0] <= 'Z';
- line = strtok (NULL, "\n"))
- {
- char keyword[64 + 1];
- unsigned long number;
-
- if (sscanf (line, "%64s%lu kB\n", keyword, &number) != 2)
- {
- warning (_("Error parsing {s,}maps file '%s'"), filename);
- break;
- }
- if (strcmp (keyword, "Anonymous:") == 0)
- has_anonymous = 1;
- if (number != 0 && (strcmp (keyword, "Shared_Dirty:") == 0
- || strcmp (keyword, "Private_Dirty:") == 0
- || strcmp (keyword, "Swap:") == 0
- || strcmp (keyword, "Anonymous:") == 0))
- modified = 1;
- }
-
- /* Older Linux kernels did not support the "Anonymous:" counter.
- If it is missing, we can't be sure - dump all the pages. */
- if (!has_anonymous)
- modified = 1;
-
- /* Invoke the callback function to create the corefile segment. */
- func (addr, endaddr - addr, offset, inode,
- read, write, exec, modified, filename, obfd);
- }
-
- do_cleanups (cleanup);
- return 0;
- }
-
- return 1;
-}
-
-/* A structure for passing information through
- linux_find_memory_regions_full. */
-
struct linux_find_memory_regions_data
{
/* The original callback. */
@@ -798,7 +665,10 @@ linux_find_memory_regions (struct gdbarch *gdbarch,
data.func = func;
data.obfd = obfd;

- return linux_find_memory_regions_full (gdbarch,
+ if (current_inferior ()->fake_pid_p)
+ return 1;
+
+ return linux_find_memory_regions_full (current_inferior ()->pid,
linux_find_memory_regions_thunk,
&data);
}
@@ -982,8 +852,10 @@ linux_make_mappings_corefile_notes (struct gdbarch *gdbarch, bfd *obfd,
pack_long (buf, long_type, 1);
obstack_grow (&data_obstack, buf, TYPE_LENGTH (long_type));

- linux_find_memory_regions_full (gdbarch, linux_make_mappings_callback,
- &mapping_data);
+ if (!current_inferior ()->fake_pid_p)
+ linux_find_memory_regions_full (current_inferior ()->pid,
+ linux_make_mappings_callback,
+ &mapping_data);

if (mapping_data.file_count != 0)
{
diff --git a/gdb/remote.c b/gdb/remote.c
index 88a57c8..cf5755d 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -123,8 +123,6 @@ static int readchar (int timeout);

static void remote_kill (struct target_ops *ops);

-static int tohex (int nib);
-
static int remote_can_async_p (void);

static int remote_is_async_p (void);
@@ -181,12 +179,6 @@ static void remote_find_new_threads (void);

static void record_currthread (ptid_t currthread);

-static int fromhex (int a);
-
-extern int hex2bin (const char *hex, gdb_byte *bin, int count);
-
-extern int bin2hex (const gdb_byte *bin, char *hex, int count);
-
static int putpkt_binary (char *buf, int cnt);

static void check_binary_download (CORE_ADDR addr);
@@ -4550,68 +4542,6 @@ extended_remote_attach (struct target_ops *ops, char *args, int from_tty)
extended_remote_attach_1 (ops, args, from_tty);
}

-/* Convert hex digit A to a number. */
-
-static int
-fromhex (int a)
-{
- if (a >= '0' && a <= '9')
- return a - '0';
- else if (a >= 'a' && a <= 'f')
- return a - 'a' + 10;
- else if (a >= 'A' && a <= 'F')
- return a - 'A' + 10;
- else
- error (_("Reply contains invalid hex digit %d"), a);
-}
-
-int
-hex2bin (const char *hex, gdb_byte *bin, int count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- {
- if (hex[0] == 0 || hex[1] == 0)
- {
- /* Hex string is short, or of uneven length.
- Return the count that has been converted so far. */
- return i;
- }
- *bin++ = fromhex (hex[0]) * 16 + fromhex (hex[1]);
- hex += 2;
- }
- return i;
-}
-
-/* Convert number NIB to a hex digit. */
-
-static int
-tohex (int nib)
-{
- if (nib < 10)
- return '0' + nib;
- else
- return 'a' + nib - 10;
-}
-
-int
-bin2hex (const gdb_byte *bin, char *hex, int count)
-{
- int i;
-
- /* May use a length, or a nul-terminated string as input. */
- if (count == 0)
- count = strlen ((char *) bin);
-
- for (i = 0; i < count; i++)
- {
- *hex++ = tohex ((*bin >> 4) & 0xf);
- *hex++ = tohex (*bin++ & 0xf);
- }
- *hex = 0;
- return i;
-}
\f
/* Check for the availability of vCont. This function should also check
the response. */
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index ca104aa..c4e6034 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -69,9 +69,6 @@
#define O_LARGEFILE 0
#endif

-extern int hex2bin (const char *hex, gdb_byte *bin, int count);
-extern int bin2hex (const gdb_byte *bin, char *hex, int count);
-
/* Maximum length of an agent aexpression.
This accounts for the fact that packets are limited to 400 bytes
(which includes everything -- including the checksum), and assumes
diff --git a/gdb/utils.c b/gdb/utils.c
index eb99f4b..484402c 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3309,104 +3309,6 @@ dummy_obstack_deallocate (void *object, void *data)
return;
}

-/* The bit offset of the highest byte in a ULONGEST, for overflow
- checking. */
-
-#define HIGH_BYTE_POSN ((sizeof (ULONGEST) - 1) * HOST_CHAR_BIT)
-
-/* True (non-zero) iff DIGIT is a valid digit in radix BASE,
- where 2 <= BASE <= 36. */
-
-static int
-is_digit_in_base (unsigned char digit, int base)
-{
- if (!isalnum (digit))
- return 0;
- if (base <= 10)
- return (isdigit (digit) && digit < base + '0');
- else
- return (isdigit (digit) || tolower (digit) < base - 10 + 'a');
-}
-
-static int
-digit_to_int (unsigned char c)
-{
- if (isdigit (c))
- return c - '0';
- else
- return tolower (c) - 'a' + 10;
-}
-
-/* As for strtoul, but for ULONGEST results. */
-
-ULONGEST
-strtoulst (const char *num, const char **trailer, int base)
-{
- unsigned int high_part;
- ULONGEST result;
- int minus = 0;
- int i = 0;
-
- /* Skip leading whitespace. */
- while (isspace (num[i]))
- i++;
-
- /* Handle prefixes. */
- if (num[i] == '+')
- i++;
- else if (num[i] == '-')
- {
- minus = 1;
- i++;
- }
-
- if (base == 0 || base == 16)
- {
- if (num[i] == '0' && (num[i + 1] == 'x' || num[i + 1] == 'X'))
- {
- i += 2;
- if (base == 0)
- base = 16;
- }
- }
-
- if (base == 0 && num[i] == '0')
- base = 8;
-
- if (base == 0)
- base = 10;
-
- if (base < 2 || base > 36)
- {
- errno = EINVAL;
- return 0;
- }
-
- result = high_part = 0;
- for (; is_digit_in_base (num[i], base); i += 1)
- {
- result = result * base + digit_to_int (num[i]);
- high_part = high_part * base + (unsigned int) (result >> HIGH_BYTE_POSN);
- result &= ((ULONGEST) 1 << HIGH_BYTE_POSN) - 1;
- if (high_part > 0xff)
- {
- errno = ERANGE;
- result = ~ (ULONGEST) 0;
- high_part = 0;
- minus = 0;
- break;
- }
- }
-
- if (trailer != NULL)
- *trailer = &num[i];
-
- result = result + ((ULONGEST) high_part << HIGH_BYTE_POSN);
- if (minus)
- return -result;
- else
- return result;
-}

/* Simple, portable version of dirname that does not modify its
argument. */
diff --git a/gdb/utils.h b/gdb/utils.h
index 52bcaff..a5b643c 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -39,8 +39,6 @@ extern int streq (const char *, const char *);

extern int subset_compare (char *, char *);

-ULONGEST strtoulst (const char *num, const char **trailer, int base);
-
int compare_positive_ints (const void *ap, const void *bp);
int compare_strings (const void *ap, const void *bp);

--
1.7.10.4

[-- Attachment #3: gdbserver-doc-201302271220.patch --]
[-- Type: text/x-patch, Size: 1313 bytes --]

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 5f39d2e..32e63e1 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -40144,6 +40144,9 @@ memory address. It is a displacement of absolute memory address against
address the file was prelinked to during the library load.
@item
@code{l_ld}, which is memory address of the @code{PT_DYNAMIC} segment
+@item
+@code{build-id}, hex encoded @code{.note.gnu.build-id} section, if such
+section exists.
@end itemize

Additionally the single @code{main-lm} attribute specifies address of
@@ -40161,7 +40164,8 @@ looks like this:
<library name="/lib/ld-linux.so.2" lm="0xe4f51c" l_addr="0xe2d000"
l_ld="0xe4eefc"/>
<library name="/lib/libc.so.6" lm="0xe4fbe8" l_addr="0x154000"
- l_ld="0x152350"/>
+ l_ld="0x152350" build-id="040000001400000003000000474e5500\
+ 829afccf7cc41e62934766d96223fe72480854e"/>
</library-list-svr>
@end smallexample

@@ -40177,6 +40181,7 @@ The format of an SVR4 library list is described by this DTD:
<!ATTLIST library lm CDATA #REQUIRED>
<!ATTLIST library l_addr CDATA #REQUIRED>
<!ATTLIST library l_ld CDATA #REQUIRED>
+<!ATTLIST library build-id CDATA #IMPLIED>
@end smallexample

@node Memory Map Format