From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 15884 invoked by alias); 27 Feb 2013 17:25:51 -0000 Received: (qmail 15793 invoked by uid 22791); 27 Feb 2013 17:25:47 -0000 X-SWARE-Spam-Status: No, hits=-3.6 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_CN,TW_EG,TW_XS X-Spam-Check-By: sourceware.org Received: from plane.gmane.org (HELO plane.gmane.org) (80.91.229.3) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Feb 2013 17:25:12 +0000 Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UAkl0-0004w2-En for gdb-patches@sourceware.org; Wed, 27 Feb 2013 18:25:30 +0100 Received: from cpe0013d4b66ebb-cmbc1401279e60.cpe.net.cable.rogers.com ([99.224.111.207]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 27 Feb 2013 18:25:30 +0100 Received: from aristovski by cpe0013d4b66ebb-cmbc1401279e60.cpe.net.cable.rogers.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 27 Feb 2013 18:25:30 +0100 To: gdb-patches@sourceware.org From: Aleksandar Ristovski Subject: Re: [patch] gdbserver build-id in qxfer_libraries reply Date: Wed, 27 Feb 2013 17:31:00 -0000 Message-ID: <512E4169.7080506@qnx.com> References: <51278984.3070208@qnx.com> <5127BB31.9040500@qnx.com> <512CA419.7020806@redhat.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------050501020809050908090306" Cc: "gdb-patches@sourceware.org" , Jan Kratochvil User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130221 Thunderbird/17.0.3 In-Reply-To: <512CA419.7020806@redhat.com> X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2013-02/txt/msg00693.txt.bz2 Message-ID: <20130227173100.EyD87XcSypQtn1AH0f1DPXQ8CNGYW9VlkSHV-QBbaTo@z> This is a multi-part message in MIME format. --------------050501020809050908090306 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 3704 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 * 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 * gdb.texinfo (Library List Format for SVR4 Targets): New 'build-id' attribute, add it to the example and document it in DTD. --------------050501020809050908090306 Content-Type: text/x-patch; name="gdbserver-build-id-in-qxfer_libraries-reply-201302271218.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="gdbserver-build-id-in-qxfer_libraries-reply-201302271218.pat"; filename*1="ch" Content-length: 42623 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 #include +#include +#include +#include /* 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; } + + +/* 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; +} + + +/* 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 . */ + + +#ifdef GDBSERVER +#include "server.h" +#include "linux-maps.h" +#include +#include +#else /* ! GDBSERVER */ +#include "defs.h" +#include "linux-maps.h" +#include "target.h" +#endif /* ! GDBSERVER */ + +#include + + +#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 . */ + +#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 @@ + 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 @@ -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, "", + "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 #include #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 @@ -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; -} /* 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 --------------050501020809050908090306 Content-Type: text/x-patch; name="gdbserver-doc-201302271220.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gdbserver-doc-201302271220.patch" Content-length: 1313 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: + l_ld="0x152350" build-id="040000001400000003000000474e5500\ + 829afccf7cc41e62934766d96223fe72480854e"/> @end smallexample @@ -40177,6 +40181,7 @@ The format of an SVR4 library list is described by this DTD: + @end smallexample @node Memory Map Format --------------050501020809050908090306--