public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v12 02/32] Move gdb_regex* to common/
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
@ 2015-08-21 21:20 ` Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 03/32] Prepare linux_find_memory_regions_full & co. for move Jan Kratochvil
                   ` (31 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

Later patches need regex support also in gdbserver.

gdb/ChangeLog
2015-07-15  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.in (HFILES_NO_SRCDIR): Change gdb_regex.h to
	common/gdb_regex.h.
	(COMMON_OBS): Add gdb_regex.o.
	(gdb_regex.o): New.
	* common/common.m4 (GDB_AC_COMMON): Add gdb_use_included_regex,
	--without-included-regex and USE_INCLUDED_REGEX.
	* common/gdb_regex.c: New file from utils.c functions.
	* common/gdb_regex.h: Move it here from gdb_regex.h, update include
	file wrapping define name.
	* configure: Rebuilt.
	* configure.ac (gdb_use_included_regex, --without-included-regex)
	(USE_INCLUDED_REGEX): Move them to common/common.m4.
	* gdb_regex.h: Move it to common/gdb_regex.h.
	* utils.c: Remove include gdb_regex.h.
	(do_regfree_cleanup, make_regfree_cleanup, get_regcomp_error)
	(compile_rx_or_error): Move them to common/gdb_regex.c.

gdb/gdbserver/ChangeLog
2015-07-15  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* Makefile.in (OBS): Add gdb_regex.o.
	(gdb_regex.o): New.
	* config.in: Rebuilt.
	* configure: Rebuilt.
---
 0 files changed

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 0527413..3247126 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -942,7 +942,7 @@ extension.h extension-priv.h nat/aarch64-linux-hw-point.h \
 build-id.h buildsym.h valprint.h \
 typeprint.h mi/mi-getopt.h mi/mi-parse.h mi/mi-console.h \
 mi/mi-out.h mi/mi-main.h mi/mi-common.h mi/mi-cmds.h linux-nat.h \
-complaints.h gdb_proc_service.h gdb_regex.h xtensa-tdep.h inf-loop.h \
+complaints.h gdb_proc_service.h common/gdb_regex.h xtensa-tdep.h inf-loop.h \
 common/gdb_wait.h common/gdb_assert.h solib.h ppc-tdep.h cp-support.h glibc-tdep.h \
 interps.h auxv.h gdbcmd.h tramp-frame.h mipsnbsd-tdep.h	\
 amd64-linux-tdep.h linespec.h location.h i387-tdep.h mn10300-tdep.h \
@@ -1087,6 +1087,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	format.o registry.o btrace.o record-btrace.o waitstatus.o \
 	print-utils.o rsp-low.o errors.o common-debug.o debug.o \
 	common-exceptions.o btrace-common.o fileio.o target-utils.o \
+	gdb_regex.o \
 	$(SUBDIR_GCC_COMPILE_OBS)
 
 TSOBS = inflow.o
@@ -2275,6 +2276,10 @@ btrace-common.o: ${srcdir}/common/btrace-common.c
 fileio.o: ${srcdir}/common/fileio.c
 	$(COMPILE) $(srcdir)/common/fileio.c
 	$(POSTCOMPILE)
+
+gdb_regex.o: ${srcdir}/common/gdb_regex.c
+	$(COMPILE) $(srcdir)/common/gdb_regex.c
+	$(POSTCOMPILE)
 #
 # gdb/target/ dependencies
 #
diff --git a/gdb/common/common.m4 b/gdb/common/common.m4
index a87579a..e48dd5a 100644
--- a/gdb/common/common.m4
+++ b/gdb/common/common.m4
@@ -44,4 +44,33 @@ gdb_cv_func_sigsetjmp=yes, gdb_cv_func_sigsetjmp=no)])
 if test $gdb_cv_func_sigsetjmp = yes; then
   AC_DEFINE(HAVE_SIGSETJMP, 1, [Define if sigsetjmp is available. ])
 fi
+
+  # Assume we'll default to using the included libiberty regex.
+  gdb_use_included_regex=yes
+
+  # However, if the system regex is GNU regex, then default to *not*
+  # using the included regex.
+  AC_CACHE_CHECK(
+    [for GNU regex],
+    [gdb_cv_have_gnu_regex],
+    [AC_TRY_COMPILE(
+      [#include <gnu-versions.h>],
+      [#define REGEX_INTERFACE_VERSION 1
+  #if _GNU_REGEX_INTERFACE_VERSION != REGEX_INTERFACE_VERSION
+  # error "Version mismatch"
+  #endif],
+      gdb_cv_have_gnu_regex=yes,
+      gdb_cv_have_gnu_regex=no)])
+  if test $gdb_cv_have_gnu_regex = yes; then
+    gdb_use_included_regex=no
+  fi
+
+  AC_ARG_WITH(included-regex,
+    AS_HELP_STRING([--without-included-regex], [don't use included regex; this is the default on systems with version 2 of the GNU C library (use with caution on other system)]),
+    gdb_with_regex=$withval,
+    gdb_with_regex=$gdb_use_included_regex)
+  if test "$gdb_with_regex" = yes; then
+    AC_DEFINE(USE_INCLUDED_REGEX, 1,
+      [Define to 1 if the regex included in libiberty should be used.])
+  fi
 ])
diff --git a/gdb/common/gdb_regex.c b/gdb/common/gdb_regex.c
new file mode 100644
index 0000000..73f30a7
--- /dev/null
+++ b/gdb/common/gdb_regex.c
@@ -0,0 +1,73 @@
+/* Shared utility routines for GDB to interact with agent.
+
+   Copyright (C) 2009-2015 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/>.  */
+
+#include "common-defs.h"
+#include "gdb_regex.h"
+
+/* A cleanup function that calls regfree.  */
+
+static void
+do_regfree_cleanup (void *r)
+{
+  regfree (r);
+}
+
+/* Create a new cleanup that frees the compiled regular expression R.  */
+
+struct cleanup *
+make_regfree_cleanup (regex_t *r)
+{
+  return make_cleanup (do_regfree_cleanup, r);
+}
+
+/* Return an xmalloc'd error message resulting from a regular
+   expression compilation failure.  */
+
+char *
+get_regcomp_error (int code, regex_t *rx)
+{
+  size_t length = regerror (code, rx, NULL, 0);
+  char *result = xmalloc (length);
+
+  regerror (code, rx, result, length);
+  return result;
+}
+
+/* Compile a regexp and throw an exception on error.  This returns a
+   cleanup to free the resulting pattern on success.  RX must not be
+   NULL.  */
+
+struct cleanup *
+compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
+{
+  int code;
+
+  gdb_assert (rx != NULL);
+
+  code = regcomp (pattern, rx, REG_NOSUB);
+  if (code != 0)
+    {
+      char *err = get_regcomp_error (code, pattern);
+
+      make_cleanup (xfree, err);
+      error (("%s: %s"), message, err);
+    }
+
+  return make_regfree_cleanup (pattern);
+}
diff --git a/gdb/common/gdb_regex.h b/gdb/common/gdb_regex.h
new file mode 100644
index 0000000..c6eb67b
--- /dev/null
+++ b/gdb/common/gdb_regex.h
@@ -0,0 +1,35 @@
+/* Portable <regex.h>.
+   Copyright (C) 2000-2015 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_GDB_REGEX_H
+#define COMMON_GDB_REGEX_H 1
+
+#ifdef USE_INCLUDED_REGEX
+# include "xregex.h"
+#else
+/* Request 4.2 BSD regex functions.  */
+# define _REGEX_RE_COMP
+# include <regex.h>
+#endif
+
+struct cleanup *make_regfree_cleanup (regex_t *);
+char *get_regcomp_error (int, regex_t *);
+struct cleanup *compile_rx_or_error (regex_t *pattern, const char *rx,
+				     const char *message);
+
+#endif /* not COMMON_GDB_REGEX_H */
diff --git a/gdb/configure b/gdb/configure
index e420c03..3e74b988 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -12378,6 +12378,57 @@ $as_echo "#define HAVE_SIGSETJMP 1" >>confdefs.h
 
 fi
 
+  # Assume we'll default to using the included libiberty regex.
+  gdb_use_included_regex=yes
+
+  # However, if the system regex is GNU regex, then default to *not*
+  # using the included regex.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU regex" >&5
+$as_echo_n "checking for GNU regex... " >&6; }
+if test "${gdb_cv_have_gnu_regex+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <gnu-versions.h>
+int
+main ()
+{
+#define REGEX_INTERFACE_VERSION 1
+  #if _GNU_REGEX_INTERFACE_VERSION != REGEX_INTERFACE_VERSION
+  # error "Version mismatch"
+  #endif
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gdb_cv_have_gnu_regex=yes
+else
+  gdb_cv_have_gnu_regex=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_have_gnu_regex" >&5
+$as_echo "$gdb_cv_have_gnu_regex" >&6; }
+  if test $gdb_cv_have_gnu_regex = yes; then
+    gdb_use_included_regex=no
+  fi
+
+
+# Check whether --with-included-regex was given.
+if test "${with_included_regex+set}" = set; then :
+  withval=$with_included_regex; gdb_with_regex=$withval
+else
+  gdb_with_regex=$gdb_use_included_regex
+fi
+
+  if test "$gdb_with_regex" = yes; then
+
+$as_echo "#define USE_INCLUDED_REGEX 1" >>confdefs.h
+
+  fi
+
 
 # Check the return and argument types of ptrace.
 
@@ -12683,57 +12734,6 @@ if test $ac_cv_func_setpgrp_void = yes; then
 fi
 fi
 
-# Assume we'll default to using the included libiberty regex.
-gdb_use_included_regex=yes
-
-# However, if the system regex is GNU regex, then default to *not*
-# using the included regex.
-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU regex" >&5
-$as_echo_n "checking for GNU regex... " >&6; }
-if test "${gdb_cv_have_gnu_regex+set}" = set; then :
-  $as_echo_n "(cached) " >&6
-else
-  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-#include <gnu-versions.h>
-int
-main ()
-{
-#define REGEX_INTERFACE_VERSION 1
-#if _GNU_REGEX_INTERFACE_VERSION != REGEX_INTERFACE_VERSION
-# error "Version mismatch"
-#endif
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
-  gdb_cv_have_gnu_regex=yes
-else
-  gdb_cv_have_gnu_regex=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_have_gnu_regex" >&5
-$as_echo "$gdb_cv_have_gnu_regex" >&6; }
-if test $gdb_cv_have_gnu_regex = yes; then
-  gdb_use_included_regex=no
-fi
-
-
-# Check whether --with-included-regex was given.
-if test "${with_included_regex+set}" = set; then :
-  withval=$with_included_regex; gdb_with_regex=$withval
-else
-  gdb_with_regex=$gdb_use_included_regex
-fi
-
-if test "$gdb_with_regex" = yes; then
-
-$as_echo "#define USE_INCLUDED_REGEX 1" >>confdefs.h
-
-fi
-
 # Check if <sys/proc.h> defines `struct thread' with a td_pcb member.
 ac_fn_c_check_member "$LINENO" "struct thread" "td_pcb" "ac_cv_member_struct_thread_td_pcb" "#include <sys/param.h>
 #include <sys/proc.h>
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 16bcd56..1669368 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -1391,35 +1391,6 @@ if test $ac_cv_func_setpgrp_void = yes; then
 fi
 fi
 
-# Assume we'll default to using the included libiberty regex.
-gdb_use_included_regex=yes
-
-# However, if the system regex is GNU regex, then default to *not*
-# using the included regex.
-AC_CACHE_CHECK(
-  [for GNU regex],
-  [gdb_cv_have_gnu_regex],
-  [AC_TRY_COMPILE(
-    [#include <gnu-versions.h>],
-    [#define REGEX_INTERFACE_VERSION 1
-#if _GNU_REGEX_INTERFACE_VERSION != REGEX_INTERFACE_VERSION
-# error "Version mismatch"
-#endif],
-    gdb_cv_have_gnu_regex=yes,
-    gdb_cv_have_gnu_regex=no)])
-if test $gdb_cv_have_gnu_regex = yes; then
-  gdb_use_included_regex=no
-fi
-
-AC_ARG_WITH(included-regex,
-  AS_HELP_STRING([--without-included-regex], [don't use included regex; this is the default on systems with version 2 of the GNU C library (use with caution on other system)]),
-  gdb_with_regex=$withval,
-  gdb_with_regex=$gdb_use_included_regex)
-if test "$gdb_with_regex" = yes; then
-  AC_DEFINE(USE_INCLUDED_REGEX, 1,
-    [Define to 1 if the regex included in libiberty should be used.])
-fi
-
 # Check if <sys/proc.h> defines `struct thread' with a td_pcb member.
 AC_CHECK_MEMBERS([struct thread.td_pcb], [], [],
 [#include <sys/param.h>
diff --git a/gdb/gdb_regex.h b/gdb/gdb_regex.h
deleted file mode 100644
index 3173a54..0000000
--- a/gdb/gdb_regex.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* Portable <regex.h>.
-   Copyright (C) 2000-2015 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 GDB_REGEX_H
-#define GDB_REGEX_H 1
-
-#ifdef USE_INCLUDED_REGEX
-# include "xregex.h"
-#else
-/* Request 4.2 BSD regex functions.  */
-# define _REGEX_RE_COMP
-# include <regex.h>
-#endif
-
-/* From utils.c.  */
-struct cleanup *make_regfree_cleanup (regex_t *);
-char *get_regcomp_error (int, regex_t *);
-struct cleanup *compile_rx_or_error (regex_t *pattern, const char *rx,
-				     const char *message);
-
-#endif /* not GDB_REGEX_H */
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 55dd1f6..ca43edc 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -195,6 +195,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
       common-exceptions.o symbol.o btrace-common.o fileio.o target-utils.o \
+      gdb_regex.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -582,6 +583,9 @@ waitstatus.o: ../target/waitstatus.c
 fileio.o: ../common/fileio.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+gdb_regex.o: ../common/gdb_regex.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 
 # Native object files rules from ../nat
 
diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in
index e2566a9..75b7f95 100644
--- a/gdb/gdbserver/config.in
+++ b/gdb/gdbserver/config.in
@@ -342,6 +342,9 @@
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
 
+/* Define to 1 if the regex included in libiberty should be used. */
+#undef USE_INCLUDED_REGEX
+
 /* Define if we should use libthread_db directly. */
 #undef USE_LIBTHREAD_DB_DIRECTLY
 
diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure
index 409f42b..166f6d5 100755
--- a/gdb/gdbserver/configure
+++ b/gdb/gdbserver/configure
@@ -694,6 +694,7 @@ enable_maintainer_mode
 enable_largefile
 enable_build_with_cxx
 enable_libmcheck
+with_included_regex
 with_ust
 with_ust_include
 with_ust_lib
@@ -1345,6 +1346,10 @@ Optional Features:
 Optional Packages:
   --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]
   --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)
+  --without-included-regex
+                          don't use included regex; this is the default on
+                          systems with version 2 of the GNU C library (use
+                          with caution on other system)
   --with-ust=PATH       Specify prefix directory for the installed UST package
                           Equivalent to --with-ust-include=PATH/include
                           plus --with-ust-lib=PATH/lib
@@ -5792,6 +5797,57 @@ $as_echo "#define HAVE_SIGSETJMP 1" >>confdefs.h
 
 fi
 
+  # Assume we'll default to using the included libiberty regex.
+  gdb_use_included_regex=yes
+
+  # However, if the system regex is GNU regex, then default to *not*
+  # using the included regex.
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU regex" >&5
+$as_echo_n "checking for GNU regex... " >&6; }
+if test "${gdb_cv_have_gnu_regex+set}" = set; then :
+  $as_echo_n "(cached) " >&6
+else
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+#include <gnu-versions.h>
+int
+main ()
+{
+#define REGEX_INTERFACE_VERSION 1
+  #if _GNU_REGEX_INTERFACE_VERSION != REGEX_INTERFACE_VERSION
+  # error "Version mismatch"
+  #endif
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  gdb_cv_have_gnu_regex=yes
+else
+  gdb_cv_have_gnu_regex=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gdb_cv_have_gnu_regex" >&5
+$as_echo "$gdb_cv_have_gnu_regex" >&6; }
+  if test $gdb_cv_have_gnu_regex = yes; then
+    gdb_use_included_regex=no
+  fi
+
+
+# Check whether --with-included-regex was given.
+if test "${with_included_regex+set}" = set; then :
+  withval=$with_included_regex; gdb_with_regex=$withval
+else
+  gdb_with_regex=$gdb_use_included_regex
+fi
+
+  if test "$gdb_with_regex" = yes; then
+
+$as_echo "#define USE_INCLUDED_REGEX 1" >>confdefs.h
+
+  fi
+
 
 # Check the return and argument types of ptrace.
 
diff --git a/gdb/utils.c b/gdb/utils.c
index e5ad195..41dca7f 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -67,7 +67,6 @@
 
 #include "gdb_usleep.h"
 #include "interps.h"
-#include "gdb_regex.h"
 
 #if !HAVE_DECL_MALLOC
 extern PTR malloc ();		/* ARI: PTR */
@@ -1114,60 +1113,6 @@ make_hex_string (const gdb_byte *data, size_t length)
 
 \f
 
-/* A cleanup function that calls regfree.  */
-
-static void
-do_regfree_cleanup (void *r)
-{
-  regfree (r);
-}
-
-/* Create a new cleanup that frees the compiled regular expression R.  */
-
-struct cleanup *
-make_regfree_cleanup (regex_t *r)
-{
-  return make_cleanup (do_regfree_cleanup, r);
-}
-
-/* Return an xmalloc'd error message resulting from a regular
-   expression compilation failure.  */
-
-char *
-get_regcomp_error (int code, regex_t *rx)
-{
-  size_t length = regerror (code, rx, NULL, 0);
-  char *result = xmalloc (length);
-
-  regerror (code, rx, result, length);
-  return result;
-}
-
-/* Compile a regexp and throw an exception on error.  This returns a
-   cleanup to free the resulting pattern on success.  RX must not be
-   NULL.  */
-
-struct cleanup *
-compile_rx_or_error (regex_t *pattern, const char *rx, const char *message)
-{
-  int code;
-
-  gdb_assert (rx != NULL);
-
-  code = regcomp (pattern, rx, REG_NOSUB);
-  if (code != 0)
-    {
-      char *err = get_regcomp_error (code, pattern);
-
-      make_cleanup (xfree, err);
-      error (("%s: %s"), message, err);
-    }
-
-  return make_regfree_cleanup (pattern);
-}
-
-\f
-
 /* This function supports the query, nquery, and yquery functions.
    Ask user a y-or-n question and return 0 if answer is no, 1 if
    answer is yes, or default the answer to the specified default

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 01/32] Create empty common/linux-maps.[ch] and common/target-utils.[ch]
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 02/32] Move gdb_regex* to common/ Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 03/32] Prepare linux_find_memory_regions_full & co. for move Jan Kratochvil
@ 2015-08-21 21:20 ` Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 04/32] Move linux_find_memory_regions_full & co Jan Kratochvil
                   ` (29 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

Prepare new files for later move.

gdb/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Create empty common/linux-maps.[ch] and common/target-utils.[ch].
	* Makefile.in (ALL_TARGET_OBS): Add linux-maps.o.
	(HFILES_NO_SRCDIR); Add common/linux-maps.h,
	common/target-utils.h.
	(COMMON_OBS): Add target-utils.o.
	(linux-maps.o, target-utils.o): New.
	* target/target-utils.c: New file.
	* target/target-utils.h: New file.
	* common/linux-maps.c: New file.
	* common/linux-maps.h: New file.
	* configure.tgt (aarch64*-*-linux*, alpha*-*-linux*)
	(am33_2.0*-*-linux*, arm*-*-linux*, bfin-*-*linux*, cris*, frv-*-*)
	(hppa*-*-linux*, i[34567]86-*-linux*, ia64-*-linux*, m32r*-*-linux*)
	(m68*-*-linux*, microblaze*-linux-*, microblaze*-*-linux*)
	(mips*-*-linux*, nios2*-*-linux*, powerpc*-*-linux*, s390*-*-linux*)
	(sh*-*-linux*, sparc-*-linux*, sparc64-*-linux*, tic6x-*-*linux)
	(tilegx-*-linux*, x86_64-*-linux*, xtensa*-*-linux*): Add linux-maps.o
	to gdb_target_obs.

gdb/gdbserver/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Create empty common/linux-maps.[ch] and common/target-utils.[ch].
	* Makefile.in (OBS): Add target-utils.o.
	(linux-maps.o, target-utils.o): New.
	* configure.srv (srv_linux_obj): Add linux-maps.o.
---
 0 files changed

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 13b9041..0527413 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -721,7 +721,8 @@ ALL_TARGET_OBS = \
 	symfile-mem.o \
 	windows-tdep.o \
 	linux-record.o \
-	ravenscar-thread.o
+	ravenscar-thread.o \
+	linux-maps.o
 
 # Host-dependent makefile fragment comes in here.
 @host_makefile_frag@
@@ -907,7 +908,7 @@ LINTFILES = $(SFILES) $(YYFILES) $(CONFIG_SRCS) init.c
 # right, it is probably easiest just to list .h files here directly.
 
 HFILES_NO_SRCDIR = \
-common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.h \
+common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.h common/linux-maps.h \
 common/x86-xstate.h nat/linux-ptrace.h nat/mips-linux-watch.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 \
@@ -987,7 +988,7 @@ common/common-debug.h common/cleanups.h common/gdb_setjmp.h \
 common/common-exceptions.h target/target.h common/symbol.h \
 common/common-regcache.h fbsd-tdep.h nat/linux-personality.h \
 common/fileio.h nat/x86-linux.h nat/x86-linux-dregs.h \
-nat/linux-namespaces.h arch/arm.h
+nat/linux-namespaces.h arch/arm.h target/target-utils.h
 
 # Header files that already have srcdir in them, or which are in objdir.
 
@@ -1085,7 +1086,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	common-utils.o buffer.o ptid.o gdb-dlfcn.o common-agent.o \
 	format.o registry.o btrace.o record-btrace.o waitstatus.o \
 	print-utils.o rsp-low.o errors.o common-debug.o debug.o \
-	common-exceptions.o btrace-common.o fileio.o \
+	common-exceptions.o btrace-common.o fileio.o target-utils.o \
 	$(SUBDIR_GCC_COMPILE_OBS)
 
 TSOBS = inflow.o
@@ -2223,6 +2224,10 @@ common-agent.o: $(srcdir)/common/agent.c
 	$(COMPILE) $(srcdir)/common/agent.c
 	$(POSTCOMPILE)
 
+linux-maps.o: ${srcdir}/common/linux-maps.c
+	$(COMPILE) $(srcdir)/common/linux-maps.c
+	$(POSTCOMPILE)
+
 vec.o: ${srcdir}/common/vec.c
 	$(COMPILE) $(srcdir)/common/vec.c
 	$(POSTCOMPILE)
@@ -2239,6 +2244,10 @@ errors.o: ${srcdir}/common/errors.c
 	$(COMPILE) $(srcdir)/common/errors.c
 	$(POSTCOMPILE)
 
+target-utils.o: ${srcdir}/target/target-utils.c
+	$(COMPILE) $(srcdir)/target/target-utils.c
+	$(POSTCOMPILE)
+
 common-debug.o: ${srcdir}/common/common-debug.c
 	$(COMPILE) $(srcdir)/common/common-debug.c
 	$(POSTCOMPILE)
diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c
new file mode 100644
index 0000000..01c8836
--- /dev/null
+++ b/gdb/common/linux-maps.c
@@ -0,0 +1,20 @@
+/* Linux-specific memory maps manipulation routines.
+   Copyright (C) 2015 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/>.  */
+
+#include "common-defs.h"
+#include "linux-maps.h"
diff --git a/gdb/common/linux-maps.h b/gdb/common/linux-maps.h
new file mode 100644
index 0000000..4228674
--- /dev/null
+++ b/gdb/common/linux-maps.h
@@ -0,0 +1,22 @@
+/* Linux-specific memory maps manipulation routines.
+   Copyright (C) 2015 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
+
+#endif /* COMMON_LINUX_MAPS_H */
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index f2c1a2d..20873c3 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -45,7 +45,7 @@ aarch64*-*-linux*)
 	# Target: AArch64 linux
 	gdb_target_obs="aarch64-tdep.o aarch64-linux-tdep.o \
 			arm-tdep.o arm-linux-tdep.o \
-			glibc-tdep.o linux-tdep.o solib-svr4.o \
+			glibc-tdep.o linux-tdep.o linux-maps.o solib-svr4.o \
 			symfile-mem.o linux-record.o"
 	build_gdbserver=yes
 	;;
@@ -53,7 +53,7 @@ aarch64*-*-linux*)
 alpha*-*-linux*)
 	# Target: Little-endian Alpha running Linux
 	gdb_target_obs="alpha-tdep.o alpha-mdebug-tdep.o alpha-linux-tdep.o \
-			linux-tdep.o solib-svr4.o"
+			linux-tdep.o linux-maps.o solib-svr4.o"
 	;;
 alpha*-*-freebsd* | alpha*-*-kfreebsd*-gnu)
 	# Target: FreeBSD/alpha
@@ -79,7 +79,7 @@ alpha*-*-*)
 am33_2.0*-*-linux*)
 	# Target: Matsushita mn10300 (AM33) running Linux
 	gdb_target_obs="mn10300-tdep.o mn10300-linux-tdep.o linux-tdep.o \
-			solib-svr4.o"
+			linux-maps.o solib-svr4.o"
 	;;
 
 arm*-wince-pe | arm*-*-mingw32ce*)
@@ -90,7 +90,8 @@ arm*-wince-pe | arm*-*-mingw32ce*)
 arm*-*-linux*)
 	# Target: ARM based machine running GNU/Linux
 	gdb_target_obs="arm-tdep.o arm-linux-tdep.o glibc-tdep.o \
-			solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
+			solib-svr4.o symfile-mem.o linux-tdep.o linux-maps.o \
+			linux-record.o"
 	build_gdbserver=yes
 	;;
 arm*-*-netbsd* | arm*-*-knetbsd*-gnu)
@@ -120,7 +121,7 @@ avr-*-*)
 
 bfin-*-*linux*)
 	# Target: Blackfin Linux
-	gdb_target_obs="bfin-tdep.o bfin-linux-tdep.o linux-tdep.o"
+	gdb_target_obs="bfin-tdep.o bfin-linux-tdep.o linux-tdep.o linux-maps.o"
 	gdb_sim=../sim/bfin/libsim.a
 	build_gdbserver=yes
 	;;
@@ -132,12 +133,14 @@ bfin-*-*)
 
 cris*)
 	# Target: CRIS
-	gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o solib-svr4.o"
+	gdb_target_obs="cris-tdep.o cris-linux-tdep.o linux-tdep.o \
+			linux-maps.o solib-svr4.o"
 	;;
 
 frv-*-*)
 	# Target: Fujitsu FRV processor
-	gdb_target_obs="frv-tdep.o frv-linux-tdep.o linux-tdep.o solib-frv.o"
+	gdb_target_obs="frv-tdep.o frv-linux-tdep.o linux-tdep.o linux-maps.o \
+			solib-frv.o"
 	gdb_sim=../sim/frv/libsim.a
 	;;
 
@@ -155,7 +158,7 @@ h8300-*-*)
 hppa*-*-linux*)
 	# Target: HP PA-RISC running Linux
 	gdb_target_obs="hppa-tdep.o hppa-linux-tdep.o glibc-tdep.o \
-			linux-tdep.o solib-svr4.o symfile-mem.o"
+			linux-tdep.o linux-maps.o solib-svr4.o symfile-mem.o"
 	;;
 hppa*-*-netbsd*)
 	# Target: NetBSD/hppa
@@ -218,7 +221,7 @@ i[34567]86-*-linux*)
 	# Target: Intel 386 running GNU/Linux
 	gdb_target_obs="i386-tdep.o i386-linux-tdep.o glibc-tdep.o i387-tdep.o \
 			solib-svr4.o symfile-mem.o \
-			linux-tdep.o linux-record.o"
+			linux-tdep.o linux-maps.o linux-record.o"
 	if test "x$enable_64_bit_bfd" = "xyes"; then
 	    # Target: GNU/Linux x86-64
 	    gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o ${gdb_target_obs}"
@@ -249,7 +252,7 @@ i[34567]86-*-*)
 ia64-*-linux*)
 	# Target: Intel IA-64 running GNU/Linux
 	gdb_target_obs="ia64-tdep.o ia64-linux-tdep.o linux-tdep.o \
-			solib-svr4.o symfile-mem.o"
+			linux-maps.o solib-svr4.o symfile-mem.o"
 	build_gdbserver=yes
 	;;
 ia64-*-*vms*)
@@ -283,7 +286,7 @@ m32r*-*-linux*)
 	# Target: Renesas M32R running GNU/Linux
 	gdb_target_obs="m32r-tdep.o m32r-linux-tdep.o remote-m32r-sdi.o \
 			glibc-tdep.o solib-svr4.o symfile-mem.o \
-			linux-tdep.o"
+			linux-tdep.o linux-maps.o"
 	gdb_sim=../sim/m32r/libsim.a
 	build_gdbserver=yes
 	;;
@@ -308,7 +311,7 @@ fido-*-elf*)
 m68*-*-linux*)
 	# Target: Motorola m68k with a.out and ELF
 	gdb_target_obs="m68k-tdep.o m68klinux-tdep.o solib-svr4.o \
-			linux-tdep.o glibc-tdep.o symfile-mem.o"
+			linux-tdep.o linux-maps.o glibc-tdep.o symfile-mem.o"
 	build_gdbserver=yes
 	;;
 m68*-*-netbsd* | m68*-*-knetbsd*-gnu)
@@ -334,7 +337,8 @@ mep-*-*)
 microblaze*-linux-*|microblaze*-*-linux*)
 	# Target: Xilinx MicroBlaze running Linux
 	gdb_target_obs="microblaze-tdep.o microblaze-linux-tdep.o microblaze-rom.o \
-			monitor.o dsrec.o solib-svr4.o symfile-mem.o linux-tdep.o"
+			monitor.o dsrec.o solib-svr4.o symfile-mem.o \
+			linux-tdep.o linux-maps.o"
 	gdb_sim=../sim/microblaze/libsim.a
 	;;
 microblaze*-*-*)
@@ -346,7 +350,7 @@ microblaze*-*-*)
 mips*-*-linux*)
 	# Target: Linux/MIPS
 	gdb_target_obs="mips-tdep.o mips-linux-tdep.o glibc-tdep.o \
-			solib-svr4.o symfile-mem.o linux-tdep.o"
+			solib-svr4.o symfile-mem.o linux-tdep.o linux-maps.o"
 	gdb_sim=../sim/mips/libsim.a
 	build_gdbserver=yes
 	;;
@@ -394,7 +398,7 @@ mt-*-*)
 nios2*-*-linux*)
 	# Target: Altera Nios II running Linux
 	gdb_target_obs="nios2-tdep.o nios2-linux-tdep.o solib-svr4.o \
-			symfile-mem.o glibc-tdep.o linux-tdep.o"
+			symfile-mem.o glibc-tdep.o linux-tdep.o linux-maps.o"
 	;;
 
 nios2*-*-*)
@@ -433,7 +437,7 @@ powerpc*-*-linux*)
 	gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \
 			ppc64-tdep.o solib-svr4.o solib-spu.o \
 			spu-multiarch.o \
-			glibc-tdep.o symfile-mem.o linux-tdep.o \
+			glibc-tdep.o symfile-mem.o linux-tdep.o linux-maps.o \
 			ravenscar-thread.o ppc-ravenscar-thread.o \
 			linux-record.o "
 	gdb_sim=../sim/ppc/libsim.a
@@ -457,7 +461,7 @@ powerpc*-*-*)
 
 s390*-*-linux*)
 	# Target: S390 running Linux
-	gdb_target_obs="s390-linux-tdep.o solib-svr4.o linux-tdep.o"
+	gdb_target_obs="s390-linux-tdep.o solib-svr4.o linux-tdep.o linux-maps.o"
 	build_gdbserver=yes
 	;;
 
@@ -486,7 +490,7 @@ sh*-*-linux*)
 	# Target: GNU/Linux Super-H
 	gdb_target_obs="sh-tdep.o sh64-tdep.o sh-linux-tdep.o monitor.o \
 			dsrec.o solib-svr4.o symfile-mem.o \
-			glibc-tdep.o linux-tdep.o"
+			glibc-tdep.o linux-tdep.o linux-maps.o"
 	gdb_sim=../sim/sh/libsim.a
 	build_gdbserver=yes
 	;;
@@ -514,7 +518,7 @@ sparc-*-linux*)
 	# Target: GNU/Linux SPARC
 	gdb_target_obs="sparc-tdep.o sparc-sol2-tdep.o sol2-tdep.o \
 			sparc-linux-tdep.o solib-svr4.o symfile-mem.o \
-			linux-tdep.o \
+			linux-tdep.o linux-maps.o \
 			ravenscar-thread.o sparc-ravenscar-thread.o"
 	if test "x$enable_64_bit_bfd" = "xyes"; then
 	    # Target: GNU/Linux UltraSPARC
@@ -528,7 +532,8 @@ sparc64-*-linux*)
 	gdb_target_obs="sparc64-tdep.o sparc64-sol2-tdep.o sol2-tdep.o \
 			sparc64-linux-tdep.o sparc-tdep.o sparc-sol2-tdep.o \
 			sparc-linux-tdep.o solib-svr4.o linux-tdep.o \
-			ravenscar-thread.o sparc-ravenscar-thread.o"
+			linux-maps.o ravenscar-thread.o \
+			sparc-ravenscar-thread.o"
 	build_gdbserver=yes
 	;;
 sparc*-*-freebsd* | sparc*-*-kfreebsd*-gnu)
@@ -595,7 +600,7 @@ spu*-*-*)
 tic6x-*-*linux)
 	# Target: GNU/Linux TI C6x
 	gdb_target_obs="tic6x-tdep.o tic6x-linux-tdep.o solib-dsbt.o \
-			glibc-tdep.o linux-tdep.o"
+			glibc-tdep.o linux-tdep.o linux-maps.o"
 	;;
 
 tic6x-*-*)
@@ -606,7 +611,7 @@ tic6x-*-*)
 tilegx-*-linux*)
 	# Target: TILE-Gx
 	gdb_target_obs="tilegx-tdep.o tilegx-linux-tdep.o solib-svr4.o \
-			symfile-mem.o glibc-tdep.o linux-tdep.o"
+			symfile-mem.o glibc-tdep.o linux-tdep.o linux-maps.o"
 	build_gdbserver=yes
 	;;
 
@@ -656,7 +661,8 @@ x86_64-*-linux*)
 	# Target: GNU/Linux x86-64
 	gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o i386-tdep.o \
 			i387-tdep.o i386-linux-tdep.o glibc-tdep.o \
-			solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o"
+			solib-svr4.o symfile-mem.o linux-tdep.o linux-maps.o \
+			linux-record.o"
 	build_gdbserver=yes
 	;;
 x86_64-*-freebsd* | x86_64-*-kfreebsd*-gnu)
@@ -686,7 +692,7 @@ x86_64-*-openbsd*)
 xtensa*-*-linux*)	gdb_target=linux
 	# Target: GNU/Linux Xtensa
 	gdb_target_obs="xtensa-tdep.o xtensa-config.o xtensa-linux-tdep.o \
-			solib-svr4.o symfile-mem.o linux-tdep.o"
+			solib-svr4.o symfile-mem.o linux-tdep.o linux-maps.o"
 	build_gdbserver=yes
 	;;
 xtensa*)
diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 5e04e530..55dd1f6 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -194,7 +194,7 @@ OBS = agent.o ax.o inferiors.o regcache.o remote-utils.o server.o signals.o \
       mem-break.o hostio.o event-loop.o tracepoint.o xml-utils.o \
       common-utils.o ptid.o buffer.o format.o filestuff.o dll.o notif.o \
       tdesc.o print-utils.o rsp-low.o errors.o common-debug.o cleanups.o \
-      common-exceptions.o symbol.o btrace-common.o fileio.o \
+      common-exceptions.o symbol.o btrace-common.o fileio.o target-utils.o \
       $(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
 GDBREPLAY_OBS = gdbreplay.o version.o
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
@@ -519,6 +519,9 @@ ax.o: ax.c
 signals.o: ../common/signals.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+linux-maps.o: ../common/linux-maps.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 print-utils.o: ../common/print-utils.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
@@ -531,6 +534,9 @@ common-utils.o: ../common/common-utils.c
 posix-strerror.o: ../common/posix-strerror.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
+target-utils.o: ../target/target-utils.c
+	$(COMPILE) $<
+	$(POSTCOMPILE)
 mingw-strerror.o: ../common/mingw-strerror.c
 	$(COMPILE) $<
 	$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 320c26a..757e72e 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -42,7 +42,7 @@ srv_amd64_linux_xmlfiles="i386/amd64-linux.xml i386/amd64-avx-linux.xml i386/amd
 
 # Linux object files.  This is so we don't have to repeat
 # these files over and over again.
-srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o"
+srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-maps.o linux-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o"
 
 # Input is taken from the "${target}" variable.
 
diff --git a/gdb/target/target-utils.c b/gdb/target/target-utils.c
new file mode 100644
index 0000000..4e8fae7
--- /dev/null
+++ b/gdb/target/target-utils.c
@@ -0,0 +1,21 @@
+/* Utility target functions for GDB, and GDBserver.
+
+   Copyright (C) 2015 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/>.  */
+
+#include "common-defs.h"
+#include "target/target-utils.h"
diff --git a/gdb/target/target-utils.h b/gdb/target/target-utils.h
new file mode 100644
index 0000000..443ffc3
--- /dev/null
+++ b/gdb/target/target-utils.h
@@ -0,0 +1,23 @@
+/* Utility target functions for GDB, and GDBserver.
+
+   Copyright (C) 2015 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 TARGET_TARGET_UTILS_H
+#define TARGET_TARGET_UTILS_H
+
+#endif /* TARGET_TARGET_UTILS_H */

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 03/32] Prepare linux_find_memory_regions_full & co. for move
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 02/32] Move gdb_regex* to common/ Jan Kratochvil
@ 2015-08-21 21:20 ` Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 01/32] Create empty common/linux-maps.[ch] and common/target-utils.[ch] Jan Kratochvil
                   ` (30 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

Prepare code for move into gdb/common/.

gdb/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Prepare linux_find_memory_regions_full & co. for move.
	* linux-tdep.c (linux_find_memory_region_ftype): Comment.
	(linux_find_memory_regions_full): Change signature and prepare
	for moving to linux-maps.
	(linux_find_memory_regions_data): Rename field 'obfd' to 'data'.
	(linux_find_memory_regions_thunk): New.
	(linux_find_memory_regions_thunk): Use 'data' field instead of 'obfd'.
	(linux_find_memory_regions_gdb): New.
	(linux_find_memory_regions): Rename argument 'obfd' to 'func_data'.
	(linux_make_mappings_corefile_notes): Use
	linux_find_memory_regions_gdb.
	* target.c (read_alloc_pread_ftype): New typedef.
	(target_fileio_read_alloc_1_pread): New function.
	(read_alloc): Refactor from target_fileio_read_alloc_1.
	(read_stralloc_func_ftype): New typedef.
	(target_fileio_read_alloc_1): New implementation. Use read_alloc.
	(read_stralloc): Refactored from target_fileio_read_stralloc.
	(target_fileio_read_stralloc): New implementation, use read_stralloc.
---
 0 files changed

diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index ff3ada7..982599e 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -1098,6 +1098,10 @@ linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
     error (_("unable to handle request"));
 }
 
+/* Callback function for linux_find_memory_regions_full.  If it returns
+   non-zero linux_find_memory_regions_full returns immediately with that
+   value.  */
+
 typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
 					    ULONGEST offset, ULONGEST inode,
 					    int read, int write,
@@ -1105,43 +1109,22 @@ typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
 					    const char *filename,
 					    void *data);
 
-/* List memory regions in the inferior for a corefile.  */
+/* List memory regions in the inferior PID matched to FILTERFLAGS for
+   a corefile.  Call FUNC with FUNC_DATA for each such region.  Return
+   immediately with the value returned by FUNC if it is non-zero.
+   *MEMORY_TO_FREE_PTR should be registered to be freed automatically if
+   called FUNC throws an exception.  MEMORY_TO_FREE_PTR can be also
+   passed as NULL if it is not used.  Return -1 if error occurs, 0 if
+   all memory regions have been processed or return the value from FUNC
+   if FUNC returns non-zero.  */
 
 static int
-linux_find_memory_regions_full (struct gdbarch *gdbarch,
+linux_find_memory_regions_full (pid_t pid, enum filterflags filterflags,
 				linux_find_memory_region_ftype *func,
-				void *obfd)
+				void *func_data)
 {
   char mapsfilename[100];
-  char coredumpfilter_name[100];
-  char *data, *coredumpfilterdata;
-  pid_t pid;
-  /* Default dump behavior of coredump_filter (0x33), according to
-     Documentation/filesystems/proc.txt from the Linux kernel
-     tree.  */
-  enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
-				  | COREFILTER_ANON_SHARED
-				  | COREFILTER_ELF_HEADERS
-				  | COREFILTER_HUGETLB_PRIVATE);
-
-  /* We need to know the real target PID to access /proc.  */
-  if (current_inferior ()->fake_pid_p)
-    return 1;
-
-  pid = current_inferior ()->pid;
-
-  if (use_coredump_filter)
-    {
-      xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
-		 "/proc/%d/coredump_filter", pid);
-      coredumpfilterdata = target_fileio_read_stralloc (NULL,
-							coredumpfilter_name);
-      if (coredumpfilterdata != NULL)
-	{
-	  sscanf (coredumpfilterdata, "%x", &filterflags);
-	  xfree (coredumpfilterdata);
-	}
-    }
+  char *data;
 
   xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", pid);
   data = target_fileio_read_stralloc (NULL, mapsfilename);
@@ -1156,6 +1139,7 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
     {
       struct cleanup *cleanup = make_cleanup (xfree, data);
       char *line, *t;
+      int retval = 0;
 
       line = strtok_r (data, "\n", &t);
       while (line != NULL)
@@ -1270,17 +1254,20 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
 
 	  /* Invoke the callback function to create the corefile segment.  */
 	  if (should_dump_p)
-	    func (addr, endaddr - addr, offset, inode,
-		  read, write, exec, 1, /* MODIFIED is true because we
-					   want to dump the mapping.  */
-		  filename, obfd);
+	    retval = func (addr, endaddr - addr, offset, inode,
+			   read, write, exec,
+			   1, /* MODIFIED is true because we want to dump the
+				 mapping.  */
+			   filename, func_data);
+	  if (retval != 0)
+	    break;
 	}
 
       do_cleanups (cleanup);
-      return 0;
+      return retval;
     }
 
-  return 1;
+  return -1;
 }
 
 /* A structure for passing information through
@@ -1294,7 +1281,7 @@ struct linux_find_memory_regions_data
 
   /* The original datum.  */
 
-  void *obfd;
+  void *data;
 };
 
 /* A callback for linux_find_memory_regions that converts between the
@@ -1308,7 +1295,48 @@ linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,
 {
   struct linux_find_memory_regions_data *data = arg;
 
-  return data->func (vaddr, size, read, write, exec, modified, data->obfd);
+  return data->func (vaddr, size, read, write, exec, modified, data->data);
+}
+
+/* Wrapper of linux_find_memory_regions_full handling FAKE_PID_P in GDB.  */
+
+static int
+linux_find_memory_regions_gdb (struct gdbarch *gdbarch,
+			       linux_find_memory_region_ftype *func,
+			       void *func_data)
+{
+  pid_t pid;
+  /* Default dump behavior of coredump_filter (0x33), according to
+     Documentation/filesystems/proc.txt from the Linux kernel
+     tree.  */
+  enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
+				  | COREFILTER_ANON_SHARED
+				  | COREFILTER_ELF_HEADERS
+				  | COREFILTER_HUGETLB_PRIVATE);
+
+  /* We need to know the real target PID so
+     linux_find_memory_regions_full can access /proc.  */
+  if (current_inferior ()->fake_pid_p)
+    return -1;
+
+  pid = current_inferior ()->pid;
+
+  if (use_coredump_filter)
+    {
+      char coredumpfilter_name[100], *coredumpfilterdata;
+
+      xsnprintf (coredumpfilter_name, sizeof (coredumpfilter_name),
+		 "/proc/%d/coredump_filter", pid);
+      coredumpfilterdata = target_fileio_read_stralloc (NULL,
+							coredumpfilter_name);
+      if (coredumpfilterdata != NULL)
+	{
+	  sscanf (coredumpfilterdata, "%x", &filterflags);
+	  xfree (coredumpfilterdata);
+	}
+    }
+
+  return linux_find_memory_regions_full (pid, filterflags, func, func_data);
 }
 
 /* A variant of linux_find_memory_regions_full that is suitable as the
@@ -1316,16 +1344,15 @@ linux_find_memory_regions_thunk (ULONGEST vaddr, ULONGEST size,
 
 static int
 linux_find_memory_regions (struct gdbarch *gdbarch,
-			   find_memory_region_ftype func, void *obfd)
+			   find_memory_region_ftype func, void *func_data)
 {
   struct linux_find_memory_regions_data data;
 
   data.func = func;
-  data.obfd = obfd;
+  data.data = func_data;
 
-  return linux_find_memory_regions_full (gdbarch,
-					 linux_find_memory_regions_thunk,
-					 &data);
+  return linux_find_memory_regions_gdb (gdbarch,
+					linux_find_memory_regions_thunk, &data);
 }
 
 /* Determine which signal stopped execution.  */
@@ -1507,8 +1534,8 @@ 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);
+  linux_find_memory_regions_gdb (gdbarch, linux_make_mappings_callback,
+				 &mapping_data);
 
   if (mapping_data.file_count != 0)
     {
diff --git a/gdb/target.c b/gdb/target.c
index a0a55d9..f06b2c2 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -2997,6 +2997,20 @@ target_fileio_close_cleanup (void *opaque)
   target_fileio_close (fd, &target_errno);
 }
 
+typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len,
+				      ULONGEST offset, int *target_errno);
+
+/* Helper for target_fileio_read_alloc_1 to make it interruptible.  */
+
+static int
+target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len,
+				  ULONGEST offset, int *target_errno)
+{
+  QUIT;
+
+  return target_fileio_pread (handle, read_buf, len, offset, target_errno);
+}
+
 /* Read target file FILENAME, in the filesystem as seen by INF.  If
    INF is NULL, use the filesystem seen by the debugger (GDB or, for
    remote targets, the remote stub).  Store the result in *BUF_P and
@@ -3006,23 +3020,14 @@ target_fileio_close_cleanup (void *opaque)
    more information.  */
 
 static LONGEST
-target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
-			    gdb_byte **buf_p, int padding)
+read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
+	    int padding)
 {
-  struct cleanup *close_cleanup;
   size_t buf_alloc, buf_pos;
   gdb_byte *buf;
   LONGEST n;
-  int fd;
   int target_errno;
 
-  fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700,
-			   &target_errno);
-  if (fd == -1)
-    return -1;
-
-  close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
-
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
   buf_alloc = 4096;
@@ -3030,25 +3035,24 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
   buf_pos = 0;
   while (1)
     {
-      n = target_fileio_pread (fd, &buf[buf_pos],
-			       buf_alloc - buf_pos - padding, buf_pos,
-			       &target_errno);
-      if (n < 0)
+      n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
+		      buf_pos, &target_errno);
+      if (n <= 0)
 	{
-	  /* An error occurred.  */
-	  do_cleanups (close_cleanup);
-	  xfree (buf);
-	  return -1;
-	}
-      else if (n == 0)
-	{
-	  /* Read all there was.  */
-	  do_cleanups (close_cleanup);
-	  if (buf_pos == 0)
+	  if (n < 0 || (n == 0 && buf_pos == 0))
 	    xfree (buf);
 	  else
 	    *buf_p = buf;
-	  return buf_pos;
+	  if (n < 0)
+	    {
+	      /* An error occurred.  */
+	      return -1;
+	    }
+	  else
+	    {
+	      /* Read all there was.  */
+	      return buf_pos;
+	    }
 	}
 
       buf_pos += n;
@@ -3059,11 +3063,31 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
 	  buf_alloc *= 2;
 	  buf = xrealloc (buf, buf_alloc);
 	}
-
-      QUIT;
     }
 }
 
+typedef LONGEST (read_stralloc_func_ftype) (struct inferior *inf,
+					    const char *filename,
+					    gdb_byte **buf_p, int padding);
+
+static LONGEST
+target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
+			    gdb_byte **buf_p, int padding)
+{
+  struct cleanup *close_cleanup;
+  int fd, target_errno;
+  LONGEST retval;
+
+  fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700, &target_errno);
+  if (fd == -1)
+    return -1;
+
+  close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
+  retval = read_alloc (buf_p, fd, target_fileio_read_alloc_1_pread, padding);
+  do_cleanups (close_cleanup);
+  return retval;
+}
+
 /* See target.h.  */
 
 LONGEST
@@ -3073,16 +3097,17 @@ target_fileio_read_alloc (struct inferior *inf, const char *filename,
   return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
 }
 
-/* See target.h.  */
+/* Helper for target_fileio_read_stralloc.  */
 
-char *
-target_fileio_read_stralloc (struct inferior *inf, const char *filename)
+static char *
+read_stralloc (struct inferior *inf, const char *filename,
+	       read_stralloc_func_ftype *func)
 {
   gdb_byte *buffer;
   char *bufstr;
   LONGEST i, transferred;
 
-  transferred = target_fileio_read_alloc_1 (inf, filename, &buffer, 1);
+  transferred = func (inf, filename, &buffer, 1);
   bufstr = (char *) buffer;
 
   if (transferred < 0)
@@ -3106,6 +3131,13 @@ target_fileio_read_stralloc (struct inferior *inf, const char *filename)
   return bufstr;
 }
 
+/* See target.h.  */
+
+char *
+target_fileio_read_stralloc (struct inferior *inf, const char *filename)
+{
+  return read_stralloc (inf, filename, target_fileio_read_alloc_1);
+}
 
 static int
 default_region_ok_for_hw_watchpoint (struct target_ops *self,

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 04/32] Move linux_find_memory_regions_full & co.
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (2 preceding siblings ...)
  2015-08-21 21:20 ` [PATCH v12 01/32] Create empty common/linux-maps.[ch] and common/target-utils.[ch] Jan Kratochvil
@ 2015-08-21 21:20 ` Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 05/32] gdbserver build-id attribute generator Jan Kratochvil
                   ` (28 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

This should be just a move with no changes.

gdb/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Move linux_find_memory_regions_full & co.
	* linux-tdep.c (linux-maps.h): Include.
	(gdb_regex.h): Remove the include.
	(enum filterflags, struct smaps_vmflags, read_mapping, decode_vmflags)
	(mapping_is_anonymous_p, dump_mapping_p): Moved to common/linux-maps.c.
	(linux_find_memory_region_ftype): Moved typedef to common/linux-maps.h.
	(linux_find_memory_regions_full): Moved definition to
	common/linux-maps.c.
	* common/linux-maps.c: Include ctype.h, target/target-utils.h,
	gdb_regex.h and target/target.h.
	(struct smaps_vmflags, read_mapping, decode_vmflags)
	(mapping_is_anonymous_p, dump_mapping_p): Move from linux-tdep.c.
	(linux_find_memory_regions_full): Move from linux-tdep.c.
	* common/linux-maps.h (read_mapping): New declaration.
	(linux_find_memory_region_ftype, enum filterflags): Moved from
	linux-tdep.c.
	(linux_find_memory_regions_full): New declaration.
	* target.c (target/target-utils.h): Include.
	(read_alloc_pread_ftype): Moved typedef to target/target-utils.h.
	(read_alloc, read_stralloc_func_ftype, read_stralloc): Moved
	definitions to target/target-utils.c.
	* target.h (target_fileio_read_stralloc): Move it to target/target.h.
	* target/target-utils.c (read_alloc, read_stralloc): Move definitions
	from target.c.
	* target/target-utils.h (read_alloc_pread_ftype): New typedef.
	(read_alloc): New declaration.
	(read_stralloc_func_ftype): New typedef.
	(read_stralloc): New declaration.
	* target/target.h (target_fileio_read_stralloc): Move it from target.h.

gdb/gdbserver/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	* target.c: Include target/target-utils.h and fcntl.h.
	(target_fileio_read_stralloc_1_pread, target_fileio_read_stralloc_1)
	(target_fileio_read_stralloc): New functions.
---
 0 files changed

diff --git a/gdb/common/linux-maps.c b/gdb/common/linux-maps.c
index 01c8836..b9f3990 100644
--- a/gdb/common/linux-maps.c
+++ b/gdb/common/linux-maps.c
@@ -18,3 +18,477 @@
 
 #include "common-defs.h"
 #include "linux-maps.h"
+#include <ctype.h>
+#include "target/target-utils.h"
+#include "gdb_regex.h"
+#include "target/target.h"
+
+/* This struct is used to map flags found in the "VmFlags:" field (in
+   the /proc/<PID>/smaps file).  */
+
+struct smaps_vmflags
+  {
+    /* Zero if this structure has not been initialized yet.  It
+       probably means that the Linux kernel being used does not emit
+       the "VmFlags:" field on "/proc/PID/smaps".  */
+
+    unsigned int initialized_p : 1;
+
+    /* Memory mapped I/O area (VM_IO, "io").  */
+
+    unsigned int io_page : 1;
+
+    /* Area uses huge TLB pages (VM_HUGETLB, "ht").  */
+
+    unsigned int uses_huge_tlb : 1;
+
+    /* Do not include this memory region on the coredump
+       (VM_DONTDUMP, "dd").  */
+
+    unsigned int exclude_coredump : 1;
+
+    /* Is this a MAP_SHARED mapping (VM_SHARED, "sh").  */
+
+    unsigned int shared_mapping : 1;
+  };
+
+/* 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);
+
+  p = skip_spaces_const (p);
+  *permissions = p;
+  while (*p && !isspace (*p))
+    p++;
+  *permissions_len = p - *permissions;
+
+  *offset = strtoulst (p, &p, 16);
+
+  p = skip_spaces_const (p);
+  *device = p;
+  while (*p && !isspace (*p))
+    p++;
+  *device_len = p - *device;
+
+  *inode = strtoulst (p, &p, 10);
+
+  p = skip_spaces_const (p);
+  *filename = p;
+}
+
+/* Helper function to decode the "VmFlags" field in /proc/PID/smaps.
+
+   This function was based on the documentation found on
+   <Documentation/filesystems/proc.txt>, on the Linux kernel.
+
+   Linux kernels before commit
+   834f82e2aa9a8ede94b17b656329f850c1471514 (3.10) do not have this
+   field on smaps.  */
+
+static void
+decode_vmflags (char *p, struct smaps_vmflags *v)
+{
+  char *saveptr = NULL;
+  const char *s;
+
+  v->initialized_p = 1;
+  p = skip_to_space (p);
+  p = skip_spaces (p);
+
+  for (s = strtok_r (p, " ", &saveptr);
+       s != NULL;
+       s = strtok_r (NULL, " ", &saveptr))
+    {
+      if (strcmp (s, "io") == 0)
+	v->io_page = 1;
+      else if (strcmp (s, "ht") == 0)
+	v->uses_huge_tlb = 1;
+      else if (strcmp (s, "dd") == 0)
+	v->exclude_coredump = 1;
+      else if (strcmp (s, "sh") == 0)
+	v->shared_mapping = 1;
+    }
+}
+
+/* Return 1 if the memory mapping is anonymous, 0 otherwise.
+
+   FILENAME is the name of the file present in the first line of the
+   memory mapping, in the "/proc/PID/smaps" output.  For example, if
+   the first line is:
+
+   7fd0ca877000-7fd0d0da0000 r--p 00000000 fd:02 2100770   /path/to/file
+
+   Then FILENAME will be "/path/to/file".  */
+
+static int
+mapping_is_anonymous_p (const char *filename)
+{
+  static regex_t dev_zero_regex, shmem_file_regex, file_deleted_regex;
+  static int init_regex_p = 0;
+
+  if (!init_regex_p)
+    {
+      struct cleanup *c = make_cleanup (null_cleanup, NULL);
+
+      /* Let's be pessimistic and assume there will be an error while
+	 compiling the regex'es.  */
+      init_regex_p = -1;
+
+      /* DEV_ZERO_REGEX matches "/dev/zero" filenames (with or
+	 without the "(deleted)" string in the end).  We know for
+	 sure, based on the Linux kernel code, that memory mappings
+	 whose associated filename is "/dev/zero" are guaranteed to be
+	 MAP_ANONYMOUS.  */
+      compile_rx_or_error (&dev_zero_regex, "^/dev/zero\\( (deleted)\\)\\?$",
+			   _("Could not compile regex to match /dev/zero "
+			     "filename"));
+      /* SHMEM_FILE_REGEX matches "/SYSV%08x" filenames (with or
+	 without the "(deleted)" string in the end).  These filenames
+	 refer to shared memory (shmem), and memory mappings
+	 associated with them are MAP_ANONYMOUS as well.  */
+      compile_rx_or_error (&shmem_file_regex,
+			   "^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$",
+			   _("Could not compile regex to match shmem "
+			     "filenames"));
+      /* FILE_DELETED_REGEX is a heuristic we use to try to mimic the
+	 Linux kernel's 'n_link == 0' code, which is responsible to
+	 decide if it is dealing with a 'MAP_SHARED | MAP_ANONYMOUS'
+	 mapping.  In other words, if FILE_DELETED_REGEX matches, it
+	 does not necessarily mean that we are dealing with an
+	 anonymous shared mapping.  However, there is no easy way to
+	 detect this currently, so this is the best approximation we
+	 have.
+
+	 As a result, GDB will dump readonly pages of deleted
+	 executables when using the default value of coredump_filter
+	 (0x33), while the Linux kernel will not dump those pages.
+	 But we can live with that.  */
+      compile_rx_or_error (&file_deleted_regex, " (deleted)$",
+			   _("Could not compile regex to match "
+			     "'<file> (deleted)'"));
+      /* We will never release these regexes, so just discard the
+	 cleanups.  */
+      discard_cleanups (c);
+
+      /* If we reached this point, then everything succeeded.  */
+      init_regex_p = 1;
+    }
+
+  if (init_regex_p == -1)
+    {
+      const char deleted[] = " (deleted)";
+      size_t del_len = sizeof (deleted) - 1;
+      size_t filename_len = strlen (filename);
+
+      /* There was an error while compiling the regex'es above.  In
+	 order to try to give some reliable information to the caller,
+	 we just try to find the string " (deleted)" in the filename.
+	 If we managed to find it, then we assume the mapping is
+	 anonymous.  */
+      return (filename_len >= del_len
+	      && strcmp (filename + filename_len - del_len, deleted) == 0);
+    }
+
+  if (*filename == '\0'
+      || regexec (&dev_zero_regex, filename, 0, NULL, 0) == 0
+      || regexec (&shmem_file_regex, filename, 0, NULL, 0) == 0
+      || regexec (&file_deleted_regex, filename, 0, NULL, 0) == 0)
+    return 1;
+
+  return 0;
+}
+
+/* Return 0 if the memory mapping (which is related to FILTERFLAGS, V,
+   MAYBE_PRIVATE_P, and MAPPING_ANONYMOUS_P) should not be dumped, or
+   greater than 0 if it should.
+
+   In a nutshell, this is the logic that we follow in order to decide
+   if a mapping should be dumped or not.
+
+   - If the mapping is associated to a file whose name ends with
+     " (deleted)", or if the file is "/dev/zero", or if it is
+     "/SYSV%08x" (shared memory), or if there is no file associated
+     with it, or if the AnonHugePages: or the Anonymous: fields in the
+     /proc/PID/smaps have contents, then GDB considers this mapping to
+     be anonymous.  Otherwise, GDB considers this mapping to be a
+     file-backed mapping (because there will be a file associated with
+     it).
+ 
+     It is worth mentioning that, from all those checks described
+     above, the most fragile is the one to see if the file name ends
+     with " (deleted)".  This does not necessarily mean that the
+     mapping is anonymous, because the deleted file associated with
+     the mapping may have been a hard link to another file, for
+     example.  The Linux kernel checks to see if "i_nlink == 0", but
+     GDB cannot easily (and normally) do this check (iff running as
+     root, it could find the mapping in /proc/PID/map_files/ and
+     determine whether there still are other hard links to the
+     inode/file).  Therefore, we made a compromise here, and we assume
+     that if the file name ends with " (deleted)", then the mapping is
+     indeed anonymous.  FWIW, this is something the Linux kernel could
+     do better: expose this information in a more direct way.
+ 
+   - If we see the flag "sh" in the "VmFlags:" field (in
+     /proc/PID/smaps), then certainly the memory mapping is shared
+     (VM_SHARED).  If we have access to the VmFlags, and we don't see
+     the "sh" there, then certainly the mapping is private.  However,
+     Linux kernels before commit
+     834f82e2aa9a8ede94b17b656329f850c1471514 (3.10) do not have the
+     "VmFlags:" field; in that case, we use another heuristic: if we
+     see 'p' in the permission flags, then we assume that the mapping
+     is private, even though the presence of the 's' flag there would
+     mean VM_MAYSHARE, which means the mapping could still be private.
+     This should work OK enough, however.  */
+
+static int
+dump_mapping_p (enum filterflags filterflags, const struct smaps_vmflags *v,
+		int maybe_private_p, int mapping_anon_p, int mapping_file_p,
+		const char *filename)
+{
+  /* Initially, we trust in what we received from our caller.  This
+     value may not be very precise (i.e., it was probably gathered
+     from the permission line in the /proc/PID/smaps list, which
+     actually refers to VM_MAYSHARE, and not VM_SHARED), but it is
+     what we have until we take a look at the "VmFlags:" field
+     (assuming that the version of the Linux kernel being used
+     supports it, of course).  */
+  int private_p = maybe_private_p;
+
+  /* We always dump vDSO and vsyscall mappings, because it's likely that
+     there'll be no file to read the contents from at core load time.
+     The kernel does the same.  */
+  if (strcmp ("[vdso]", filename) == 0
+      || strcmp ("[vsyscall]", filename) == 0)
+    return 1;
+
+  if (v->initialized_p)
+    {
+      /* We never dump I/O mappings.  */
+      if (v->io_page)
+	return 0;
+
+      /* Check if we should exclude this mapping.  */
+      if (v->exclude_coredump)
+	return 0;
+
+      /* Update our notion of whether this mapping is shared or
+	 private based on a trustworthy value.  */
+      private_p = !v->shared_mapping;
+
+      /* HugeTLB checking.  */
+      if (v->uses_huge_tlb)
+	{
+	  if ((private_p && (filterflags & COREFILTER_HUGETLB_PRIVATE))
+	      || (!private_p && (filterflags & COREFILTER_HUGETLB_SHARED)))
+	    return 1;
+
+	  return 0;
+	}
+    }
+
+  if (private_p)
+    {
+      if (mapping_anon_p && mapping_file_p)
+	{
+	  /* This is a special situation.  It can happen when we see a
+	     mapping that is file-backed, but that contains anonymous
+	     pages.  */
+	  return ((filterflags & COREFILTER_ANON_PRIVATE) != 0
+		  || (filterflags & COREFILTER_MAPPED_PRIVATE) != 0);
+	}
+      else if (mapping_anon_p)
+	return (filterflags & COREFILTER_ANON_PRIVATE) != 0;
+      else
+	return (filterflags & COREFILTER_MAPPED_PRIVATE) != 0;
+    }
+  else
+    {
+      if (mapping_anon_p && mapping_file_p)
+	{
+	  /* This is a special situation.  It can happen when we see a
+	     mapping that is file-backed, but that contains anonymous
+	     pages.  */
+	  return ((filterflags & COREFILTER_ANON_SHARED) != 0
+		  || (filterflags & COREFILTER_MAPPED_SHARED) != 0);
+	}
+      else if (mapping_anon_p)
+	return (filterflags & COREFILTER_ANON_SHARED) != 0;
+      else
+	return (filterflags & COREFILTER_MAPPED_SHARED) != 0;
+    }
+}
+
+/* List memory regions in the inferior PID matched to FILTERFLAGS for
+   a corefile.  Call FUNC with FUNC_DATA for each such region.  Return
+   immediately with the value returned by FUNC if it is non-zero.
+   *MEMORY_TO_FREE_PTR should be registered to be freed automatically if
+   called FUNC throws an exception.  MEMORY_TO_FREE_PTR can be also
+   passed as NULL if it is not used.  Return -1 if error occurs, 0 if
+   all memory regions have been processed or return the value from FUNC
+   if FUNC returns non-zero.  */
+
+int
+linux_find_memory_regions_full (pid_t pid, enum filterflags filterflags,
+				linux_find_memory_region_ftype *func,
+				void *func_data)
+{
+  char mapsfilename[100];
+  char *data;
+
+  xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", pid);
+  data = target_fileio_read_stralloc (NULL, mapsfilename);
+  if (data == NULL)
+    {
+      /* Older Linux kernels did not support /proc/PID/smaps.  */
+      xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps", pid);
+      data = target_fileio_read_stralloc (NULL, mapsfilename);
+    }
+
+  if (data != NULL)
+    {
+      struct cleanup *cleanup = make_cleanup (xfree, data);
+      char *line, *t;
+      int retval = 0;
+
+      line = strtok_r (data, "\n", &t);
+      while (line != NULL)
+	{
+	  ULONGEST addr, endaddr, offset, inode;
+	  const char *permissions, *device, *filename;
+	  struct smaps_vmflags v;
+	  size_t permissions_len, device_len;
+	  int read, write, exec, priv;
+	  int has_anonymous = 0;
+	  int should_dump_p = 0;
+	  int mapping_anon_p;
+	  int mapping_file_p;
+
+	  memset (&v, 0, sizeof (v));
+	  read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
+			&offset, &device, &device_len, &inode, &filename);
+	  mapping_anon_p = mapping_is_anonymous_p (filename);
+	  /* If the mapping is not anonymous, then we can consider it
+	     to be file-backed.  These two states (anonymous or
+	     file-backed) seem to be exclusive, but they can actually
+	     coexist.  For example, if a file-backed mapping has
+	     "Anonymous:" pages (see more below), then the Linux
+	     kernel will dump this mapping when the user specified
+	     that she only wants anonymous mappings in the corefile
+	     (*even* when she explicitly disabled the dumping of
+	     file-backed mappings).  */
+	  mapping_file_p = !mapping_anon_p;
+
+	  /* Decode permissions.  */
+	  read = (memchr (permissions, 'r', permissions_len) != 0);
+	  write = (memchr (permissions, 'w', permissions_len) != 0);
+	  exec = (memchr (permissions, 'x', permissions_len) != 0);
+	  /* 'private' here actually means VM_MAYSHARE, and not
+	     VM_SHARED.  In order to know if a mapping is really
+	     private or not, we must check the flag "sh" in the
+	     VmFlags field.  This is done by decode_vmflags.  However,
+	     if we are using a Linux kernel released before the commit
+	     834f82e2aa9a8ede94b17b656329f850c1471514 (3.10), we will
+	     not have the VmFlags there.  In this case, there is
+	     really no way to know if we are dealing with VM_SHARED,
+	     so we just assume that VM_MAYSHARE is enough.  */
+	  priv = memchr (permissions, 'p', permissions_len) != 0;
+
+	  /* Try to detect if region should be dumped by parsing smaps
+	     counters.  */
+	  for (line = strtok_r (NULL, "\n", &t);
+	       line != NULL && line[0] >= 'A' && line[0] <= 'Z';
+	       line = strtok_r (NULL, "\n", &t))
+	    {
+	      char keyword[64 + 1];
+
+	      if (sscanf (line, "%64s", keyword) != 1)
+		{
+		  warning (_("Error parsing {s,}maps file '%s'"), mapsfilename);
+		  break;
+		}
+
+	      if (strcmp (keyword, "Anonymous:") == 0)
+		{
+		  /* Older Linux kernels did not support the
+		     "Anonymous:" counter.  Check it here.  */
+		  has_anonymous = 1;
+		}
+	      else if (strcmp (keyword, "VmFlags:") == 0)
+		decode_vmflags (line, &v);
+
+	      if (strcmp (keyword, "AnonHugePages:") == 0
+		  || strcmp (keyword, "Anonymous:") == 0)
+		{
+		  unsigned long number;
+
+		  if (sscanf (line, "%*s%lu", &number) != 1)
+		    {
+		      warning (_("Error parsing {s,}maps file '%s' number"),
+			       mapsfilename);
+		      break;
+		    }
+		  if (number > 0)
+		    {
+		      /* Even if we are dealing with a file-backed
+			 mapping, if it contains anonymous pages we
+			 consider it to be *also* an anonymous
+			 mapping, because this is what the Linux
+			 kernel does:
+
+			 // Dump segments that have been written to.
+			 if (vma->anon_vma && FILTER(ANON_PRIVATE))
+			 	goto whole;
+
+			 Note that if the mapping is already marked as
+			 file-backed (i.e., mapping_file_p is
+			 non-zero), then this is a special case, and
+			 this mapping will be dumped either when the
+			 user wants to dump file-backed *or* anonymous
+			 mappings.  */
+		      mapping_anon_p = 1;
+		    }
+		}
+	    }
+
+	  if (has_anonymous)
+	    should_dump_p = dump_mapping_p (filterflags, &v, priv,
+					    mapping_anon_p, mapping_file_p,
+					    filename);
+	  else
+	    {
+	      /* Older Linux kernels did not support the "Anonymous:" counter.
+		 If it is missing, we can't be sure - dump all the pages.  */
+	      should_dump_p = 1;
+	    }
+
+	  /* Invoke the callback function to create the corefile segment.  */
+	  if (should_dump_p)
+	    retval = func (addr, endaddr - addr, offset, inode,
+			   read, write, exec,
+			   1, /* MODIFIED is true because we want to dump the
+				 mapping.  */
+			   filename, func_data);
+	  if (retval != 0)
+	    break;
+	}
+
+      do_cleanups (cleanup);
+      return retval;
+    }
+
+  return -1;
+}
diff --git a/gdb/common/linux-maps.h b/gdb/common/linux-maps.h
index 4228674..0bec9db 100644
--- a/gdb/common/linux-maps.h
+++ b/gdb/common/linux-maps.h
@@ -19,4 +19,46 @@
 #ifndef COMMON_LINUX_MAPS_H
 #define COMMON_LINUX_MAPS_H
 
+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);
+
+/* Callback function for linux_find_memory_regions_full.  If it returns
+   non-zero linux_find_memory_regions_full returns immediately with that
+   value.  */
+
+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);
+
+/* This enum represents the values that the user can choose when
+   informing the Linux kernel about which memory mappings will be
+   dumped in a corefile.  They are described in the file
+   Documentation/filesystems/proc.txt, inside the Linux kernel
+   tree.  */
+
+enum filterflags
+  {
+    COREFILTER_ANON_PRIVATE = 1 << 0,
+    COREFILTER_ANON_SHARED = 1 << 1,
+    COREFILTER_MAPPED_PRIVATE = 1 << 2,
+    COREFILTER_MAPPED_SHARED = 1 << 3,
+    COREFILTER_ELF_HEADERS = 1 << 4,
+    COREFILTER_HUGETLB_PRIVATE = 1 << 5,
+    COREFILTER_HUGETLB_SHARED = 1 << 6,
+  };
+
+extern int
+  linux_find_memory_regions_full (pid_t pid, enum filterflags filterflags,
+				  linux_find_memory_region_ftype *func,
+				  void *func_data);
+
 #endif /* COMMON_LINUX_MAPS_H */
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index 8fcfe9b..44cf0b9 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -20,6 +20,8 @@
 
 #include "server.h"
 #include "tracepoint.h"
+#include "target/target-utils.h"
+#include <fcntl.h>
 
 struct target_ops *the_target;
 
@@ -216,3 +218,37 @@ kill_inferior (int pid)
 
   return (*the_target->kill) (pid);
 }
+
+static int
+target_fileio_read_stralloc_1_pread (int handle, gdb_byte *read_buf, int len,
+				     ULONGEST offset, int *target_errno)
+{
+  int retval = pread (handle, read_buf, len, offset);
+
+  *target_errno = errno;
+  return retval;
+}
+
+static LONGEST
+target_fileio_read_stralloc_1 (struct inferior *inf, const char *filename,
+			       gdb_byte **buf_p, int padding)
+{
+  int fd;
+  LONGEST retval;
+
+  fd = open (filename, O_RDONLY);
+  if (fd == -1)
+    return -1;
+
+  retval = read_alloc (buf_p, fd, target_fileio_read_stralloc_1_pread, padding);
+
+  close (fd);
+
+  return retval;
+}
+
+char *
+target_fileio_read_stralloc (struct inferior *inf, const char *filename)
+{
+  return read_stralloc (inf, filename, target_fileio_read_stralloc_1);
+}
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 982599e..3df86ba 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -35,56 +35,11 @@
 #include "observer.h"
 #include "objfiles.h"
 #include "infcall.h"
+#include "linux-maps.h"
 #include "gdbcmd.h"
-#include "gdb_regex.h"
 
 #include <ctype.h>
 
-/* This enum represents the values that the user can choose when
-   informing the Linux kernel about which memory mappings will be
-   dumped in a corefile.  They are described in the file
-   Documentation/filesystems/proc.txt, inside the Linux kernel
-   tree.  */
-
-enum filterflags
-  {
-    COREFILTER_ANON_PRIVATE = 1 << 0,
-    COREFILTER_ANON_SHARED = 1 << 1,
-    COREFILTER_MAPPED_PRIVATE = 1 << 2,
-    COREFILTER_MAPPED_SHARED = 1 << 3,
-    COREFILTER_ELF_HEADERS = 1 << 4,
-    COREFILTER_HUGETLB_PRIVATE = 1 << 5,
-    COREFILTER_HUGETLB_SHARED = 1 << 6,
-  };
-
-/* This struct is used to map flags found in the "VmFlags:" field (in
-   the /proc/<PID>/smaps file).  */
-
-struct smaps_vmflags
-  {
-    /* Zero if this structure has not been initialized yet.  It
-       probably means that the Linux kernel being used does not emit
-       the "VmFlags:" field on "/proc/PID/smaps".  */
-
-    unsigned int initialized_p : 1;
-
-    /* Memory mapped I/O area (VM_IO, "io").  */
-
-    unsigned int io_page : 1;
-
-    /* Area uses huge TLB pages (VM_HUGETLB, "ht").  */
-
-    unsigned int uses_huge_tlb : 1;
-
-    /* Do not include this memory region on the coredump (VM_DONTDUMP, "dd").  */
-
-    unsigned int exclude_coredump : 1;
-
-    /* Is this a MAP_SHARED mapping (VM_SHARED, "sh").  */
-
-    unsigned int shared_mapping : 1;
-  };
-
 /* Whether to take the /proc/PID/coredump_filter into account when
    generating a corefile.  */
 
@@ -395,286 +350,6 @@ 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);
-
-  p = skip_spaces_const (p);
-  *permissions = p;
-  while (*p && !isspace (*p))
-    p++;
-  *permissions_len = p - *permissions;
-
-  *offset = strtoulst (p, &p, 16);
-
-  p = skip_spaces_const (p);
-  *device = p;
-  while (*p && !isspace (*p))
-    p++;
-  *device_len = p - *device;
-
-  *inode = strtoulst (p, &p, 10);
-
-  p = skip_spaces_const (p);
-  *filename = p;
-}
-
-/* Helper function to decode the "VmFlags" field in /proc/PID/smaps.
-
-   This function was based on the documentation found on
-   <Documentation/filesystems/proc.txt>, on the Linux kernel.
-
-   Linux kernels before commit
-   834f82e2aa9a8ede94b17b656329f850c1471514 (3.10) do not have this
-   field on smaps.  */
-
-static void
-decode_vmflags (char *p, struct smaps_vmflags *v)
-{
-  char *saveptr = NULL;
-  const char *s;
-
-  v->initialized_p = 1;
-  p = skip_to_space (p);
-  p = skip_spaces (p);
-
-  for (s = strtok_r (p, " ", &saveptr);
-       s != NULL;
-       s = strtok_r (NULL, " ", &saveptr))
-    {
-      if (strcmp (s, "io") == 0)
-	v->io_page = 1;
-      else if (strcmp (s, "ht") == 0)
-	v->uses_huge_tlb = 1;
-      else if (strcmp (s, "dd") == 0)
-	v->exclude_coredump = 1;
-      else if (strcmp (s, "sh") == 0)
-	v->shared_mapping = 1;
-    }
-}
-
-/* Return 1 if the memory mapping is anonymous, 0 otherwise.
-
-   FILENAME is the name of the file present in the first line of the
-   memory mapping, in the "/proc/PID/smaps" output.  For example, if
-   the first line is:
-
-   7fd0ca877000-7fd0d0da0000 r--p 00000000 fd:02 2100770   /path/to/file
-
-   Then FILENAME will be "/path/to/file".  */
-
-static int
-mapping_is_anonymous_p (const char *filename)
-{
-  static regex_t dev_zero_regex, shmem_file_regex, file_deleted_regex;
-  static int init_regex_p = 0;
-
-  if (!init_regex_p)
-    {
-      struct cleanup *c = make_cleanup (null_cleanup, NULL);
-
-      /* Let's be pessimistic and assume there will be an error while
-	 compiling the regex'es.  */
-      init_regex_p = -1;
-
-      /* DEV_ZERO_REGEX matches "/dev/zero" filenames (with or
-	 without the "(deleted)" string in the end).  We know for
-	 sure, based on the Linux kernel code, that memory mappings
-	 whose associated filename is "/dev/zero" are guaranteed to be
-	 MAP_ANONYMOUS.  */
-      compile_rx_or_error (&dev_zero_regex, "^/dev/zero\\( (deleted)\\)\\?$",
-			   _("Could not compile regex to match /dev/zero "
-			     "filename"));
-      /* SHMEM_FILE_REGEX matches "/SYSV%08x" filenames (with or
-	 without the "(deleted)" string in the end).  These filenames
-	 refer to shared memory (shmem), and memory mappings
-	 associated with them are MAP_ANONYMOUS as well.  */
-      compile_rx_or_error (&shmem_file_regex,
-			   "^/\\?SYSV[0-9a-fA-F]\\{8\\}\\( (deleted)\\)\\?$",
-			   _("Could not compile regex to match shmem "
-			     "filenames"));
-      /* FILE_DELETED_REGEX is a heuristic we use to try to mimic the
-	 Linux kernel's 'n_link == 0' code, which is responsible to
-	 decide if it is dealing with a 'MAP_SHARED | MAP_ANONYMOUS'
-	 mapping.  In other words, if FILE_DELETED_REGEX matches, it
-	 does not necessarily mean that we are dealing with an
-	 anonymous shared mapping.  However, there is no easy way to
-	 detect this currently, so this is the best approximation we
-	 have.
-
-	 As a result, GDB will dump readonly pages of deleted
-	 executables when using the default value of coredump_filter
-	 (0x33), while the Linux kernel will not dump those pages.
-	 But we can live with that.  */
-      compile_rx_or_error (&file_deleted_regex, " (deleted)$",
-			   _("Could not compile regex to match "
-			     "'<file> (deleted)'"));
-      /* We will never release these regexes, so just discard the
-	 cleanups.  */
-      discard_cleanups (c);
-
-      /* If we reached this point, then everything succeeded.  */
-      init_regex_p = 1;
-    }
-
-  if (init_regex_p == -1)
-    {
-      const char deleted[] = " (deleted)";
-      size_t del_len = sizeof (deleted) - 1;
-      size_t filename_len = strlen (filename);
-
-      /* There was an error while compiling the regex'es above.  In
-	 order to try to give some reliable information to the caller,
-	 we just try to find the string " (deleted)" in the filename.
-	 If we managed to find it, then we assume the mapping is
-	 anonymous.  */
-      return (filename_len >= del_len
-	      && strcmp (filename + filename_len - del_len, deleted) == 0);
-    }
-
-  if (*filename == '\0'
-      || regexec (&dev_zero_regex, filename, 0, NULL, 0) == 0
-      || regexec (&shmem_file_regex, filename, 0, NULL, 0) == 0
-      || regexec (&file_deleted_regex, filename, 0, NULL, 0) == 0)
-    return 1;
-
-  return 0;
-}
-
-/* Return 0 if the memory mapping (which is related to FILTERFLAGS, V,
-   MAYBE_PRIVATE_P, and MAPPING_ANONYMOUS_P) should not be dumped, or
-   greater than 0 if it should.
-
-   In a nutshell, this is the logic that we follow in order to decide
-   if a mapping should be dumped or not.
-
-   - If the mapping is associated to a file whose name ends with
-     " (deleted)", or if the file is "/dev/zero", or if it is
-     "/SYSV%08x" (shared memory), or if there is no file associated
-     with it, or if the AnonHugePages: or the Anonymous: fields in the
-     /proc/PID/smaps have contents, then GDB considers this mapping to
-     be anonymous.  Otherwise, GDB considers this mapping to be a
-     file-backed mapping (because there will be a file associated with
-     it).
- 
-     It is worth mentioning that, from all those checks described
-     above, the most fragile is the one to see if the file name ends
-     with " (deleted)".  This does not necessarily mean that the
-     mapping is anonymous, because the deleted file associated with
-     the mapping may have been a hard link to another file, for
-     example.  The Linux kernel checks to see if "i_nlink == 0", but
-     GDB cannot easily (and normally) do this check (iff running as
-     root, it could find the mapping in /proc/PID/map_files/ and
-     determine whether there still are other hard links to the
-     inode/file).  Therefore, we made a compromise here, and we assume
-     that if the file name ends with " (deleted)", then the mapping is
-     indeed anonymous.  FWIW, this is something the Linux kernel could
-     do better: expose this information in a more direct way.
- 
-   - If we see the flag "sh" in the "VmFlags:" field (in
-     /proc/PID/smaps), then certainly the memory mapping is shared
-     (VM_SHARED).  If we have access to the VmFlags, and we don't see
-     the "sh" there, then certainly the mapping is private.  However,
-     Linux kernels before commit
-     834f82e2aa9a8ede94b17b656329f850c1471514 (3.10) do not have the
-     "VmFlags:" field; in that case, we use another heuristic: if we
-     see 'p' in the permission flags, then we assume that the mapping
-     is private, even though the presence of the 's' flag there would
-     mean VM_MAYSHARE, which means the mapping could still be private.
-     This should work OK enough, however.  */
-
-static int
-dump_mapping_p (enum filterflags filterflags, const struct smaps_vmflags *v,
-		int maybe_private_p, int mapping_anon_p, int mapping_file_p,
-		const char *filename)
-{
-  /* Initially, we trust in what we received from our caller.  This
-     value may not be very precise (i.e., it was probably gathered
-     from the permission line in the /proc/PID/smaps list, which
-     actually refers to VM_MAYSHARE, and not VM_SHARED), but it is
-     what we have until we take a look at the "VmFlags:" field
-     (assuming that the version of the Linux kernel being used
-     supports it, of course).  */
-  int private_p = maybe_private_p;
-
-  /* We always dump vDSO and vsyscall mappings, because it's likely that
-     there'll be no file to read the contents from at core load time.
-     The kernel does the same.  */
-  if (strcmp ("[vdso]", filename) == 0
-      || strcmp ("[vsyscall]", filename) == 0)
-    return 1;
-
-  if (v->initialized_p)
-    {
-      /* We never dump I/O mappings.  */
-      if (v->io_page)
-	return 0;
-
-      /* Check if we should exclude this mapping.  */
-      if (v->exclude_coredump)
-	return 0;
-
-      /* Update our notion of whether this mapping is shared or
-	 private based on a trustworthy value.  */
-      private_p = !v->shared_mapping;
-
-      /* HugeTLB checking.  */
-      if (v->uses_huge_tlb)
-	{
-	  if ((private_p && (filterflags & COREFILTER_HUGETLB_PRIVATE))
-	      || (!private_p && (filterflags & COREFILTER_HUGETLB_SHARED)))
-	    return 1;
-
-	  return 0;
-	}
-    }
-
-  if (private_p)
-    {
-      if (mapping_anon_p && mapping_file_p)
-	{
-	  /* This is a special situation.  It can happen when we see a
-	     mapping that is file-backed, but that contains anonymous
-	     pages.  */
-	  return ((filterflags & COREFILTER_ANON_PRIVATE) != 0
-		  || (filterflags & COREFILTER_MAPPED_PRIVATE) != 0);
-	}
-      else if (mapping_anon_p)
-	return (filterflags & COREFILTER_ANON_PRIVATE) != 0;
-      else
-	return (filterflags & COREFILTER_MAPPED_PRIVATE) != 0;
-    }
-  else
-    {
-      if (mapping_anon_p && mapping_file_p)
-	{
-	  /* This is a special situation.  It can happen when we see a
-	     mapping that is file-backed, but that contains anonymous
-	     pages.  */
-	  return ((filterflags & COREFILTER_ANON_SHARED) != 0
-		  || (filterflags & COREFILTER_MAPPED_SHARED) != 0);
-	}
-      else if (mapping_anon_p)
-	return (filterflags & COREFILTER_ANON_SHARED) != 0;
-      else
-	return (filterflags & COREFILTER_MAPPED_SHARED) != 0;
-    }
-}
-
 /* Implement the "info proc" command.  */
 
 static void
@@ -1098,178 +773,6 @@ linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
     error (_("unable to handle request"));
 }
 
-/* Callback function for linux_find_memory_regions_full.  If it returns
-   non-zero linux_find_memory_regions_full returns immediately with that
-   value.  */
-
-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 PID matched to FILTERFLAGS for
-   a corefile.  Call FUNC with FUNC_DATA for each such region.  Return
-   immediately with the value returned by FUNC if it is non-zero.
-   *MEMORY_TO_FREE_PTR should be registered to be freed automatically if
-   called FUNC throws an exception.  MEMORY_TO_FREE_PTR can be also
-   passed as NULL if it is not used.  Return -1 if error occurs, 0 if
-   all memory regions have been processed or return the value from FUNC
-   if FUNC returns non-zero.  */
-
-static int
-linux_find_memory_regions_full (pid_t pid, enum filterflags filterflags,
-				linux_find_memory_region_ftype *func,
-				void *func_data)
-{
-  char mapsfilename[100];
-  char *data;
-
-  xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/smaps", pid);
-  data = target_fileio_read_stralloc (NULL, mapsfilename);
-  if (data == NULL)
-    {
-      /* Older Linux kernels did not support /proc/PID/smaps.  */
-      xsnprintf (mapsfilename, sizeof mapsfilename, "/proc/%d/maps", pid);
-      data = target_fileio_read_stralloc (NULL, mapsfilename);
-    }
-
-  if (data != NULL)
-    {
-      struct cleanup *cleanup = make_cleanup (xfree, data);
-      char *line, *t;
-      int retval = 0;
-
-      line = strtok_r (data, "\n", &t);
-      while (line != NULL)
-	{
-	  ULONGEST addr, endaddr, offset, inode;
-	  const char *permissions, *device, *filename;
-	  struct smaps_vmflags v;
-	  size_t permissions_len, device_len;
-	  int read, write, exec, priv;
-	  int has_anonymous = 0;
-	  int should_dump_p = 0;
-	  int mapping_anon_p;
-	  int mapping_file_p;
-
-	  memset (&v, 0, sizeof (v));
-	  read_mapping (line, &addr, &endaddr, &permissions, &permissions_len,
-			&offset, &device, &device_len, &inode, &filename);
-	  mapping_anon_p = mapping_is_anonymous_p (filename);
-	  /* If the mapping is not anonymous, then we can consider it
-	     to be file-backed.  These two states (anonymous or
-	     file-backed) seem to be exclusive, but they can actually
-	     coexist.  For example, if a file-backed mapping has
-	     "Anonymous:" pages (see more below), then the Linux
-	     kernel will dump this mapping when the user specified
-	     that she only wants anonymous mappings in the corefile
-	     (*even* when she explicitly disabled the dumping of
-	     file-backed mappings).  */
-	  mapping_file_p = !mapping_anon_p;
-
-	  /* Decode permissions.  */
-	  read = (memchr (permissions, 'r', permissions_len) != 0);
-	  write = (memchr (permissions, 'w', permissions_len) != 0);
-	  exec = (memchr (permissions, 'x', permissions_len) != 0);
-	  /* 'private' here actually means VM_MAYSHARE, and not
-	     VM_SHARED.  In order to know if a mapping is really
-	     private or not, we must check the flag "sh" in the
-	     VmFlags field.  This is done by decode_vmflags.  However,
-	     if we are using a Linux kernel released before the commit
-	     834f82e2aa9a8ede94b17b656329f850c1471514 (3.10), we will
-	     not have the VmFlags there.  In this case, there is
-	     really no way to know if we are dealing with VM_SHARED,
-	     so we just assume that VM_MAYSHARE is enough.  */
-	  priv = memchr (permissions, 'p', permissions_len) != 0;
-
-	  /* Try to detect if region should be dumped by parsing smaps
-	     counters.  */
-	  for (line = strtok_r (NULL, "\n", &t);
-	       line != NULL && line[0] >= 'A' && line[0] <= 'Z';
-	       line = strtok_r (NULL, "\n", &t))
-	    {
-	      char keyword[64 + 1];
-
-	      if (sscanf (line, "%64s", keyword) != 1)
-		{
-		  warning (_("Error parsing {s,}maps file '%s'"), mapsfilename);
-		  break;
-		}
-
-	      if (strcmp (keyword, "Anonymous:") == 0)
-		{
-		  /* Older Linux kernels did not support the
-		     "Anonymous:" counter.  Check it here.  */
-		  has_anonymous = 1;
-		}
-	      else if (strcmp (keyword, "VmFlags:") == 0)
-		decode_vmflags (line, &v);
-
-	      if (strcmp (keyword, "AnonHugePages:") == 0
-		  || strcmp (keyword, "Anonymous:") == 0)
-		{
-		  unsigned long number;
-
-		  if (sscanf (line, "%*s%lu", &number) != 1)
-		    {
-		      warning (_("Error parsing {s,}maps file '%s' number"),
-			       mapsfilename);
-		      break;
-		    }
-		  if (number > 0)
-		    {
-		      /* Even if we are dealing with a file-backed
-			 mapping, if it contains anonymous pages we
-			 consider it to be *also* an anonymous
-			 mapping, because this is what the Linux
-			 kernel does:
-
-			 // Dump segments that have been written to.
-			 if (vma->anon_vma && FILTER(ANON_PRIVATE))
-			 	goto whole;
-
-			 Note that if the mapping is already marked as
-			 file-backed (i.e., mapping_file_p is
-			 non-zero), then this is a special case, and
-			 this mapping will be dumped either when the
-			 user wants to dump file-backed *or* anonymous
-			 mappings.  */
-		      mapping_anon_p = 1;
-		    }
-		}
-	    }
-
-	  if (has_anonymous)
-	    should_dump_p = dump_mapping_p (filterflags, &v, priv,
-					    mapping_anon_p, mapping_file_p,
-					    filename);
-	  else
-	    {
-	      /* Older Linux kernels did not support the "Anonymous:" counter.
-		 If it is missing, we can't be sure - dump all the pages.  */
-	      should_dump_p = 1;
-	    }
-
-	  /* Invoke the callback function to create the corefile segment.  */
-	  if (should_dump_p)
-	    retval = func (addr, endaddr - addr, offset, inode,
-			   read, write, exec,
-			   1, /* MODIFIED is true because we want to dump the
-				 mapping.  */
-			   filename, func_data);
-	  if (retval != 0)
-	    break;
-	}
-
-      do_cleanups (cleanup);
-      return retval;
-    }
-
-  return -1;
-}
-
 /* A structure for passing information through
    linux_find_memory_regions_full.  */
 
diff --git a/gdb/target.c b/gdb/target.c
index f06b2c2..def5a91 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -43,6 +43,7 @@
 #include "agent.h"
 #include "auxv.h"
 #include "target-debug.h"
+#include "target/target-utils.h"
 
 static void target_info (char *, int);
 
@@ -2997,9 +2998,6 @@ target_fileio_close_cleanup (void *opaque)
   target_fileio_close (fd, &target_errno);
 }
 
-typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len,
-				      ULONGEST offset, int *target_errno);
-
 /* Helper for target_fileio_read_alloc_1 to make it interruptible.  */
 
 static int
@@ -3020,57 +3018,6 @@ target_fileio_read_alloc_1_pread (int handle, gdb_byte *read_buf, int len,
    more information.  */
 
 static LONGEST
-read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
-	    int padding)
-{
-  size_t buf_alloc, buf_pos;
-  gdb_byte *buf;
-  LONGEST n;
-  int target_errno;
-
-  /* Start by reading up to 4K at a time.  The target will throttle
-     this number down if necessary.  */
-  buf_alloc = 4096;
-  buf = xmalloc (buf_alloc);
-  buf_pos = 0;
-  while (1)
-    {
-      n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
-		      buf_pos, &target_errno);
-      if (n <= 0)
-	{
-	  if (n < 0 || (n == 0 && buf_pos == 0))
-	    xfree (buf);
-	  else
-	    *buf_p = buf;
-	  if (n < 0)
-	    {
-	      /* An error occurred.  */
-	      return -1;
-	    }
-	  else
-	    {
-	      /* Read all there was.  */
-	      return buf_pos;
-	    }
-	}
-
-      buf_pos += n;
-
-      /* If the buffer is filling up, expand it.  */
-      if (buf_alloc < buf_pos * 2)
-	{
-	  buf_alloc *= 2;
-	  buf = xrealloc (buf, buf_alloc);
-	}
-    }
-}
-
-typedef LONGEST (read_stralloc_func_ftype) (struct inferior *inf,
-					    const char *filename,
-					    gdb_byte **buf_p, int padding);
-
-static LONGEST
 target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
 			    gdb_byte **buf_p, int padding)
 {
@@ -3097,41 +3044,7 @@ target_fileio_read_alloc (struct inferior *inf, const char *filename,
   return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
 }
 
-/* Helper for target_fileio_read_stralloc.  */
-
-static char *
-read_stralloc (struct inferior *inf, const char *filename,
-	       read_stralloc_func_ftype *func)
-{
-  gdb_byte *buffer;
-  char *bufstr;
-  LONGEST i, transferred;
-
-  transferred = func (inf, filename, &buffer, 1);
-  bufstr = (char *) buffer;
-
-  if (transferred < 0)
-    return NULL;
-
-  if (transferred == 0)
-    return xstrdup ("");
-
-  bufstr[transferred] = 0;
-
-  /* Check for embedded NUL bytes; but allow trailing NULs.  */
-  for (i = strlen (bufstr); i < transferred; i++)
-    if (bufstr[i] != 0)
-      {
-	warning (_("target file %s "
-		   "contained unexpected null characters"),
-		 filename);
-	break;
-      }
-
-  return bufstr;
-}
-
-/* See target.h.  */
+/* See target/target.h.  */
 
 char *
 target_fileio_read_stralloc (struct inferior *inf, const char *filename)
diff --git a/gdb/target.h b/gdb/target.h
index 1fdaf00..9d7b2b0 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -2073,16 +2073,6 @@ extern LONGEST target_fileio_read_alloc (struct inferior *inf,
 					 const char *filename,
 					 gdb_byte **buf_p);
 
-/* Read target file FILENAME, in the filesystem as seen by INF.  If
-   INF is NULL, use the filesystem seen by the debugger (GDB or, for
-   remote targets, the remote stub).  The result is NUL-terminated and
-   returned as a string, allocated using xmalloc.  If an error occurs
-   or the transfer is unsupported, NULL is returned.  Empty objects
-   are returned as allocated but empty strings.  A warning is issued
-   if the result contains any embedded NUL bytes.  */
-extern char *target_fileio_read_stralloc (struct inferior *inf,
-					  const char *filename);
-
 
 /* Tracepoint-related operations.  */
 
diff --git a/gdb/target/target-utils.c b/gdb/target/target-utils.c
index 4e8fae7..cdfa6e6 100644
--- a/gdb/target/target-utils.c
+++ b/gdb/target/target-utils.c
@@ -19,3 +19,82 @@
 
 #include "common-defs.h"
 #include "target/target-utils.h"
+
+LONGEST
+read_alloc (gdb_byte **buf_p, int handle, read_alloc_pread_ftype *pread_func,
+	    int padding)
+{
+  size_t buf_alloc, buf_pos;
+  gdb_byte *buf;
+  LONGEST n;
+  int target_errno;
+
+  /* Start by reading up to 4K at a time.  The target will throttle
+     this number down if necessary.  */
+  buf_alloc = 4096;
+  buf = xmalloc (buf_alloc);
+  buf_pos = 0;
+  while (1)
+    {
+      n = pread_func (handle, &buf[buf_pos], buf_alloc - buf_pos - padding,
+		      buf_pos, &target_errno);
+      if (n <= 0)
+	{
+	  if (n < 0 || (n == 0 && buf_pos == 0))
+	    xfree (buf);
+	  else
+	    *buf_p = buf;
+	  if (n < 0)
+	    {
+	      /* An error occurred.  */
+	      return -1;
+	    }
+	  else
+	    {
+	      /* Read all there was.  */
+	      return buf_pos;
+	    }
+	}
+
+      buf_pos += n;
+
+      /* If the buffer is filling up, expand it.  */
+      if (buf_alloc < buf_pos * 2)
+	{
+	  buf_alloc *= 2;
+	  buf = xrealloc (buf, buf_alloc);
+	}
+    }
+}
+
+char *
+read_stralloc (struct inferior *inf, const char *filename,
+	       read_stralloc_func_ftype *func)
+{
+  gdb_byte *buffer;
+  char *bufstr;
+  LONGEST i, transferred;
+
+  transferred = func (inf, filename, &buffer, 1);
+  bufstr = (char *) buffer;
+
+  if (transferred < 0)
+    return NULL;
+
+  if (transferred == 0)
+    return xstrdup ("");
+
+  bufstr[transferred] = 0;
+
+  /* Check for embedded NUL bytes; but allow trailing NULs.  */
+  for (i = strlen (bufstr); i < transferred; i++)
+    if (bufstr[i] != 0)
+      {
+	warning (_("target file %s "
+		   "contained unexpected null characters"),
+		 filename);
+	break;
+      }
+
+  return bufstr;
+}
diff --git a/gdb/target/target-utils.h b/gdb/target/target-utils.h
index 443ffc3..e8bf52a 100644
--- a/gdb/target/target-utils.h
+++ b/gdb/target/target-utils.h
@@ -20,4 +20,16 @@
 #ifndef TARGET_TARGET_UTILS_H
 #define TARGET_TARGET_UTILS_H
 
+typedef int (read_alloc_pread_ftype) (int handle, gdb_byte *read_buf, int len,
+				      ULONGEST offset, int *target_errno);
+extern LONGEST read_alloc (gdb_byte **buf_p, int handle,
+			   read_alloc_pread_ftype *pread_func, int padding);
+
+struct inferior;
+typedef LONGEST (read_stralloc_func_ftype) (struct inferior *inf,
+					    const char *filename,
+					    gdb_byte **buf_p, int padding);
+extern char *read_stralloc (struct inferior *inf, const char *filename,
+			    read_stralloc_func_ftype *func);
+
 #endif /* TARGET_TARGET_UTILS_H */
diff --git a/gdb/target/target.h b/gdb/target/target.h
index 6ee0fee..4c85fe0 100644
--- a/gdb/target/target.h
+++ b/gdb/target/target.h
@@ -70,4 +70,15 @@ extern void target_stop_and_wait (ptid_t ptid);
 
 extern void target_continue_no_signal (ptid_t ptid);
 
+/* Read target file FILENAME, in the filesystem as seen by INF.  If
+   INF is NULL, use the filesystem seen by the debugger (GDB or, for
+   remote targets, the remote stub).  The result is NUL-terminated and
+   returned as a string, allocated using xmalloc.  If an error occurs
+   or the transfer is unsupported, NULL is returned.  Empty objects
+   are returned as allocated but empty strings.  A warning is issued
+   if the result contains any embedded NUL bytes.  */
+struct inferior;
+extern char *target_fileio_read_stralloc (struct inferior *inf,
+					  const char *filename);
+
 #endif /* TARGET_COMMON_H */

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 05/32] gdbserver build-id attribute generator
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (3 preceding siblings ...)
  2015-08-21 21:20 ` [PATCH v12 04/32] Move linux_find_memory_regions_full & co Jan Kratochvil
@ 2015-08-21 21:20 ` Jan Kratochvil
  2015-08-22  7:17   ` Eli Zaretskii
  2015-08-21 21:21 ` [PATCH v12 10/32] Code cleanup: Add enum for openp_flags Jan Kratochvil
                   ` (27 subsequent siblings)
  32 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

Producer part of the new "build-id" XML attribute.

gdb/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

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

gdb/doc/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	gdbserver build-id attribute generator.
	* gdb.texinfo (Library List Format for SVR4 Targets): Add
	'build-id' in description, example, new attribute in dtd.

gdb/gdbserver/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	gdbserver build-id attribute generator.
	* linux-low.c (linux-maps.h, search.h, rsp-low.h): Include.
	(ElfXX_Ehdr, ElfXX_Phdr, ElfXX_Nhdr): New.
	(ELFXX_FLD, ELFXX_SIZEOF, ELFXX_ROUNDUP, BUILD_ID_INVALID): New.
	(find_phdr): New.
	(get_dynamic): Use find_pdhr to traverse program headers.
	(struct mapping_entry, mapping_entry_s, free_mapping_entry_vec)
	(compare_mapping_entry_range, struct find_memory_region_callback_data)
	(read_build_id, find_memory_region_callback, lrfind_mapping_entry)
	(get_hex_build_id): New.
	(linux_qxfer_libraries_svr4): Add optional build-id attribute
	to reply XML document.
---
 0 files changed

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b550765..e82e41d 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -39753,6 +39753,8 @@ 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{NT_GNU_BUILD_ID} note, if it exists.
 @end itemize
 
 Additionally the single @code{main-lm} attribute specifies address of
@@ -39770,7 +39772,7 @@ 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="9afccf7cc41e6293476223fe72480854"/>
 </library-list-svr>
 @end smallexample
 
@@ -39779,13 +39781,14 @@ The format of an SVR4 library list is described by this DTD:
 @smallexample
 <!-- library-list-svr4: Root element with versioning -->
 <!ELEMENT library-list-svr4  (library)*>
-<!ATTLIST library-list-svr4  version CDATA   #FIXED  "1.0">
-<!ATTLIST library-list-svr4  main-lm CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  version  CDATA   #FIXED  "1.0">
+<!ATTLIST library-list-svr4  main-lm  CDATA   #IMPLIED>
 <!ELEMENT library            EMPTY>
-<!ATTLIST library            name    CDATA   #REQUIRED>
-<!ATTLIST library            lm      CDATA   #REQUIRED>
-<!ATTLIST library            l_addr  CDATA   #REQUIRED>
-<!ATTLIST library            l_ld    CDATA   #REQUIRED>
+<!ATTLIST library            name     CDATA   #REQUIRED>
+<!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
diff --git a/gdb/features/library-list-svr4.dtd b/gdb/features/library-list-svr4.dtd
index 082945d..5741f03 100644
--- a/gdb/features/library-list-svr4.dtd
+++ b/gdb/features/library-list-svr4.dtd
@@ -6,11 +6,12 @@
 
 <!-- library-list-svr4: Root element with versioning -->
 <!ELEMENT library-list-svr4  (library)*>
-<!ATTLIST library-list-svr4  version CDATA   #FIXED  "1.0">
-<!ATTLIST library-list-svr4  main-lm CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  version  CDATA   #FIXED  "1.0">
+<!ATTLIST library-list-svr4  main-lm  CDATA   #IMPLIED>
 
 <!ELEMENT library            EMPTY>
-<!ATTLIST library            name    CDATA   #REQUIRED>
-<!ATTLIST library            lm      CDATA   #REQUIRED>
-<!ATTLIST library            l_addr  CDATA   #REQUIRED>
-<!ATTLIST library            l_ld    CDATA   #REQUIRED>
+<!ATTLIST library            name     CDATA   #REQUIRED>
+<!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/linux-low.c b/gdb/gdbserver/linux-low.c
index 2bc91c2..ee8563e 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -22,6 +22,7 @@
 #include "agent.h"
 #include "tdesc.h"
 #include "rsp-low.h"
+#include "linux-maps.h"
 
 #include "nat/linux-nat.h"
 #include "nat/linux-waitpid.h"
@@ -43,9 +44,11 @@
 #include <sys/stat.h>
 #include <sys/vfs.h>
 #include <sys/uio.h>
+#include <search.h>
 #include "filestuff.h"
 #include "tracepoint.h"
 #include "hostio.h"
+#include "rsp-low.h"
 #ifndef ELFMAG0
 /* Don't include <linux/elf.h> here.  If it got included by gdb_proc_service.h
    then ELFMAG0 will have been defined.  If it didn't get included by
@@ -185,6 +188,31 @@ lwp_stop_reason (struct lwp_info *lwp)
   return lwp->stop_reason;
 }
 
+typedef union ElfXX_Ehdr
+{
+  Elf32_Ehdr _32;
+  Elf64_Ehdr _64;
+} ElfXX_Ehdr;
+
+typedef union ElfXX_Phdr
+{
+  Elf32_Phdr _32;
+  Elf64_Phdr _64;
+} ElfXX_Phdr;
+
+typedef union ElfXX_Nhdr
+{
+  Elf32_Nhdr _32;
+  Elf64_Nhdr _64;
+} ElfXX_Nhdr;
+
+#define ELFXX_FLD(elf64, hdr, fld) ((elf64) ? (hdr)._64.fld : (hdr)._32.fld)
+#define ELFXX_SIZEOF(elf64, hdr) ((elf64) ? sizeof ((hdr)._64) \
+					  : sizeof ((hdr)._32))
+/* Round up to next 4 byte boundary.  */
+#define ELFXX_ROUNDUP_4(elf64, what) (((what) + 3) & ~(ULONGEST) 3)
+#define BUILD_ID_INVALID "?"
+
 /* A list of all unknown processes which receive stop signals.  Some
    other process will presumably claim each of these as forked
    children momentarily.  */
@@ -6220,15 +6248,38 @@ get_phdr_phnum_from_proc_auxv (const int pid, const int is_elf64,
   return 0;
 }
 
+/* Linearly traverse pheaders and look for P_TYPE pheader.  */
+
+static const void *
+find_phdr (const int is_elf64, const void *const phdr_begin,
+	   const void *const phdr_end, const ULONGEST p_type)
+{
+#define PHDR_NEXT(hdrp) ((const void *) ((const gdb_byte *) (hdrp) + \
+			 ELFXX_SIZEOF (is_elf64, *hdrp)))
+
+  const ElfXX_Phdr *phdr = phdr_begin;
+
+  while (PHDR_NEXT (phdr) <= phdr_end)
+    {
+      if (ELFXX_FLD (is_elf64, *phdr, p_type) == p_type)
+	return phdr;
+      phdr = PHDR_NEXT (phdr);
+    }
+
+  return NULL;
+#undef PHDR_NEXT
+}
+
 /* Return &_DYNAMIC (via PT_DYNAMIC) in the inferior, or 0 if not present.  */
 
 static CORE_ADDR
 get_dynamic (const int pid, const int is_elf64)
 {
   CORE_ADDR phdr_memaddr, relocation;
-  int num_phdr, i;
+  int num_phdr;
   unsigned char *phdr_buf;
-  const int phdr_size = is_elf64 ? sizeof (Elf64_Phdr) : sizeof (Elf32_Phdr);
+  const ElfXX_Phdr *phdr;
+  const int phdr_size = ELFXX_SIZEOF (is_elf64, *phdr);
 
   if (get_phdr_phnum_from_proc_auxv (pid, is_elf64, &phdr_memaddr, &num_phdr))
     return 0;
@@ -6242,22 +6293,10 @@ get_dynamic (const int pid, const int is_elf64)
   /* Compute relocation: it is expected to be 0 for "regular" executables,
      non-zero for PIE ones.  */
   relocation = -1;
-  for (i = 0; relocation == -1 && i < num_phdr; i++)
-    if (is_elf64)
-      {
-	Elf64_Phdr *const p = (Elf64_Phdr *) (phdr_buf + i * phdr_size);
-
-	if (p->p_type == PT_PHDR)
-	  relocation = phdr_memaddr - p->p_vaddr;
-      }
-    else
-      {
-	Elf32_Phdr *const p = (Elf32_Phdr *) (phdr_buf + i * phdr_size);
-
-	if (p->p_type == PT_PHDR)
-	  relocation = phdr_memaddr - p->p_vaddr;
-      }
-
+  phdr = find_phdr (is_elf64, phdr_buf, phdr_buf + num_phdr * phdr_size,
+		    PT_PHDR);
+  if (phdr != NULL)
+    relocation = phdr_memaddr - ELFXX_FLD (is_elf64, *phdr, p_vaddr);
   if (relocation == -1)
     {
       /* PT_PHDR is optional, but necessary for PIE in general.  Fortunately
@@ -6273,23 +6312,11 @@ get_dynamic (const int pid, const int is_elf64)
       return 0;
     }
 
-  for (i = 0; i < num_phdr; i++)
-    {
-      if (is_elf64)
-	{
-	  Elf64_Phdr *const p = (Elf64_Phdr *) (phdr_buf + i * phdr_size);
-
-	  if (p->p_type == PT_DYNAMIC)
-	    return p->p_vaddr + relocation;
-	}
-      else
-	{
-	  Elf32_Phdr *const p = (Elf32_Phdr *) (phdr_buf + i * phdr_size);
+  phdr = find_phdr (is_elf64, phdr_buf, phdr_buf + num_phdr * phdr_size,
+		    PT_DYNAMIC);
 
-	  if (p->p_type == PT_DYNAMIC)
-	    return p->p_vaddr + relocation;
-	}
-    }
+  if (phdr != NULL)
+    return ELFXX_FLD (is_elf64, *phdr, p_vaddr) + relocation;
 
   return 0;
 }
@@ -6451,6 +6478,278 @@ struct link_map_offsets
     int l_prev_offset;
   };
 
+
+/* Structure for holding a mapping.  Only mapping
+   containing l_ld can have hex_build_id set.  */
+
+struct mapping_entry
+{
+  /* Fields are populated from linux_find_memory_region parameters.  */
+
+  ULONGEST vaddr;
+  ULONGEST size;
+  ULONGEST offset;
+  ULONGEST inode;
+
+  /* Hex encoded string allocated using xmalloc, and
+     needs to be freed.  It can be NULL.  */
+
+  char *hex_build_id;
+};
+
+typedef struct mapping_entry mapping_entry_s;
+
+DEF_VEC_O(mapping_entry_s);
+
+/* Free vector of mapping_entry_s objects.  */
+
+static void
+free_mapping_entry_vec (VEC (mapping_entry_s) *lst)
+{
+  int ix;
+  mapping_entry_s *p;
+
+  for (ix = 0; VEC_iterate (mapping_entry_s, lst, ix, p); ++ix)
+    xfree (p->hex_build_id);
+
+  VEC_free (mapping_entry_s, lst);
+}
+
+/* Used for finding a mapping containing the given
+   l_ld passed in K.  */
+
+static int
+compare_mapping_entry_range (const void *const k, const void *const b)
+{
+  const ULONGEST key = *(const CORE_ADDR *) k;
+  const mapping_entry_s *const p = b;
+
+  if (key < p->vaddr)
+    return -1;
+
+  if (key < p->vaddr + p->size)
+    return 0;
+
+  return 1;
+}
+
+struct find_memory_region_callback_data
+{
+  unsigned is_elf64;
+
+  /* Return.  Must be freed with free_mapping_entry_vec.  */
+  VEC (mapping_entry_s) *list;
+};
+
+/* Read build-id from PT_NOTE.
+   Argument LOAD_ADDR represents run time virtual address corresponding to
+   the beginning of the first loadable segment.  L_ADDR is displacement
+   as supplied by the dynamic linker.  */
+
+static void
+read_build_id (struct find_memory_region_callback_data *const p,
+	       mapping_entry_s *const bil, const CORE_ADDR load_addr,
+	       const CORE_ADDR l_addr)
+{
+  const int is_elf64 = p->is_elf64;
+  ElfXX_Ehdr ehdr;
+
+  if (linux_read_memory (load_addr, (unsigned char *) &ehdr,
+			 ELFXX_SIZEOF (is_elf64, ehdr)) == 0
+      && ELFXX_FLD (is_elf64, ehdr, e_ident[EI_MAG0]) == ELFMAG0
+      && ELFXX_FLD (is_elf64, ehdr, e_ident[EI_MAG1]) == ELFMAG1
+      && ELFXX_FLD (is_elf64, ehdr, e_ident[EI_MAG2]) == ELFMAG2
+      && ELFXX_FLD (is_elf64, ehdr, e_ident[EI_MAG3]) == ELFMAG3)
+    {
+      const ElfXX_Phdr *phdr;
+      void *phdr_buf;
+      const unsigned e_phentsize = ELFXX_FLD (is_elf64, ehdr, e_phentsize);
+
+      if (ELFXX_FLD (is_elf64, ehdr, e_phnum) >= 100
+	  || e_phentsize != ELFXX_SIZEOF (is_elf64, *phdr))
+	{
+	  /* Basic sanity check failed.  */
+	  warning (_("Could not identify program header at %s."),
+		   paddress (load_addr));
+	  return;
+	}
+
+      phdr_buf = alloca (ELFXX_FLD (is_elf64, ehdr, e_phnum) * e_phentsize);
+
+      if (linux_read_memory (load_addr + ELFXX_FLD (is_elf64, ehdr, e_phoff),
+			     phdr_buf,
+			     ELFXX_FLD (is_elf64, ehdr, e_phnum) * e_phentsize)
+	  != 0)
+	{
+	  warning (_("Could not read program header at %s."),
+		   paddress (load_addr));
+	  return;
+	}
+
+      phdr = phdr_buf;
+
+      for (;;)
+	{
+	  gdb_byte *pt_note;
+	  const gdb_byte *pt_end;
+	  const ElfXX_Nhdr *nhdr;
+	  CORE_ADDR note_addr;
+
+	  phdr = find_phdr (p->is_elf64, phdr, (gdb_byte *) phdr_buf
+			    + ELFXX_FLD (is_elf64, ehdr, e_phnum) * e_phentsize,
+			    PT_NOTE);
+	  if (phdr == NULL)
+	    break;
+	  pt_note = xmalloc (ELFXX_FLD (is_elf64, *phdr, p_memsz));
+	  note_addr = ELFXX_FLD (is_elf64, *phdr, p_vaddr) + l_addr;
+	  if (linux_read_memory (note_addr, pt_note,
+				 ELFXX_FLD (is_elf64, *phdr, p_memsz)) != 0)
+	    {
+	      xfree (pt_note);
+	      warning (_("Could not read note at address 0x%s"),
+		       paddress (note_addr));
+	      break;
+	    }
+
+	  pt_end = pt_note + ELFXX_FLD (is_elf64, *phdr, p_memsz);
+	  nhdr = (void *) pt_note;
+	  while ((const gdb_byte *) nhdr < pt_end)
+	    {
+	      const size_t namesz
+		= ELFXX_ROUNDUP_4 (is_elf64, ELFXX_FLD (is_elf64, *nhdr,
+							n_namesz));
+	      const size_t descsz
+		= ELFXX_ROUNDUP_4 (is_elf64, ELFXX_FLD (is_elf64, *nhdr,
+							n_descsz));
+	      const size_t note_sz = (ELFXX_SIZEOF (is_elf64, *nhdr) + namesz
+				      + descsz);
+
+	      if (((const gdb_byte *) nhdr + note_sz) > pt_end || note_sz == 0
+		  || descsz == 0)
+		{
+		  warning (_("Malformed PT_NOTE at address 0x%s\n"),
+			   paddress (note_addr + (gdb_byte *) nhdr - pt_note));
+		  break;
+		}
+	      if (ELFXX_FLD (is_elf64, *nhdr, n_type) == NT_GNU_BUILD_ID
+		  && ELFXX_FLD (is_elf64, *nhdr, n_namesz) == 4)
+		{
+		  const char gnu[4] = "GNU\0";
+		  const char *const pname
+		    = (char *) nhdr + ELFXX_SIZEOF (is_elf64, *nhdr);
+
+		  if (memcmp (pname, gnu, 4) == 0)
+		    {
+		      const size_t n_descsz = ELFXX_FLD (is_elf64, *nhdr,
+							 n_descsz);
+
+		      bil->hex_build_id = xmalloc (n_descsz * 2 + 1);
+		      bin2hex ((const gdb_byte *) pname + namesz,
+			       bil->hex_build_id, n_descsz);
+		      xfree (pt_note);
+		      return;
+		    }
+		}
+	      nhdr = (void *) ((gdb_byte *) nhdr + note_sz);
+	    }
+	  xfree (pt_note);
+	}
+    }
+}
+
+static linux_find_memory_region_ftype find_memory_region_callback;
+
+/* Add mapping_entry.  See linux_find_memory_ftype for the parameters
+   description.  */
+
+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)
+{
+  if (inode != 0)
+    {
+      struct find_memory_region_callback_data *const p = data;
+      mapping_entry_s bil;
+
+      bil.vaddr = vaddr;
+      bil.size = size;
+      bil.offset = offset;
+      bil.inode = inode;
+      bil.hex_build_id = NULL;
+
+      VEC_safe_push (mapping_entry_s, p->list, &bil);
+    }
+
+  /* Continue the traversal.  */
+  return 0;
+}
+
+/* Linear reverse find starting from RBEGIN towards REND looking for
+   the lowest vaddr mapping of the same inode and zero offset.  */
+
+static mapping_entry_s *
+lrfind_mapping_entry (mapping_entry_s *const rbegin,
+		      const mapping_entry_s *const rend)
+{
+  mapping_entry_s *p;
+
+  for (p = rbegin - 1; p >= rend; --p)
+    if (p->offset == 0 && p->inode == rbegin->inode)
+      return p;
+
+  return NULL;
+}
+
+/* Get build-id for the given L_LD, where L_LD corresponds to
+   link_map.l_ld as specified by the dynamic linker.
+   DATA must point to already filled list of mapping_entry elements.
+
+   If build-id had not been read, read it and cache in corresponding
+   list element.
+
+   Return build_id as stored in the list element corresponding
+   to L_LD.
+
+   NULL may be returned if build-id could not be fetched.
+
+   Returned string must not be freed explicitly.  */
+
+static const char *
+get_hex_build_id (const CORE_ADDR l_addr, const CORE_ADDR l_ld,
+		  struct find_memory_region_callback_data *const data)
+{
+  mapping_entry_s *bil;
+
+  bil = bsearch (&l_ld, VEC_address (mapping_entry_s, data->list),
+		 VEC_length (mapping_entry_s, data->list),
+		 sizeof (mapping_entry_s), compare_mapping_entry_range);
+
+  if (bil == NULL)
+    return NULL;
+
+  if (bil->hex_build_id == NULL)
+    {
+      mapping_entry_s *bil_min;
+
+      bil_min = lrfind_mapping_entry (bil, VEC_address (mapping_entry_s,
+							data->list));
+      if (bil_min != NULL)
+	read_build_id (data, bil, bil_min->vaddr, l_addr);
+      else
+	{
+	  /* Do not try to find hex_build_id again.  */
+	  bil->hex_build_id = xstrdup (BUILD_ID_INVALID);
+	  warning (_("Could not determine load address; mapping entry with "
+		     "offset 0 corresponding to l_ld = 0x%s could not be "
+		     "found; build-id can not be used."),
+		   paddress (l_ld));
+	}
+    }
+
+  return bil->hex_build_id;
+}
+
 /* Construct qXfer:libraries-svr4:read reply.  */
 
 static int
@@ -6463,6 +6762,18 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
   struct process_info_private *const priv = current_process ()->priv;
   char filename[PATH_MAX];
   int pid, is_elf64;
+  struct find_memory_region_callback_data data;
+  
+  /* COREFILTER_ANON_PRIVATE and COREFILTER_ANON_SHARED do not have an
+     associated file but they may represent a " (deleted)" file with
+     valid ELF header.  */ 
+  const enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
+					| COREFILTER_ANON_SHARED
+					| COREFILTER_MAPPED_PRIVATE
+					| COREFILTER_MAPPED_SHARED
+					| COREFILTER_ELF_HEADERS
+					| COREFILTER_HUGETLB_PRIVATE
+					| COREFILTER_HUGETLB_SHARED);
 
   static const struct link_map_offsets lmo_32bit_offsets =
     {
@@ -6505,6 +6816,14 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
   lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
   ptr_size = is_elf64 ? 8 : 4;
 
+  data.is_elf64 = is_elf64;
+  data.list = NULL;
+  VEC_reserve (mapping_entry_s, data.list, 16);
+  if (linux_find_memory_regions_full (pid, filterflags,
+				      find_memory_region_callback, &data)
+      < 0)
+    warning (_("Finding memory regions failed"));
+
   while (annex[0] != '\0')
     {
       const char *sep;
@@ -6611,6 +6930,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;
+	      const char *hex_enc_build_id = NULL;
 
 	      if (!header_done)
 		{
@@ -6619,7 +6939,11 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 		  header_done = 1;
 		}
 
-	      while (allocated < p - document + len + 200)
+	      hex_enc_build_id = get_hex_build_id (l_addr, l_ld, &data);
+
+	      while (allocated < (p - document + len + 200
+				  + (hex_enc_build_id != NULL
+				     ? strlen (hex_enc_build_id) : 0)))
 		{
 		  /* Expand to guarantee sufficient storage.  */
 		  uintptr_t document_len = p - document;
@@ -6631,9 +6955,13 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 
 	      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
+		  && strcmp (hex_enc_build_id, BUILD_ID_INVALID) != 0)
+		p += sprintf (p, " build-id=\"%s\"", hex_enc_build_id);
+	      p += sprintf (p, "/>");
 	      free (name);
 	    }
 	}
@@ -6660,6 +6988,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 
   memcpy (readbuf, document + offset, len);
   xfree (document);
+  free_mapping_entry_vec (data.list);
 
   return len;
 }

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 00/32] Validate binary before use
@ 2015-08-21 21:20 Jan Kratochvil
  2015-08-21 21:20 ` [PATCH v12 02/32] Move gdb_regex* to common/ Jan Kratochvil
                   ` (32 more replies)
  0 siblings, 33 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:20 UTC (permalink / raw)
  To: gdb-patches

Hi,

git://sourceware.org/git/archer.git
jankratochvil/gdbserverbuildid

The new file-locating parts are freshly coded, there are many possible future
improvements but I find the patchset as a minimal functional upstreamable
support for locating files from gdbserver build-ids.

It does not support build-ids from linux-nat and core files (as Fedora GDB
supports).  It also does not ask librpm for debuginfo-install suggestions.

There remain callers (like exec_file_and_symbols_resync) using various old
functions returning only 'char *filename;'.  This means if target binary has
build-id GDB will open the file twice - first to verify the build-id and second
to really start using that file.  The new functions returning 'struct
file_location file;' open such file as BFD only once.

It could cache already unsuccessfully searched paths.  With current sysroot
":target:" (that is ""+"target:") if target_filesystem_is_local() then all the
directories including debug-file-directory etc. will be searched twice (if no
matching file is found).  A quick but incomplete fix would be to only suppress
the second "target:" default sysroot part if target_filesystem_is_local().

This means that this patchset as is may be a performance regression.  But main
executable is only one and shared libraries should use the "fast" 'struct
file_location file;' code path.  But I haven't really traced/benchmarked it.

It could suppress repeated warning messages about non-matching build-ids.  It
may be related to the previous paragraph.

GDB could offload the build-id search in target: directories to gdbserver.
Currently if sysroot and/or debug-file-directory and other directory lists
contain multiple target:-starting paths GDB will ask gdbserver for each one
separately, each time sending vFile:open:..., multiple vFile:pread: etc.
(guessing), with each call costing one RTT.


Thanks,
Jan


v12
 * Add COREFILTER_ANON_PRIVATE and COREFILTER_ANON_SHARED to filterflags.
 * Free build_id in free_so(), not clear_so().
 * Add all the parts for locating (not just verifying) files by build-id.

v11
 * Use configure.tgt+ALL_TARGET_OBS instead of config/**.mh .
 * Move linux-maps.[ch] nat/ -> common/ .
 * Rename set solib-build-id-force -> set validate-build-id .
 * Rebase: Remove bfd_target_elf_flavour and elf_tdata->build_id requirement.
 * More descriptive warning messages.

v7
 * move linux-maps.[ch] common/->nat/ and target-utils.[ch] common/->target/
 * remove GDBSERVER #ifdefs
 * rebase on top of the new 'struct inferior *inf' parameter

v6
 * move also gdb_regex* to common/ as discussed above, also in config*.ac
 * skip_to_space{,_const}() were moved to common/
 * common/common-defs.h #include reordering
 * new passing of enum filterflags from linux_qxfer_libraries_svr4()
 * dropped refactoring of code moved to common/ that avoided GDB exceptions
 * new svr4_copy_library_list() needs to handle new so_list->build_id

v5
 * svr4_validate() considers missing local build-id as not-a-match
 * target_so_ops->validate() now returns not-a-match reason as a string
 * rename common/common-target.[ch] -> common/target-utils.[ch]
 * testcase runs (but broken) even on different-filesystem remote target
 * testcase simplified by using with_test_prefix()

v4
 * NEWS, doc/gdb.texinfo additions.
 * Used host-defs.h.
 * New set/show solib-build-id-force.
 * testsuite: Do not run on non-localhost remote targets.

v3
	[patchv3 0/8] Validate binary before use
	https://sourceware.org/ml/gdb-patches/2014-02/msg00842.html
	Message-ID: <20140227213229.GA21121@host2.jankratochvil.net>
 * Implemented the review comments I made.
 * Removed fetching build-id in solib-svr4.c for NAT run.

v2
	[PATCH 0/8] v2 - validate binary before use
	https://sourceware.org/ml/gdb-patches/2013-04/msg00472.html
	Message-ID: <1366127096-5744-1-git-send-email-ARistovski@qnx.com>

---

 gdb/testsuite/gdb.base/attach.exp              |    7 +
 gdb/testsuite/gdb.base/break-probes.exp        |    7 +
 gdb/testsuite/gdb.base/main-mismatch-mod.c     |   39 +++++
 gdb/testsuite/gdb.base/main-mismatch.c         |   39 +++++
 gdb/testsuite/gdb.base/main-mismatch.exp       |  158 +++++++++++++++++++
 gdb/testsuite/gdb.base/solib-mismatch-lib.c    |   30 ++++
 gdb/testsuite/gdb.base/solib-mismatch-libmod.c |   30 ++++
 gdb/testsuite/gdb.base/solib-mismatch.c        |   56 +++++++
 gdb/testsuite/gdb.base/solib-mismatch.exp      |  198 ++++++++++++++++++++++++
 9 files changed, 560 insertions(+), 4 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch-mod.c
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch.c
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch.exp
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch-lib.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch-libmod.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch.exp

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 11/32] Code cleanup: Remove OPF_RETURN_REALPATH
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (5 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 10/32] Code cleanup: Add enum for openp_flags Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-21 21:21 ` [PATCH v12 07/32] Code cleanup: Make solib_find_1 variable const Jan Kratochvil
                   ` (25 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Hi,

OPF_RETURN_REALPATH is used only at the end of openp() to convert the returned
values.  That is not useful, code can be simplified if callers that passed
OPF_RETURN_REALPATH adjust the returned values on their own.  Or at least it
helps further refactorizations.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* cli/cli-cmds.c (find_and_open_script): Remove OPF_RETURN_REALPATH.
	Call gdb_realpath_and_xfree.
	* defs.h (enum openp_flags): Add OPF_NONE, remove OPF_RETURN_REALPATH.
	* dwarf2read.c (try_open_dwop_file): Remove OPF_RETURN_REALPATH.  Call
	gdb_realpath_and_xfree.
	* nto-tdep.c (nto_find_and_open_solib): Remove OPF_RETURN_REALPATH.
	Call gdb_realpath_and_xfree and xstrdup.
	* solib.c (solib_find_2): New variable temp_pathname_is_realpath.
	Remove OPF_RETURN_REALPATH.  Conditionally call gdb_realpath_and_xfree.
	* source.c (openp): Remove OPF_RETURN_REALPATH processing.
	(source_full_path_of, find_and_open_source): Remove
	OPF_RETURN_REALPATH.  Call gdb_realpath_and_xfree.
	* symfile.c (symfile_bfd_open): Likewise.
	* utils.c (gdb_realpath_and_xfree): New function.
	* utils.h (gdb_realpath_and_xfree): New prototype.
---
 0 files changed

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index a5a4c7c..5b90d4e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -500,7 +500,7 @@ find_and_open_script (const char *script_file, int search_path,
   char *file;
   int fd;
   struct cleanup *old_cleanups;
-  enum openp_flags search_flags = OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH;
+  enum openp_flags search_flags = OPF_TRY_CWD_FIRST;
 
   file = tilde_expand (script_file);
   old_cleanups = make_cleanup (xfree, file);
@@ -523,6 +523,8 @@ find_and_open_script (const char *script_file, int search_path,
 
   do_cleanups (old_cleanups);
 
+  *full_pathp = gdb_realpath_and_xfree (*full_pathp);
+
   *streamp = fdopen (fd, FOPEN_RT);
   if (*streamp == NULL)
     {
diff --git a/gdb/defs.h b/gdb/defs.h
index 3d248f6..ca95634 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -323,6 +323,9 @@ extern const char *pc_prefix (CORE_ADDR);
 /* See openp function definition for their description.  */
 enum openp_flags
 {
+  /* No options specified, type-compatibile with the enum.  */
+  OPF_NONE            = 0,
+
   /* Try to open ./STRING before searching PATH (ie pretend the first
      element of PATH is ".").  This also indicates that, unless
      OPF_SEARCH_IN_PATH is also specified, a slash in STRING disables
@@ -334,9 +337,6 @@ enum openp_flags
   /* Absolute names will also be searched in path (we usually want this
      for source files but not for executables).  */
   OPF_SEARCH_IN_PATH  = (1 << 1),
-
-  /* See openp, to be removed.  */
-  OPF_RETURN_REALPATH = (1 << 2),
 };
 
 extern int openp (const char *, enum openp_flags, const char *, int, char **);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 23b60f9..835ba4f 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -10470,7 +10470,7 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   else
     search_path = xstrdup (debug_file_directory);
 
-  flags = OPF_RETURN_REALPATH;
+  flags = OPF_NONE;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
   desc = openp (search_path, flags, file_name,
@@ -10478,6 +10478,7 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   xfree (search_path);
   if (desc < 0)
     return NULL;
+  absolute_name = gdb_realpath_and_xfree (absolute_name);
 
   sym_bfd = gdb_bfd_open (absolute_name, gnutarget, desc);
   xfree (absolute_name);
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
index ba3c845..72909fd 100644
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -127,7 +127,7 @@ nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
 	     arch_path);
 
   base = lbasename (solib);
-  ret = openp (buf, OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, base, o_flags,
+  ret = openp (buf, OPF_TRY_CWD_FIRST, base, o_flags,
 	       temp_pathname);
   if (ret < 0 && base != solib)
     {
@@ -136,11 +136,13 @@ nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
       if (temp_pathname)
 	{
 	  if (ret >= 0)
-	    *temp_pathname = gdb_realpath (arch_path);
+	    *temp_pathname = xstrdup (arch_path);
 	  else
 	    *temp_pathname = NULL;
 	}
     }
+  if (ret >= 0)
+    *temp_pathname = gdb_realpath_and_xfree (*temp_pathname);
   return ret;
 }
 
diff --git a/gdb/solib.c b/gdb/solib.c
index 98af2c0..1c408c0 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -158,7 +158,7 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
   char *temp_pathname = NULL;
   const char *fskind = effective_target_file_system_kind ();
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  int prefix_len, orig_prefix_len;
+  int prefix_len, orig_prefix_len, temp_pathname_is_realpath;
 
   /* If the absolute prefix starts with "target:" but the filesystem
      accessed by the target_fileio_* methods is the local filesystem
@@ -311,7 +311,12 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
      needs to be freed.  */
 
   if (found_file < 0)
-    temp_pathname = NULL;
+    {
+      temp_pathname = NULL;
+      temp_pathname_is_realpath = 1;
+    }
+  else
+    temp_pathname_is_realpath = 0;
 
   /* If the search in gdb_sysroot failed, and the path name is
      absolute at this point, make it relative.  (openp will try and open the
@@ -331,8 +336,7 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
   /* If not found, and we're looking for a solib, search the
      solib_search_path (if any).  */
   if (is_solib && found_file < 0 && solib_search_path != NULL)
-    found_file = openp (solib_search_path,
-			OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+    found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
 			in_pathname, O_RDONLY | O_BINARY, &temp_pathname);
 
   /* If not found, and we're looking for a solib, next search the
@@ -340,8 +344,7 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
      path).  This is to allow reading solibs from a path that differs
      from the opened path.  */
   if (is_solib && found_file < 0 && solib_search_path != NULL)
-    found_file = openp (solib_search_path,
-			OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+    found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
 			target_lbasename (fskind, in_pathname),
 			O_RDONLY | O_BINARY, &temp_pathname);
 
@@ -355,7 +358,7 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
   if (found_file < 0 && sysroot == NULL)
     found_file = openp (get_in_environ (current_inferior ()->environment,
 					"PATH"),
-			OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
+			OPF_TRY_CWD_FIRST, in_pathname,
 			O_RDONLY | O_BINARY, &temp_pathname);
 
   /* If not found, and we're looking for a solib, next search the
@@ -363,9 +366,12 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
   if (is_solib && found_file < 0 && sysroot == NULL)
     found_file = openp (get_in_environ (current_inferior ()->environment,
 					"LD_LIBRARY_PATH"),
-			OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH, in_pathname,
+			OPF_TRY_CWD_FIRST, in_pathname,
 			O_RDONLY | O_BINARY, &temp_pathname);
 
+  if (found_file >= 0 && temp_pathname_is_realpath)
+    temp_pathname = gdb_realpath_and_xfree (temp_pathname);
+
   if (fd == NULL)
     {
       if (found_file >= 0)
diff --git a/gdb/source.c b/gdb/source.c
index 888ed2b..97849f8 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -749,11 +749,6 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
    and the file, sigh!  Emacs gets confuzzed by this when we print the
    source file name!!! 
 
-   If OPTS has OPF_RETURN_REALPATH set return FILENAME_OPENED resolved by
-   gdb_realpath.  Even without OPF_RETURN_REALPATH this function still returns
-   filename starting with "/".  If FILENAME_OPENED is NULL this option has no
-   effect.
-
    If a file is found, return the descriptor.
    Otherwise, return -1, with errno set for the last name we tried to open.  */
 
@@ -910,13 +905,10 @@ openp (const char *path, enum openp_flags opts, const char *string,
 done:
   if (filename_opened)
     {
-      /* If a file was opened, canonicalize its filename.  */
       if (fd < 0)
 	*filename_opened = NULL;
-      else if ((opts & OPF_RETURN_REALPATH) != 0)
-	*filename_opened = gdb_realpath (filename);
       else
-	*filename_opened = gdb_abspath (filename);
+	*filename_opened = xstrdup (filename);
     }
 
   return fd;
@@ -939,14 +931,15 @@ source_full_path_of (const char *filename, char **full_pathname)
 {
   int fd;
 
-  fd = openp (source_path,
-	      OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH,
+  fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH,
 	      filename, O_RDONLY, full_pathname);
   if (fd < 0)
     {
       *full_pathname = NULL;
       return 0;
     }
+  
+  *full_pathname = gdb_realpath_and_xfree (*full_pathname);
 
   close (fd);
   return 1;
@@ -1113,17 +1106,18 @@ find_and_open_source (const char *filename,
         }
     }
 
-  result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, filename,
-		  OPEN_MODE, fullname);
+  result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, fullname);
   if (result < 0)
     {
       /* Didn't work.  Try using just the basename.  */
       p = lbasename (filename);
       if (p != filename)
-	result = openp (path, OPF_SEARCH_IN_PATH | OPF_RETURN_REALPATH, p,
-			OPEN_MODE, fullname);
+	result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, fullname);
     }
 
+  if (result >= 0)
+    *fullname = gdb_realpath_and_xfree (*fullname);
+
   do_cleanups (cleanup);
   return result;
 }
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 856572a..40f0451 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1731,8 +1731,7 @@ symfile_bfd_open (const char *name)
       expanded_name = tilde_expand (name); /* Returns 1st new malloc'd copy.  */
 
       /* Look down path for it, allocate 2nd new malloc'd copy.  */
-      desc = openp (getenv ("PATH"),
-		    OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+      desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
 		    expanded_name, O_RDONLY | O_BINARY, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
       if (desc < 0)
@@ -1740,8 +1739,7 @@ symfile_bfd_open (const char *name)
 	  char *exename = alloca (strlen (expanded_name) + 5);
 
 	  strcat (strcpy (exename, expanded_name), ".exe");
-	  desc = openp (getenv ("PATH"),
-			OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH,
+	  desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
 			exename, O_RDONLY | O_BINARY, &absolute_name);
 	}
 #endif
@@ -1752,6 +1750,7 @@ symfile_bfd_open (const char *name)
 	}
 
       xfree (expanded_name);
+      absolute_name = gdb_realpath_and_xfree (absolute_name);
       make_cleanup (xfree, absolute_name);
       name = absolute_name;
     }
diff --git a/gdb/utils.c b/gdb/utils.c
index 41dca7f..1bd273a 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -2820,6 +2820,17 @@ gdb_realpath (const char *filename)
   return xstrdup (filename);
 }
 
+/* Wrap gdb_realpath by also calling xfree for the FILENAME parameter.  */
+
+char *
+gdb_realpath_and_xfree (char *filename)
+{
+  char *retval = gdb_realpath (filename);
+
+  xfree (filename);
+  return retval;
+}
+
 /* Return a copy of FILENAME, with its directory prefix canonicalized
    by gdb_realpath.  */
 
diff --git a/gdb/utils.h b/gdb/utils.h
index 995a1cf..e15ff6d 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -124,6 +124,8 @@ extern struct cleanup *make_bpstat_clear_actions_cleanup (void);
 
 extern char *gdb_realpath (const char *);
 
+extern char *gdb_realpath_and_xfree (char *filename);
+
 extern char *gdb_realpath_keepfile (const char *);
 
 extern char *gdb_abspath (const char *);

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 12/32] Code cleanup: Remove openp parameter mode
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (8 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 06/32] Validate symbol file using build-id Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-21 21:21 ` [PATCH v12 08/32] Permit multiple sysroot directories Jan Kratochvil
                   ` (22 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Hi,

simplify the code, make it also suitable for more code refactorings.
The new flag OPF_OPEN_RW_TMP is removed later in this patch series.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* cli/cli-cmds.c (find_and_open_script): Update openp caller.
	* defs.h (enum openp_flags): Add OPF_OPEN_RW_TMP.
	(openp): Remove parameter mode.
	* dwarf2read.c (try_open_dwop_file): Update openp caller.
	* exec.c (exec_file_attach): Likewise.
	* nto-tdep.c (nto_find_and_open_solib): Remove parameter o_flags,
	update openp caller.
	* nto-tdep.h (nto_find_and_open_solib): Remove parameter o_flags.
	* solib.c (solib_find_2): Update openp and find_and_open_solib caller.
	* solist.h (struct target_so_ops): Remove parameter o_flags from
	find_and_open_solib method.
	* source.c (openp): Change parameter mode to a new variable.
	(source_full_path_of, find_and_open_source): Update openp caller.
	* symfile.c (symfile_bfd_open): Likewise.
---
 0 files changed

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 5b90d4e..d495463 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -510,8 +510,7 @@ find_and_open_script (const char *script_file, int search_path,
 
   /* Search for and open 'file' on the search path used for source
      files.  Put the full location in *FULL_PATHP.  */
-  fd = openp (source_path, search_flags,
-	      file, O_RDONLY, full_pathp);
+  fd = openp (source_path, search_flags, file, full_pathp);
 
   if (fd == -1)
     {
diff --git a/gdb/defs.h b/gdb/defs.h
index ca95634..7795b4a 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -337,9 +337,12 @@ enum openp_flags
   /* Absolute names will also be searched in path (we usually want this
      for source files but not for executables).  */
   OPF_SEARCH_IN_PATH  = (1 << 1),
+
+  /* Open the file in read/write mode if WRITE_FILES says so.  */
+  OPF_OPEN_RW_TMP     = (1 << 3),
 };
 
-extern int openp (const char *, enum openp_flags, const char *, int, char **);
+extern int openp (const char *, enum openp_flags, const char *, char **);
 
 extern int source_full_path_of (const char *, char **);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 835ba4f..ae06e14 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -10473,8 +10473,7 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   flags = OPF_NONE;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
-  desc = openp (search_path, flags, file_name,
-		O_RDONLY | O_BINARY, &absolute_name);
+  desc = openp (search_path, flags, file_name, &absolute_name);
   xfree (search_path);
   if (desc < 0)
     return NULL;
diff --git a/gdb/exec.c b/gdb/exec.c
index f1b1049..e87d154 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -247,21 +247,18 @@ exec_file_attach (const char *filename, int from_tty)
 	}
       else
 	{
-	  scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-				filename, write_files ?
-				O_RDWR | O_BINARY : O_RDONLY | O_BINARY,
-				&scratch_pathname);
+	  scratch_chan = openp (getenv ("PATH"),
+				OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
+				filename, &scratch_pathname);
 #if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
 	  if (scratch_chan < 0)
 	    {
 	      char *exename = alloca (strlen (filename) + 5);
 
 	      strcat (strcpy (exename, filename), ".exe");
-	      scratch_chan = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-				    exename, write_files ?
-				    O_RDWR | O_BINARY
-				    : O_RDONLY | O_BINARY,
-				    &scratch_pathname);
+	      scratch_chan = openp (getenv ("PATH"),
+	                            OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
+				    exename, &scratch_pathname);
 	    }
 #endif
 	  if (scratch_chan < 0)
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
index 72909fd..7c8b4ce 100644
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -82,7 +82,7 @@ nto_map_arch_to_cputype (const char *arch)
 }
 
 int
-nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
+nto_find_and_open_solib (char *solib, char **temp_pathname)
 {
   char *buf, *arch_path, *nto_root;
   const char *endian;
@@ -127,12 +127,11 @@ nto_find_and_open_solib (char *solib, unsigned o_flags, char **temp_pathname)
 	     arch_path);
 
   base = lbasename (solib);
-  ret = openp (buf, OPF_TRY_CWD_FIRST, base, o_flags,
-	       temp_pathname);
+  ret = openp (buf, OPF_TRY_CWD_FIRST, base, temp_pathname);
   if (ret < 0 && base != solib)
     {
       xsnprintf (arch_path, arch_len, "/%s", solib);
-      ret = open (arch_path, o_flags, 0);
+      ret = open (arch_path, O_RDONLY | O_BINARY);
       if (temp_pathname)
 	{
 	  if (ret >= 0)
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
index bd85d2a..1f8045a 100644
--- a/gdb/nto-tdep.h
+++ b/gdb/nto-tdep.h
@@ -154,7 +154,7 @@ void nto_relocate_section_addresses (struct so_list *,
 
 int nto_map_arch_to_cputype (const char *);
 
-int nto_find_and_open_solib (char *, unsigned, char **);
+int nto_find_and_open_solib (char *, char **);
 
 enum gdb_osabi nto_elf_osabi_sniffer (bfd *abfd);
 
diff --git a/gdb/solib.c b/gdb/solib.c
index 1c408c0..b16f47b 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -337,7 +337,7 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
      solib_search_path (if any).  */
   if (is_solib && found_file < 0 && solib_search_path != NULL)
     found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-			in_pathname, O_RDONLY | O_BINARY, &temp_pathname);
+			in_pathname, &temp_pathname);
 
   /* If not found, and we're looking for a solib, next search the
      solib_search_path (if any) for the basename only (ignoring the
@@ -345,29 +345,25 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
      from the opened path.  */
   if (is_solib && found_file < 0 && solib_search_path != NULL)
     found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-			target_lbasename (fskind, in_pathname),
-			O_RDONLY | O_BINARY, &temp_pathname);
+			target_lbasename (fskind, in_pathname), &temp_pathname);
 
   /* If not found, and we're looking for a solib, try to use target
      supplied solib search method.  */
   if (is_solib && found_file < 0 && ops->find_and_open_solib)
-    found_file = ops->find_and_open_solib (in_pathname, O_RDONLY | O_BINARY,
-					   &temp_pathname);
+    found_file = ops->find_and_open_solib (in_pathname, &temp_pathname);
 
   /* If not found, next search the inferior's $PATH environment variable.  */
   if (found_file < 0 && sysroot == NULL)
     found_file = openp (get_in_environ (current_inferior ()->environment,
 					"PATH"),
-			OPF_TRY_CWD_FIRST, in_pathname,
-			O_RDONLY | O_BINARY, &temp_pathname);
+			OPF_TRY_CWD_FIRST, in_pathname, &temp_pathname);
 
   /* If not found, and we're looking for a solib, next search the
      inferior's $LD_LIBRARY_PATH environment variable.  */
   if (is_solib && found_file < 0 && sysroot == NULL)
     found_file = openp (get_in_environ (current_inferior ()->environment,
 					"LD_LIBRARY_PATH"),
-			OPF_TRY_CWD_FIRST, in_pathname,
-			O_RDONLY | O_BINARY, &temp_pathname);
+			OPF_TRY_CWD_FIRST, in_pathname, &temp_pathname);
 
   if (found_file >= 0 && temp_pathname_is_realpath)
     temp_pathname = gdb_realpath_and_xfree (temp_pathname);
diff --git a/gdb/solist.h b/gdb/solist.h
index af9acc2..47e9d88 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -146,8 +146,7 @@ struct target_so_ops
        If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
        pointer to a malloc'd and realpath'd copy of SONAME is stored there,
        otherwise NULL is stored there.  */
-    int (*find_and_open_solib) (char *soname,
-        unsigned o_flags, char **temp_pathname);
+    int (*find_and_open_solib) (char *soname, char **temp_pathname);
 
     /* Hook for looking up global symbols in a library-specific way.  */
     struct block_symbol (*lookup_lib_global_symbol)
diff --git a/gdb/source.c b/gdb/source.c
index 97849f8..8dfe580 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -737,9 +737,8 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
   return vec;
 }
 
-/* Open a file named STRING, searching path PATH (dir names sep by some char)
-   using mode MODE in the calls to open.  You cannot use this function to
-   create files (O_CREAT).
+/* Open a file named STRING, searching path PATH (dir names sep by some char).
+   You cannot use this function to create files.
 
    OPTS specifies the function behaviour in specific cases.
 
@@ -756,18 +755,16 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
     >>>>  eg executable, non-directory.  */
 int
 openp (const char *path, enum openp_flags opts, const char *string,
-       int mode, char **filename_opened)
+       char **filename_opened)
 {
   int fd;
   char *filename;
   int alloclen;
   VEC (char_ptr) *dir_vec;
   struct cleanup *back_to;
-  int ix;
+  int ix, mode;
   char *dir;
 
-  /* The open syscall MODE parameter is not specified.  */
-  gdb_assert ((mode & O_CREAT) == 0);
   gdb_assert (string != NULL);
 
   /* A file with an empty name cannot possibly exist.  Report a failure
@@ -786,7 +783,8 @@ openp (const char *path, enum openp_flags opts, const char *string,
   if (!path)
     path = ".";
 
-  mode |= O_BINARY;
+  mode = (O_BINARY | (((opts & OPF_OPEN_RW_TMP) && write_files)
+		      ? O_RDWR : O_RDONLY));
 
   if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string))
     {
@@ -932,7 +930,7 @@ source_full_path_of (const char *filename, char **full_pathname)
   int fd;
 
   fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH,
-	      filename, O_RDONLY, full_pathname);
+	      filename, full_pathname);
   if (fd < 0)
     {
       *full_pathname = NULL;
@@ -1106,13 +1104,17 @@ find_and_open_source (const char *filename,
         }
     }
 
-  result = openp (path, OPF_SEARCH_IN_PATH, filename, OPEN_MODE, fullname);
+  gdb_assert (OPEN_MODE == (O_RDONLY | O_BINARY));
+  result = openp (path, OPF_SEARCH_IN_PATH, filename, fullname);
   if (result < 0)
     {
       /* Didn't work.  Try using just the basename.  */
       p = lbasename (filename);
       if (p != filename)
-	result = openp (path, OPF_SEARCH_IN_PATH, p, OPEN_MODE, fullname);
+	{
+	  gdb_assert (OPEN_MODE == (O_RDONLY | O_BINARY));
+	  result = openp (path, OPF_SEARCH_IN_PATH, p, fullname);
+	}
     }
 
   if (result >= 0)
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 40f0451..c0eb4ce 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1732,7 +1732,7 @@ symfile_bfd_open (const char *name)
 
       /* Look down path for it, allocate 2nd new malloc'd copy.  */
       desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-		    expanded_name, O_RDONLY | O_BINARY, &absolute_name);
+		    expanded_name, &absolute_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
       if (desc < 0)
 	{
@@ -1740,7 +1740,7 @@ symfile_bfd_open (const char *name)
 
 	  strcat (strcpy (exename, expanded_name), ".exe");
 	  desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-			exename, O_RDONLY | O_BINARY, &absolute_name);
+			exename, &absolute_name);
 	}
 #endif
       if (desc < 0)

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 07/32] Code cleanup: Make solib_find_1 variable const
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (6 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 11/32] Code cleanup: Remove OPF_RETURN_REALPATH Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-21 21:21 ` [PATCH v12 06/32] Validate symbol file using build-id Jan Kratochvil
                   ` (24 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Hi,

it gets used in the next patch.


Jan


2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* solib.c (solib_find_1): Make sysroot variable const.
---
 0 files changed

diff --git a/gdb/solib.c b/gdb/solib.c
index cf78f6a..be31ffd 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -157,7 +157,7 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
   char *temp_pathname = NULL;
   const char *fskind = effective_target_file_system_kind ();
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  char *sysroot = gdb_sysroot;
+  const char *sysroot = gdb_sysroot;
   int prefix_len, orig_prefix_len;
 
   /* If the absolute prefix starts with "target:" but the filesystem
@@ -179,8 +179,10 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
     sysroot = NULL;
   else if (prefix_len != orig_prefix_len)
     {
-      sysroot = savestring (sysroot, prefix_len);
-      make_cleanup (xfree, sysroot);
+      char *s = savestring (sysroot, prefix_len);
+
+      make_cleanup (xfree, s);
+      sysroot = s;
     }
 
   /* If we're on a non-DOS-based system, backslashes won't be

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 08/32] Permit multiple sysroot directories
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (9 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 12/32] Code cleanup: Remove openp parameter mode Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-22  7:31   ` Eli Zaretskii
  2015-08-21 21:22 ` [PATCH v12 20/32] symfile_bfd_open: Make it use openp_bfd() Jan Kratochvil
                   ` (21 subsequent siblings)
  32 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Hi,

the goal is to have both "" and "target:" as the default gdb_sysroot, in this
order.  Therefore permit multiple directory components of gdb_sysroot.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* NEWS (Changes since GDB 7.10): Mention set sysroot and show sysroot.
	* solib.c: Include source.h.
	(solib_find_1): Rename to ...
	(solib_find_2): ... here and change the sysroot variable to parameter.
	(solib_find_1): Call it using dirnames_to_char_ptr_vec_target_exc.
	* source.c (dirnames_to_char_ptr_vec_target_exc): New function.
	* source.h (dirnames_to_char_ptr_vec_target_exc): New declaration.

gdb/doc/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.texinfo (Files): Permit set sysroot and show sysroot to have
	multiple components.
---
 0 files changed

diff --git a/gdb/NEWS b/gdb/NEWS
index fce33f3..f5a01e8 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -35,6 +35,9 @@ show debug bfd-cache
   The "/m" option is now considered deprecated: its "source-centric"
   output hasn't proved useful in practice.
 
+* The "set sysroot" (and "show sysroot") commands now permit multiple
+  directory paths.
+
 * New options
 
 set validate-build-id (on|off)
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index e82e41d..fa30007 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18154,7 +18154,8 @@ to specify the search directories for target libraries.
 @kindex set solib-absolute-prefix
 @kindex set sysroot
 @item set sysroot @var{path}
-Use @var{path} as the system root for the program being debugged.  Any
+Use @var{path} as the system root (or list of system roots) for the
+program being debugged.  Any
 absolute shared library paths will be prefixed with @var{path}; many
 runtime loaders store the absolute paths to the shared library in the
 target program's memory.  When starting processes remotely, and when
@@ -18166,7 +18167,10 @@ to be laid out in the same way that they are on the target, with
 e.g.@: a @file{/bin}, @file{/lib} and @file{/usr/lib} hierarchy under
 @var{path}.
 
-If @var{path} starts with the sequence @file{target:} and the target
+Multiple entries may be delimited by the host platform path separator in use.
+
+If @var{path} starts with the sequence @file{target:} (even if the host
+platform path separator is character @file{:}) and the target
 system is remote then @value{GDBN} will retrieve the target binaries
 from the remote system.  This is only supported when using a remote
 target that supports the @code{remote get} command (@pxref{File
@@ -18248,7 +18252,7 @@ location.
 
 @kindex show sysroot
 @item show sysroot
-Display the current executable and shared library prefix.
+Display the current executable and shared library prefix(es).
 
 @kindex set solib-search-path
 @item set solib-search-path @var{path}
diff --git a/gdb/solib.c b/gdb/solib.c
index be31ffd..98af2c0 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -46,6 +46,7 @@
 #include "filesystem.h"
 #include "gdb_bfd.h"
 #include "filestuff.h"
+#include "source.h"
 
 /* Architecture-specific operations.  */
 
@@ -118,9 +119,9 @@ show_solib_search_path (struct ui_file *file, int from_tty,
    is non-NULL, *FD is set to either -1 or an open file handle for
    the binary file.
 
-   Global variable GDB_SYSROOT is used as a prefix directory
+   Parameter SYSROOT is used as a prefix directory
    to search for binary files if they have an absolute path.
-   If GDB_SYSROOT starts with "target:" and target filesystem
+   If SYSROOT starts with "target:" and target filesystem
    is the local filesystem then the "target:" prefix will be
    stripped before the search starts.  This ensures that the
    same search algorithm is used for local files regardless of
@@ -150,14 +151,13 @@ show_solib_search_path (struct ui_file *file, int from_tty,
 */
 
 static char *
-solib_find_1 (char *in_pathname, int *fd, int is_solib)
+solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
 {
   const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   int found_file = -1;
   char *temp_pathname = NULL;
   const char *fskind = effective_target_file_system_kind ();
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  const char *sysroot = gdb_sysroot;
   int prefix_len, orig_prefix_len;
 
   /* If the absolute prefix starts with "target:" but the filesystem
@@ -377,6 +377,31 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
   return temp_pathname;
 }
 
+/* It is an solib_find_2 wrapper handling multiple directory components
+   of GDB_SYSROOT.  */
+
+static char *
+solib_find_1 (char *in_pathname, int *fd, int is_solib)
+{
+  VEC (char_ptr) *sysroot_vec;
+  struct cleanup *back_to;
+  char *retval, *sysroot;
+  int ix;
+
+  sysroot_vec = dirnames_to_char_ptr_vec_target_exc (gdb_sysroot);
+  back_to = make_cleanup_free_char_ptr_vec (sysroot_vec);
+
+  for (ix = 0; VEC_iterate (char_ptr, sysroot_vec, ix, sysroot); ++ix)
+    {
+      retval = solib_find_2 (in_pathname, fd, is_solib, sysroot);
+      if (retval != NULL)
+	break;
+    }
+
+  do_cleanups (back_to);
+  return retval;
+}
+
 /* Return the full pathname of the main executable, or NULL if not
    found.  The returned pathname is malloc'ed and must be freed by
    the caller.  If FD is non-NULL, *FD is set to either -1 or an open
diff --git a/gdb/source.c b/gdb/source.c
index 0c23b7e..4cd3046 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -702,6 +702,41 @@ is_regular_file (const char *name)
   return S_ISREG (st.st_mode);
 }
 
+/* It is a wrapper of dirnames_to_char_ptr_vec which handles possible
+   TARGET_SYSROOT_PREFIX clash with DIRNAME_SEPARATOR.  */
+
+VEC (char_ptr) *
+dirnames_to_char_ptr_vec_target_exc (const char *string)
+{
+  VEC (char_ptr) *vec = dirnames_to_char_ptr_vec (string);
+  int ix;
+  char *s;
+
+  if (DIRNAME_SEPARATOR == ':')
+    for (ix = 0; ix < VEC_length (char_ptr, vec);)
+      {
+	char *s = VEC_index (char_ptr, vec, ix);
+
+	gdb_assert (strcmp (TARGET_SYSROOT_PREFIX, "target" ":") == 0);
+	if (strcmp (s, "target") != 0)
+	  {
+	    ++ix;
+	    continue;
+	  }
+	VEC_ordered_remove (char_ptr, vec, ix);
+	xfree (s);
+	if (ix == VEC_length (char_ptr, vec))
+	  VEC_safe_push (char_ptr, vec, xstrdup (TARGET_SYSROOT_PREFIX));
+	else
+	  xfree (VEC_replace (char_ptr, vec, ix,
+			      concat (TARGET_SYSROOT_PREFIX,
+				      VEC_index (char_ptr, vec, ix),
+				      NULL)));
+      }
+
+  return vec;
+}
+
 /* Open a file named STRING, searching path PATH (dir names sep by some char)
    using mode MODE in the calls to open.  You cannot use this function to
    create files (O_CREAT).
diff --git a/gdb/source.h b/gdb/source.h
index 9050357..fd58d8e 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -98,4 +98,7 @@ extern void clear_current_source_symtab_and_line (void);
 
 /* Add a source path substitution rule.  */
 extern void add_substitute_path_rule (char *, char *);
+
+extern VEC (char_ptr) *dirnames_to_char_ptr_vec_target_exc (const char *string);
+
 #endif

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 06/32] Validate symbol file using build-id
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (7 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 07/32] Code cleanup: Make solib_find_1 variable const Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-22  7:23   ` Eli Zaretskii
  2015-08-21 21:21 ` [PATCH v12 12/32] Code cleanup: Remove openp parameter mode Jan Kratochvil
                   ` (23 subsequent siblings)
  32 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Consumer part of the "build-id" attribute.

gdb/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Validate symbol file using build-id.
	* NEWS (Changes since GDB 7.10): Add 'set validate-build-id'
	and 'show validate-build-id'.  Add build-id attribute.
	* build-id.c: Include gdbcmd.h.
	(validate_build_id, show_validate_build_id, _initialize_build_id): New.
	* build-id.h (validate_build_id): New declaration.
	* solib-svr4.c: Include rsp-low.h.
	(svr4_copy_library_list): Duplicate field build_id.
	(library_list_start_library): Parse 'build-id' attribute.
	(svr4_library_attributes): Add 'build-id' attribute.
	* solib.c (free_so): Free build_id.
	* solist.h (struct so_list): New fields 'build_idsz' and 'build_id'.
---
 0 files changed

diff --git a/gdb/NEWS b/gdb/NEWS
index 2cedccd..fce33f3 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -35,6 +35,20 @@ show debug bfd-cache
   The "/m" option is now considered deprecated: its "source-centric"
   output hasn't proved useful in practice.
 
+* New options
+
+set validate-build-id (on|off)
+show validate-build-id
+  Inferior shared library and symbol file may contain unique build-id.
+  If both build-ids are present but they do not match then this setting
+  enables (off) or disables (on) loading of such symbol file.
+
+* New features in the GDB remote stub, GDBserver
+
+  ** library-list-svr4 contains also optional attribute 'build-id' for
+     each library.  GDB does not load library with build-id that
+     does not match such attribute.
+
 *** Changes in GDB 7.10
 
 * Support for process record-replay and reverse debugging on aarch64*-linux*
diff --git a/gdb/build-id.c b/gdb/build-id.c
index c89cd55..0b069fd 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -26,6 +26,21 @@
 #include "objfiles.h"
 #include "filenames.h"
 #include "gdbcore.h"
+#include "gdbcmd.h"
+
+/* Boolean for command 'set validate-build-id'.  */
+int validate_build_id = 1;
+
+/* Implement 'show validate-build-id'.  */
+
+static void
+show_validate_build_id (struct ui_file *file, int from_tty,
+			struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Validation a build-id matches to load a shared "
+			    "library is %s.\n"),
+		    value);
+}
 
 /* See build-id.h.  */
 
@@ -167,3 +182,22 @@ find_separate_debug_file_by_buildid (struct objfile *objfile)
     }
   return NULL;
 }
+
+extern initialize_file_ftype _initialize_build_id; /* -Wmissing-prototypes */
+
+void
+_initialize_build_id (void)
+{
+  add_setshow_boolean_cmd ("validate-build-id", class_support,
+			   &validate_build_id, _("\
+Set validation a build-id matches to load a shared library."), _("\
+SHow validation a build-id matches to load a shared library."), _("\
+Inferior shared library and symbol file may contain unique build-id.\n\
+If both build-ids are present but they do not match then this setting\n\
+enables (off) or disables (on) loading of such symbol file.\n\
+Loading non-matching symbol file may confuse debugging including breakage\n\
+of backtrace output."),
+			   NULL,
+			   show_validate_build_id,
+			   &setlist, &showlist);
+}
diff --git a/gdb/build-id.h b/gdb/build-id.h
index bea761b..63b9d8d 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -45,4 +45,6 @@ extern bfd *build_id_to_debug_bfd (size_t build_id_len,
 
 extern char *find_separate_debug_file_by_buildid (struct objfile *objfile);
 
+extern int validate_build_id;
+
 #endif /* BUILD_ID_H */
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 1fb07d5..070b95f 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -45,6 +45,7 @@
 #include "auxv.h"
 #include "gdb_bfd.h"
 #include "probe.h"
+#include "rsp-low.h"
 
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
@@ -1139,6 +1140,12 @@ svr4_copy_library_list (struct so_list *src)
       newobj->lm_info = xmalloc (sizeof (struct lm_info));
       memcpy (newobj->lm_info, src->lm_info, sizeof (struct lm_info));
 
+      if (newobj->build_id != NULL)
+	{
+	  newobj->build_id = xmalloc (src->build_idsz);
+	  memcpy (newobj->build_id, src->build_id, src->build_idsz);
+	}
+
       newobj->next = NULL;
       *link = newobj;
       link = &newobj->next;
@@ -1166,6 +1173,9 @@ library_list_start_library (struct gdb_xml_parser *parser,
   ULONGEST *lmp = xml_find_attribute (attributes, "lm")->value;
   ULONGEST *l_addrp = xml_find_attribute (attributes, "l_addr")->value;
   ULONGEST *l_ldp = xml_find_attribute (attributes, "l_ld")->value;
+  const struct gdb_xml_value *const att_build_id
+    = xml_find_attribute (attributes, "build-id");
+  const char *const hex_build_id = att_build_id ? att_build_id->value : NULL;
   struct so_list *new_elem;
 
   new_elem = XCNEW (struct so_list);
@@ -1177,6 +1187,37 @@ library_list_start_library (struct gdb_xml_parser *parser,
   strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1);
   new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
   strcpy (new_elem->so_original_name, new_elem->so_name);
+  if (hex_build_id != NULL)
+    {
+      const size_t hex_build_id_len = strlen (hex_build_id);
+
+      if (hex_build_id_len == 0)
+	warning (_("Shared library \"%s\" received empty build-id "
+	           "from gdbserver"), new_elem->so_original_name);
+      else if ((hex_build_id_len & 1U) != 0)
+	warning (_("Shared library \"%s\" received odd number "
+		   "of build-id \"%s\" hex characters from gdbserver"),
+		 new_elem->so_original_name, hex_build_id);
+      else
+	{
+	  const size_t build_idsz = hex_build_id_len / 2;
+
+	  new_elem->build_id = xmalloc (build_idsz);
+	  new_elem->build_idsz = hex2bin (hex_build_id, new_elem->build_id,
+					  build_idsz);
+	  if (new_elem->build_idsz != build_idsz)
+	    {
+	      warning (_("Shared library \"%s\" received invalid "
+			 "build-id \"%s\" hex character at encoded byte "
+			 "position %s (first as 0) from gdbserver"),
+		       new_elem->so_original_name, hex_build_id,
+		       pulongest (new_elem->build_idsz));
+	      xfree (new_elem->build_id);
+	      new_elem->build_id = NULL;
+	      new_elem->build_idsz = 0;
+	    }
+	}
+    }
 
   *list->tailp = new_elem;
   list->tailp = &new_elem->next;
@@ -1211,6 +1252,7 @@ static const struct gdb_xml_attribute svr4_library_attributes[] =
   { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
   { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { "build-id", GDB_XML_AF_OPTIONAL, NULL, NULL },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
diff --git a/gdb/solib.c b/gdb/solib.c
index d2ea901..cf78f6a 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -650,6 +650,7 @@ free_so (struct so_list *so)
   clear_so (so);
   ops->free_so (so);
 
+  xfree (so->build_id);
   xfree (so);
 }
 
diff --git a/gdb/solist.h b/gdb/solist.h
index 844c6f9..af9acc2 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -75,6 +75,19 @@ struct so_list
        There may not be just one (e.g. if two segments are relocated
        differently); but this is only used for "info sharedlibrary".  */
     CORE_ADDR addr_low, addr_high;
+
+    /* Build id decoded from .note.gnu.build-id without note header.  This is
+       actual BUILD_ID which comes either from the remote target via qXfer
+       packet or via reading target memory.  Note that if there's a
+       mismatch with the associated bfd then so->abfd will be cleared.
+       Reading target memory should be done by following execution view
+       of the binary (following program headers in the case of ELF).
+       Computing address from the linking view (following ELF section
+       headers) may give incorrect build-id memory address despite the
+       symbols still match.
+       Such an example is a prelinked vs. unprelinked i386 ELF file.  */
+    size_t build_idsz;
+    gdb_byte *build_id;
   };
 
 struct target_so_ops

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 10/32] Code cleanup: Add enum for openp_flags
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (4 preceding siblings ...)
  2015-08-21 21:20 ` [PATCH v12 05/32] gdbserver build-id attribute generator Jan Kratochvil
@ 2015-08-21 21:21 ` Jan Kratochvil
  2015-08-21 21:21 ` [PATCH v12 11/32] Code cleanup: Remove OPF_RETURN_REALPATH Jan Kratochvil
                   ` (26 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:21 UTC (permalink / raw)
  To: gdb-patches

Hi,

it is for many reasons better, in C++ it could be even type safe.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* cli/cli-cmds.c (find_and_open_script): Use enum openp_flags for
	search_flags.
	* defs.h (OPF_TRY_CWD_FIRST, OPF_SEARCH_IN_PATH, OPF_RETURN_REALPATH):
	Wrap them to a new ...
	(enum openp_flags): ... enum.
	(openp): Update prototype.
	* dwarf2read.c (try_open_dwop_file): Use enum openp_flags for flags.
	* source.c (openp): Update opts parameter type.  Move out OPF_*
	comments.
---
 0 files changed

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index bcd7802..a5a4c7c 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -500,7 +500,7 @@ find_and_open_script (const char *script_file, int search_path,
   char *file;
   int fd;
   struct cleanup *old_cleanups;
-  int search_flags = OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH;
+  enum openp_flags search_flags = OPF_TRY_CWD_FIRST | OPF_RETURN_REALPATH;
 
   file = tilde_expand (script_file);
   old_cleanups = make_cleanup (xfree, file);
diff --git a/gdb/defs.h b/gdb/defs.h
index f4951ab..3d248f6 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -321,11 +321,25 @@ extern const char *pc_prefix (CORE_ADDR);
 /* From source.c */
 
 /* See openp function definition for their description.  */
-#define OPF_TRY_CWD_FIRST     0x01
-#define OPF_SEARCH_IN_PATH    0x02
-#define OPF_RETURN_REALPATH   0x04
+enum openp_flags
+{
+  /* Try to open ./STRING before searching PATH (ie pretend the first
+     element of PATH is ".").  This also indicates that, unless
+     OPF_SEARCH_IN_PATH is also specified, a slash in STRING disables
+     searching of the path (this is so that "exec-file ./foo" or
+     "symbol-file ./foo" insures that you get that particular version of
+     foo or an error message).  */
+  OPF_TRY_CWD_FIRST   = (1 << 0),
+
+  /* Absolute names will also be searched in path (we usually want this
+     for source files but not for executables).  */
+  OPF_SEARCH_IN_PATH  = (1 << 1),
+
+  /* See openp, to be removed.  */
+  OPF_RETURN_REALPATH = (1 << 2),
+};
 
-extern int openp (const char *, int, const char *, int, char **);
+extern int openp (const char *, enum openp_flags, const char *, int, char **);
 
 extern int source_full_path_of (const char *, char **);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 0c61df7..23b60f9 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -10450,7 +10450,8 @@ static bfd *
 try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
 {
   bfd *sym_bfd;
-  int desc, flags;
+  int desc;
+  enum openp_flags flags;
   char *absolute_name;
   /* Blech.  OPF_TRY_CWD_FIRST also disables searching the path list if
      FILE_NAME contains a '/'.  So we can't use it.  Instead prepend "."
diff --git a/gdb/source.c b/gdb/source.c
index 4cd3046..888ed2b 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -743,17 +743,6 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
 
    OPTS specifies the function behaviour in specific cases.
 
-   If OPF_TRY_CWD_FIRST, try to open ./STRING before searching PATH.
-   (ie pretend the first element of PATH is ".").  This also indicates
-   that, unless OPF_SEARCH_IN_PATH is also specified, a slash in STRING
-   disables searching of the path (this is so that "exec-file ./foo" or
-   "symbol-file ./foo" insures that you get that particular version of
-   foo or an error message).
-
-   If OPTS has OPF_SEARCH_IN_PATH set, absolute names will also be
-   searched in path (we usually want this for source files but not for
-   executables).
-
    If FILENAME_OPENED is non-null, set it to a newly allocated string naming
    the actual file opened (this string will always start with a "/").  We
    have to take special pains to avoid doubling the "/" between the directory
@@ -771,7 +760,7 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
 /*  >>>> This should only allow files of certain types,
     >>>>  eg executable, non-directory.  */
 int
-openp (const char *path, int opts, const char *string,
+openp (const char *path, enum openp_flags opts, const char *string,
        int mode, char **filename_opened)
 {
   int fd;

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 17/32] Add file_location utility functions
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (16 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 18/32] Refactor openp() to return file_location Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 09/32] Change sysroot to ":target:" Jan Kratochvil
                   ` (14 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

build id verification faces a problem current codebase calls openp() and
similar functions which search many directories and after they find the file
they return its filename.  Caller then typically opens that file as BFD.

But to search the directories openp() needs to open each file it iterates to
verify their build-id.  Then it would close the file and caller would reopen it
again.  This is inefficient (+racy), so a new intermediate representation of
the found files is created (file_location).

Another possibility would be to depends on bfd cache as being done in
exec_file_attach.  But then a similar problem is needed for callers which want
only fd (and not bfd).  Besides that I find depending on pending
make_cleanup_bfd_unref() from openp() calls would be tricky.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* defs.h (enum openp_flags): Add OPF_IS_BFD.
	* gdb_bfd.c (fileio_errno_to_host): Make it public.
	* gdb_bfd.h (fileio_errno_to_host): Add prototype.
	* source.c: Include inferior.h and gdb/fileio.h.
	(file_location_enoent, file_location_free, file_location_cleanup)
	(file_location_is_valid, file_location_from_filename)
	(file_location_to_bfd, filename_to_bfd): New functions.
	* source.h (struct file_location): New definition.
	(file_location_enoent, file_location_free, file_location_is_valid)
	(file_location file_location_from_filename, file_location_to_bfd)
	(filename_to_bfd): New prototypes.
---
 0 files changed

diff --git a/gdb/defs.h b/gdb/defs.h
index 7795b4a..8ee8b33 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -338,6 +338,9 @@ enum openp_flags
      for source files but not for executables).  */
   OPF_SEARCH_IN_PATH  = (1 << 1),
 
+  /* Ask for bfd * to be returned in file_location.  */
+  OPF_IS_BFD          = (1 << 2),
+
   /* Open the file in read/write mode if WRITE_FILES says so.  */
   OPF_OPEN_RW_TMP     = (1 << 3),
 };
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 1224695..dc2d6c0 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -197,7 +197,7 @@ gdb_bfd_has_target_filename (struct bfd *abfd)
 
 /* Return the system error number corresponding to ERRNUM.  */
 
-static int
+int
 fileio_errno_to_host (int errnum)
 {
   switch (errnum)
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index dcc6755..99fabfd 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -172,4 +172,6 @@ int gdb_bfd_count_sections (bfd *abfd);
 
 int gdb_bfd_requires_relocations (bfd *abfd);
 
+int fileio_errno_to_host (int errnum);
+
 #endif /* GDB_BFD_H */
diff --git a/gdb/source.c b/gdb/source.c
index 4096d0d..d06cc84 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -27,6 +27,8 @@
 #include "frame.h"
 #include "value.h"
 #include "filestuff.h"
+#include "inferior.h"
+#include "gdb/fileio.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -737,6 +739,211 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
   return vec;
 }
 
+/* Initialize *FILE as failed one with error code ENOENT.  Such
+   file_location still should be processed by file_location_free.  */
+
+void
+file_location_enoent (struct file_location *file)
+{
+  memset (file, 0, sizeof (*file));
+  file->fd = -1;
+  file->file_errno = ENOENT;
+}
+
+/* Free resources of *FILE.  *FILE must be properly initialized, either
+   by a successful or unsuccessful locator.  *FILE remains unspecified
+   after this call.  */
+
+void
+file_location_free (struct file_location *file)
+{
+  if (file->fd != -1)
+    {
+      if (file->load_via_target)
+	{
+	  int target_errno;
+
+	  target_fileio_close (file->fd, &target_errno);
+	}
+      else
+	close (file->fd);
+    }
+  gdb_bfd_unref (file->abfd);
+  xfree (file->filename);
+}
+
+/* Call file_location_free suitable for make_cleanup.  */
+
+static void
+file_location_cleanup (void *file_voidp)
+{
+  file_location_free (file_voidp);
+}
+
+/* Return boolean 1 if *FILE contains a successful file representation.
+   Return 0 otherwise.  */
+
+int
+file_location_is_valid (const struct file_location *file)
+{
+  if (!file->file_errno && !file->bfderr)
+    return 1;
+  gdb_assert (file->abfd == NULL);
+  return 0;
+}
+
+/* Return new file_location from FILENAME and OPTS.  */
+
+struct file_location
+file_location_from_filename (const char *filename, enum openp_flags opts)
+{
+  struct file_location file;
+  struct cleanup *back_to;
+
+  memset (&file, 0, sizeof (file));
+  file.fd = -1;
+  back_to = make_cleanup (file_location_cleanup, &file);
+  file.filename = xstrdup (filename);
+
+  if (is_target_filename (filename))
+    {
+      filename += strlen (TARGET_SYSROOT_PREFIX);
+      if (!target_filesystem_is_local ())
+	{
+	  file.load_via_target = 1;
+
+	  /* gdb_bfd_fopen does not support "target:" filenames.  */
+	  if (write_files)
+	    warning (_("writing into executable files is "
+		       "not supported for %s sysroots"),
+		     TARGET_SYSROOT_PREFIX);
+	}
+    }
+
+  if (file.load_via_target)
+    {
+      int target_errno;
+
+      file.fd = target_fileio_open (current_inferior (),
+				    filename, FILEIO_O_RDONLY, 0,
+				    &target_errno);
+      if (file.fd == -1)
+	{
+	  file.file_errno = fileio_errno_to_host (target_errno);
+	  discard_cleanups (back_to);
+	  return file;
+	}
+    }
+  else
+    {
+      /* WRITE_FILES is ignored if !OPF_IS_BFD.  */
+
+      file.fd = gdb_open_cloexec (filename, O_RDONLY | O_BINARY, 0);
+      if (file.fd == -1)
+	{
+	  file.file_errno = errno;
+	  discard_cleanups (back_to);
+	  return file;
+	}
+    }
+
+  if ((opts & OPF_IS_BFD) == 0)
+    {
+      discard_cleanups (back_to);
+      return file;
+    }
+
+  if (file.load_via_target)
+    {
+      const int do_close = (opts & OPF_IS_BFD) != 0;
+
+      gdb_assert (strcmp (filename,
+			  file.filename + strlen (TARGET_SYSROOT_PREFIX)) == 0);
+      file.abfd = gdb_bfd_open_from_target (file.filename, gnutarget, file.fd,
+					    do_close);
+      if (do_close && file.abfd != NULL)
+	file.fd = -1;
+    }
+  else
+    {
+      if (write_files)
+	file.abfd = gdb_bfd_fopen (filename, gnutarget, FOPEN_RUB, file.fd);
+      else
+	file.abfd = gdb_bfd_open (filename, gnutarget, file.fd);
+      if ((opts & OPF_IS_BFD) != 0)
+	file.fd = -1;
+      else
+	{
+	  file.fd = dup (file.fd);
+	  if (file.fd == -1)
+	    {
+	      int save_errno = errno;
+
+	      do_cleanups (back_to);
+	      file_location_enoent (&file);
+	      file.file_errno = save_errno;
+	      return file;
+	    }
+	}
+    }
+
+  if (file.abfd == NULL)
+    {
+      file.bfderr = bfd_get_error ();
+      discard_cleanups (back_to);
+      return file;
+    }
+
+  discard_cleanups (back_to);
+  return file;
+}
+
+/* Return new BFD * from FILE.  If FILE represents a failed locator
+   result then bfd_set_error is called and NULL is returned.  FILE
+   content is always freed by this function.  The locator for FILE must
+   have been called with OPF_IS_BFD.  */
+
+bfd *
+file_location_to_bfd (struct file_location file)
+{
+  bfd *retval;
+
+  if (file.abfd == NULL)
+    {
+      const int file_errno = file.file_errno;
+      const bfd_error_type file_bfderr = file.bfderr;
+
+      gdb_assert (file_errno || file_bfderr);
+
+      file_location_free (&file);
+
+      if (file_bfderr == bfd_error_on_input)
+	bfd_set_error (bfd_error_malformed_archive);
+      else if (file_bfderr)
+	bfd_set_error (file_bfderr);
+      else
+	{
+	  bfd_set_error (bfd_error_system_call);
+	  errno = file_errno;
+	}
+      return NULL;
+    }
+  gdb_bfd_ref (file.abfd);
+  retval = file.abfd;
+  file_location_free (&file);
+  return retval;
+}
+
+/* Return new BFD * from FILENAME.  See file_location_from_filename and
+   file_location_to_bfd.  */
+
+bfd *
+filename_to_bfd (const char *filename)
+{
+  return file_location_to_bfd (file_location_from_filename (filename,
+							    OPF_IS_BFD));
+}
+
 /* Open a file named STRING, searching path PATH (dir names sep by some char).
    You cannot use this function to create files.
 
diff --git a/gdb/source.h b/gdb/source.h
index fd58d8e..f511959 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -101,4 +101,50 @@ extern void add_substitute_path_rule (char *, char *);
 
 extern VEC (char_ptr) *dirnames_to_char_ptr_vec_target_exc (const char *string);
 
+/* Unified file representation which can contain BFD *, filename and FD
+   in all or some of the forms.  */
+struct file_location
+{
+  /* This pointer can be NULL.  Use OPF_IS_BFD to get it filled in.  */
+  bfd *abfd;
+
+  /* This pointer is never NULL.  It names the actual file opened (this
+     string will always start with a "/").  We have to take special
+     pains to avoid doubling the "/" between the directory and the file,
+     sigh!  Emacs gets confuzzed by this when we print the source file
+     name!!!  */
+  char *filename;
+
+  /* A flag whether FD represents remote target fileio descriptor or
+     local operating system file descriptor.  */
+  unsigned char load_via_target;
+
+  /* File descriptor (see LOAD_VIA_TARGET) or -1.  Do not use OPF_IS_BFD
+     to get it filled in.  */
+  int fd;
+
+  /* ERRNO value if a call to fill-in this structure failed.  See also
+     BFDERR.  */
+  int file_errno;
+
+  /* BFD error value if a call to fill-in this structure failed or
+     bfd_error_no_error.  If either FILE_ERRNO or BFDERR are non-zero
+     then this file_location failed and ABFD must be NULL.  There is no
+     guarantee for failed file_location about FD value.  */
+  bfd_error_type bfderr;
+};
+
+extern void file_location_enoent (struct file_location *file);
+
+extern void file_location_free (struct file_location *file);
+
+extern int file_location_is_valid (const struct file_location *file);
+
+extern struct file_location file_location_from_filename (const char *filename,
+							 enum openp_flags opts);
+
+extern bfd *file_location_to_bfd (struct file_location file);
+
+extern bfd *filename_to_bfd (const char *filename);
+
 #endif

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 18/32] Refactor openp() to return file_location
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (15 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 19/32] solib_find: Make it use file_location Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-25 19:07   ` [PATCH v13 " Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 17/32] Add file_location utility functions Jan Kratochvil
                   ` (15 subsequent siblings)
  32 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

openp() remains as a backward compatibility wrapper around renamed
openp->openp_file().


Jan


gdb/ChangeLog
2015-08-19  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* defs.h (enum openp_flags): Remove OPF_OPEN_RW_TMP, add
	OPF_BFD_CANONICAL.
	(openp_bfd, openp_file): Add prototypes.
	* exec.c (exec_file_attach): Replace openp by openp_bfd calls.
	* source.c (file_location_from_filename): Support OPF_BFD_CANONICAL.
	(openp, openp_bfd): New functions.
	(openp): Rename to ...
	(openp_file): ... here, return file_location, remove filename_opened
	parameter.
---
 0 files changed

diff --git a/gdb/defs.h b/gdb/defs.h
index 8ee8b33..ac735c2 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -341,12 +341,20 @@ enum openp_flags
   /* Ask for bfd * to be returned in file_location.  */
   OPF_IS_BFD          = (1 << 2),
 
-  /* Open the file in read/write mode if WRITE_FILES says so.  */
-  OPF_OPEN_RW_TMP     = (1 << 3),
+  /* bfd_get_filename can be incorrect then, use only if you keep your
+     original filename separate from resulting bfd.
+     Returned file_location.filename is not canonicalized.  */
+  OPF_BFD_CANONICAL   = (1 << 3),
 };
 
 extern int openp (const char *, enum openp_flags, const char *, char **);
 
+extern bfd *openp_bfd (const char *path, enum openp_flags opts,
+		       const char *string);
+
+extern struct file_location openp_file (const char *path, enum openp_flags opts,
+					const char *string);
+
 extern int source_full_path_of (const char *, char **);
 
 extern void mod_path (char *, char **);
diff --git a/gdb/exec.c b/gdb/exec.c
index e87d154..6dd2aa6 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -216,81 +216,32 @@ exec_file_attach (const char *filename, int from_tty)
     }
   else
     {
-      int load_via_target = 0;
-      char *scratch_pathname, *canonical_pathname;
-      int scratch_chan;
       struct target_section *sections = NULL, *sections_end = NULL;
       char **matching;
 
-      if (is_target_filename (filename))
-	{
-	  if (target_filesystem_is_local ())
-	    filename += strlen (TARGET_SYSROOT_PREFIX);
-	  else
-	    load_via_target = 1;
-	}
-
-      if (load_via_target)
+      exec_bfd = openp_bfd (getenv ("PATH"),
+			    OPF_TRY_CWD_FIRST | OPF_BFD_CANONICAL, filename);
+#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
+      if (exec_bfd == NULL)
 	{
-	  /* gdb_bfd_fopen does not support "target:" filenames.  */
-	  if (write_files)
-	    warning (_("writing into executable files is "
-		       "not supported for %s sysroots"),
-		     TARGET_SYSROOT_PREFIX);
+	  char *exename = alloca (strlen (filename) + 5);
 
-	  scratch_pathname = xstrdup (filename);
-	  make_cleanup (xfree, scratch_pathname);
-
-	  scratch_chan = -1;
-
-	  canonical_pathname = scratch_pathname;
+	  strcat (strcpy (exename, filename), ".exe");
+	  exec_bfd = openp_bfd (getenv ("PATH"),
+				OPF_TRY_CWD_FIRST | OPF_BFD_CANONICAL, exename);
 	}
-      else
-	{
-	  scratch_chan = openp (getenv ("PATH"),
-				OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
-				filename, &scratch_pathname);
-#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
-	  if (scratch_chan < 0)
-	    {
-	      char *exename = alloca (strlen (filename) + 5);
-
-	      strcat (strcpy (exename, filename), ".exe");
-	      scratch_chan = openp (getenv ("PATH"),
-	                            OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
-				    exename, &scratch_pathname);
-	    }
 #endif
-	  if (scratch_chan < 0)
-	    perror_with_name (filename);
-
-	  make_cleanup (xfree, scratch_pathname);
-
-	  /* gdb_bfd_open (and its variants) prefers canonicalized
-	     pathname for better BFD caching.  */
-	  canonical_pathname = gdb_realpath (scratch_pathname);
-	  make_cleanup (xfree, canonical_pathname);
-	}
-
-      if (write_files && !load_via_target)
-	exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget,
-				  FOPEN_RUB, scratch_chan);
-      else
-	exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
-
-      if (!exec_bfd)
-	{
-	  error (_("\"%s\": could not open as an executable file: %s."),
-		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
-	}
+      if (exec_bfd == NULL)
+	error (_("\"%s\": could not open as an executable file: %s."),
+	       filename, bfd_errmsg (bfd_get_error ()));
 
       /* gdb_realpath_keepfile resolves symlinks on the local
 	 filesystem and so cannot be used for "target:" files.  */
       gdb_assert (exec_filename == NULL);
-      if (load_via_target)
+      if (is_target_filename (filename))
 	exec_filename = xstrdup (bfd_get_filename (exec_bfd));
       else
-	exec_filename = gdb_realpath_keepfile (scratch_pathname);
+	exec_filename = gdb_realpath_keepfile (filename);
 
       if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching))
 	{
@@ -298,7 +249,7 @@ exec_file_attach (const char *filename, int from_tty)
 	     it.  */
 	  exec_close ();
 	  error (_("\"%s\": not in executable format: %s"),
-		 scratch_pathname,
+		 filename,
 		 gdb_bfd_errmsg (bfd_get_error (), matching));
 	}
 
@@ -308,7 +259,7 @@ exec_file_attach (const char *filename, int from_tty)
 	     it.  */
 	  exec_close ();
 	  error (_("\"%s\": can't find the file sections: %s"),
-		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
+		 filename, bfd_errmsg (bfd_get_error ()));
 	}
 
       exec_bfd_mtime = bfd_get_mtime (exec_bfd);
diff --git a/gdb/source.c b/gdb/source.c
index d06cc84..029c3b5 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -868,8 +868,21 @@ file_location_from_filename (const char *filename, enum openp_flags opts)
     {
       if (write_files)
 	file.abfd = gdb_bfd_fopen (filename, gnutarget, FOPEN_RUB, file.fd);
-      else
+      else if ((opts & OPF_BFD_CANONICAL) == 0)
 	file.abfd = gdb_bfd_open (filename, gnutarget, file.fd);
+      else
+	{
+	  char *canonical;
+
+	  /* gdb_bfd_open (and its variants) prefers canonicalized
+	     pathname for better BFD caching.  */
+	  struct cleanup *canonical_cleanup;
+
+	  canonical = gdb_realpath (filename);
+	  canonical_cleanup = make_cleanup (xfree, canonical);
+	  file.abfd = gdb_bfd_open (canonical, gnutarget, file.fd);
+	  do_cleanups (canonical_cleanup);
+	}
       if ((opts & OPF_IS_BFD) != 0)
 	file.fd = -1;
       else
@@ -944,35 +957,79 @@ filename_to_bfd (const char *filename)
 							    OPF_IS_BFD));
 }
 
-/* Open a file named STRING, searching path PATH (dir names sep by some char).
-   You cannot use this function to create files.
-
-   OPTS specifies the function behaviour in specific cases.
+/* Wrapper of openp_file returning filename string.
 
-   FILENAME_OPENED must be non-null.  Set it to a newly allocated string naming
-   the actual file opened (this string will always start with a "/").  We
-   have to take special pains to avoid doubling the "/" between the directory
-   and the file, sigh!  Emacs gets confuzzed by this when we print the
-   source file name!!! 
+   FILENAME_OPENED must be non-null.  It is set to
+   file_location.filename returned from openp_file.
 
    If a file is found, return the descriptor.
    Otherwise, return -1, with errno set for the last name we tried to open.  */
 
-/*  >>>> This should only allow files of certain types,
-    >>>>  eg executable, non-directory.  */
 int
 openp (const char *path, enum openp_flags opts, const char *string,
        char **filename_opened)
 {
+  struct file_location file;
+  int retval;
+
+  gdb_assert ((opts & OPF_IS_BFD) == 0);
+
+  file = openp_file (path, opts, string);
+  gdb_assert (file.abfd == NULL);
+  if (file.fd == -1)
+    {
+      int save_errno = file.file_errno;
+
+      gdb_assert (file.filename == NULL);
+      file_location_free (&file);
+      *filename_opened = NULL;
+      errno = save_errno;
+      return -1;
+    }
+  gdb_assert (file.filename != NULL);
+  *filename_opened = xstrdup (file.filename);
+  retval = file.fd;
+  file.fd = -1;
+  file_location_free (&file);
+  return retval;
+}
+
+/* Wrapper of openp_file returning bfd *.  See file_location_to_bfd how
+   the function behaves in the case of failure.  */
+
+bfd *
+openp_bfd (const char *path, enum openp_flags opts, const char *string)
+{
+  gdb_assert ((opts & OPF_IS_BFD) == 0);
+
+  return file_location_to_bfd (openp_file (path, opts | OPF_IS_BFD, string));
+}
+
+/* Open a file named STRING, searching path PATH (dir names sep by some char).
+   You cannot use this function to create files.
+
+   OPTS specifies the function behaviour in specific cases.
+
+   Call file_location_is_valid on returned file_location to check
+   whether this function has succeeded.  */
+
+/*  >>>> This should only allow files of certain types,
+    >>>>  eg executable, non-directory.  */
+
+struct file_location
+openp_file (const char *path, enum openp_flags opts, const char *string)
+{
   int fd;
   char *filename;
   int alloclen;
   VEC (char_ptr) *dir_vec;
   struct cleanup *back_to;
-  int ix, mode;
+  int ix;
   char *dir;
+  struct file_location file;
 
   gdb_assert (string != NULL);
+  gdb_assert ((opts & (OPF_IS_BFD | OPF_BFD_CANONICAL)) != OPF_BFD_CANONICAL);
 
   /* A file with an empty name cannot possibly exist.  Report a failure
      without further checking.
@@ -983,16 +1040,13 @@ openp (const char *path, enum openp_flags opts, const char *string,
      when the debugger is started with an empty argument.  */
   if (string[0] == '\0')
     {
-      errno = ENOENT;
-      return -1;
+      file_location_enoent (&file);
+      return file;
     }
 
   if (!path)
     path = ".";
 
-  mode = (O_BINARY | (((opts & OPF_OPEN_RW_TMP) && write_files)
-		      ? O_RDWR : O_RDONLY));
-
   if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string))
     {
       int i;
@@ -1001,20 +1055,19 @@ openp (const char *path, enum openp_flags opts, const char *string,
 	{
 	  filename = alloca (strlen (string) + 1);
 	  strcpy (filename, string);
-	  fd = gdb_open_cloexec (filename, mode, 0);
-	  if (fd >= 0)
-	    goto done;
-	}
-      else
-	{
-	  filename = NULL;
-	  fd = -1;
+	  file = file_location_from_filename (filename, opts);
+	  if (file_location_is_valid (&file))
+	    return file;
+	  file_location_free (&file);
 	}
 
       if (!(opts & OPF_SEARCH_IN_PATH))
 	for (i = 0; string[i]; i++)
 	  if (IS_DIR_SEPARATOR (string[i]))
-	    goto done;
+	    {
+	      file_location_enoent (&file);
+	      return file;
+	    }
     }
 
   /* For dos paths, d:/foo -> /foo, and d:foo -> foo.  */
@@ -1033,7 +1086,7 @@ openp (const char *path, enum openp_flags opts, const char *string,
   filename = alloca (alloclen);
   fd = -1;
 
-  dir_vec = dirnames_to_char_ptr_vec (path);
+  dir_vec = dirnames_to_char_ptr_vec_target_exc (path);
   back_to = make_cleanup_free_char_ptr_vec (dir_vec);
 
   for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix)
@@ -1097,23 +1150,22 @@ openp (const char *path, enum openp_flags opts, const char *string,
       strcat (filename + len, SLASH_STRING);
       strcat (filename, string);
 
-      if (is_regular_file (filename))
+      if (is_target_filename (filename) || is_regular_file (filename))
 	{
-	  fd = gdb_open_cloexec (filename, mode, 0);
-	  if (fd >= 0)
-	    break;
+	  file = file_location_from_filename (filename, opts);
+	  if (file_location_is_valid (&file))
+	    {
+	      do_cleanups (back_to);
+	      return file;
+	    }
+	  file_location_free (&file);
 	}
     }
 
   do_cleanups (back_to);
 
-done:
-  if (fd < 0)
-    *filename_opened = NULL;
-  else
-    *filename_opened = xstrdup (filename);
-
-  return fd;
+  file_location_enoent (&file);
+  return file;
 }
 
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 16/32] gdb_bfd_open_from_target: Optionally do not close fd
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (13 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 15/32] gdb_bfd_open_from_target: Support real fd Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 19/32] solib_find: Make it use file_location Jan Kratochvil
                   ` (17 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

gdb_bfd_open_from_target currently always embedded passed fd into returned BFD
and closed that fd after closing that BFD.  As one cannot do dup() for target
fileio FDs one could not use FD after BFD using it has been closed.

Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb_bfd.c (gdb_bfd_iovec_fileio_close_nop): New function.
	(gdb_bfd_open_from_target): Add parameter do_close.  Optionally pass
	gdb_bfd_iovec_fileio_close_nop.
	(gdb_bfd_open): Update caller.
	* gdb_bfd.h (gdb_bfd_open_from_target): Update prototype.
---
 0 files changed

diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 51395f9..1224695 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -345,6 +345,18 @@ gdb_bfd_iovec_fileio_close (struct bfd *abfd, void *stream)
   return 0;
 }
 
+/* Helper for gdb_bfd_open_from_target when caller did not wish to close
+   ABFD's FD.  */
+
+static int
+gdb_bfd_iovec_fileio_close_nop (struct bfd *abfd, void *stream)
+{
+  xfree (stream);
+
+  /* Zero means success.  */
+  return 0;
+}
+
 /* Wrapper for target_fileio_fstat suitable for passing as the
    STAT_FUNC argument to gdb_bfd_openr_iovec.  */
 
@@ -371,7 +383,8 @@ gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
    gdb_bfd_openr_iovec.  */
 
 struct bfd *
-gdb_bfd_open_from_target (const char *name, const char *target, int fd)
+gdb_bfd_open_from_target (const char *name, const char *target, int fd,
+			  int do_close)
 {
   gdb_assert (is_target_filename (name));
   gdb_assert (!target_filesystem_is_local ());
@@ -382,7 +395,8 @@ gdb_bfd_open_from_target (const char *name, const char *target, int fd)
 			      (fd == -1 ? (void *) current_inferior ()
 					: (void *) &fd),
 			      gdb_bfd_iovec_fileio_pread,
-			      gdb_bfd_iovec_fileio_close,
+			      (do_close ? gdb_bfd_iovec_fileio_close
+					: gdb_bfd_iovec_fileio_close_nop),
 			      gdb_bfd_iovec_fileio_fstat);
 }
 
@@ -400,7 +414,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
   if (is_target_filename (name))
     {
       if (!target_filesystem_is_local ())
-	return gdb_bfd_open_from_target (name, target, fd);
+	return gdb_bfd_open_from_target (name, target, fd, 1 /* do_close */);
 
       name += strlen (TARGET_SYSROOT_PREFIX);
     }
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index 0e38d62..dcc6755 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -54,7 +54,7 @@ int gdb_bfd_has_target_filename (struct bfd *abfd);
 struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);
 
 struct bfd *gdb_bfd_open_from_target (const char *name, const char *target,
-				      int fd);
+				      int fd, int do_close);
 
 /* Increment the reference count of ABFD.  It is fine for ABFD to be
    NULL; in this case the function does nothing.  */

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 13/32] Code cleanup: openp parameter filename_opened is never NULL
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (18 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 09/32] Change sysroot to ":target:" Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 21/32] build_id_to_debug_bfd: Make it also non-.debug capable Jan Kratochvil
                   ` (12 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

this parameter is never passed as NULL in the codebase so the check can be
removed.

Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* source.c (openp): Update function comment for filename_opened.
	Remove NULL check for filename_opened.
---
 0 files changed

diff --git a/gdb/source.c b/gdb/source.c
index 8dfe580..4096d0d 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -742,7 +742,7 @@ dirnames_to_char_ptr_vec_target_exc (const char *string)
 
    OPTS specifies the function behaviour in specific cases.
 
-   If FILENAME_OPENED is non-null, set it to a newly allocated string naming
+   FILENAME_OPENED must be non-null.  Set it to a newly allocated string naming
    the actual file opened (this string will always start with a "/").  We
    have to take special pains to avoid doubling the "/" between the directory
    and the file, sigh!  Emacs gets confuzzed by this when we print the
@@ -901,13 +901,10 @@ openp (const char *path, enum openp_flags opts, const char *string,
   do_cleanups (back_to);
 
 done:
-  if (filename_opened)
-    {
-      if (fd < 0)
-	*filename_opened = NULL;
-      else
-	*filename_opened = xstrdup (filename);
-    }
+  if (fd < 0)
+    *filename_opened = NULL;
+  else
+    *filename_opened = xstrdup (filename);
 
   return fd;
 }

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 20/32] symfile_bfd_open: Make it use openp_bfd()
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (10 preceding siblings ...)
  2015-08-21 21:21 ` [PATCH v12 08/32] Permit multiple sysroot directories Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 14/32] Provide new gdb_bfd_open_from_target Jan Kratochvil
                   ` (20 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

another function gets converted to the new API.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* symfile.c (symfile_bfd_open): Use openp_bfd instead of openp and
	gdb_bfd_open.
---
 0 files changed

diff --git a/gdb/symfile.c b/gdb/symfile.c
index c0eb4ce..1e34c5f 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1721,41 +1721,33 @@ bfd *
 symfile_bfd_open (const char *name)
 {
   bfd *sym_bfd;
-  int desc = -1;
   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
 
-  if (!is_target_filename (name))
+  if (is_target_filename (name))
+    sym_bfd = filename_to_bfd (name);
+  else
     {
-      char *expanded_name, *absolute_name;
+      char *expanded_name;
 
       expanded_name = tilde_expand (name); /* Returns 1st new malloc'd copy.  */
+      make_cleanup (xfree, expanded_name);
+      name = expanded_name;
 
       /* Look down path for it, allocate 2nd new malloc'd copy.  */
-      desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-		    expanded_name, &absolute_name);
+      sym_bfd = openp_bfd (getenv ("PATH"),
+			   OPF_TRY_CWD_FIRST | OPF_BFD_CANONICAL,
+			   expanded_name);
 #if defined(__GO32__) || defined(_WIN32) || defined (__CYGWIN__)
-      if (desc < 0)
+      if (sym_bfd == NULL)
 	{
 	  char *exename = alloca (strlen (expanded_name) + 5);
 
 	  strcat (strcpy (exename, expanded_name), ".exe");
-	  desc = openp (getenv ("PATH"), OPF_TRY_CWD_FIRST,
-			exename, &absolute_name);
+	  sym_bfd = openp_bfd (getenv ("PATH"), OPF_TRY_CWD_FIRST, exename);
 	}
 #endif
-      if (desc < 0)
-	{
-	  make_cleanup (xfree, expanded_name);
-	  perror_with_name (expanded_name);
-	}
-
-      xfree (expanded_name);
-      absolute_name = gdb_realpath_and_xfree (absolute_name);
-      make_cleanup (xfree, absolute_name);
-      name = absolute_name;
     }
 
-  sym_bfd = gdb_bfd_open (name, gnutarget, desc);
   if (!sym_bfd)
     error (_("`%s': can't open to read symbols: %s."), name,
 	   bfd_errmsg (bfd_get_error ()));
@@ -1766,7 +1758,7 @@ symfile_bfd_open (const char *name)
   if (!bfd_check_format (sym_bfd, bfd_object))
     {
       make_cleanup_bfd_unref (sym_bfd);
-      error (_("`%s': can't read symbols: %s."), name,
+      error (_("`%s': can't read symbols: %s."), bfd_get_filename (sym_bfd),
 	     bfd_errmsg (bfd_get_error ()));
     }
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 15/32] gdb_bfd_open_from_target: Support real fd
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (12 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 14/32] Provide new gdb_bfd_open_from_target Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 16/32] gdb_bfd_open_from_target: Optionally do not close fd Jan Kratochvil
                   ` (18 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

gdb_bfd_open_from_target is extended so that it can be now passed also some
non-(-1) fd.  non-(-1) fd was not supported for remote files in mainline.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb_bfd.c (gdb_bfd_iovec_fileio_open_fd): New function.
	(gdb_bfd_open_from_target): Conditionally use it.
---
 0 files changed

diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 10031f8..51395f9 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -278,6 +278,19 @@ gdb_bfd_iovec_fileio_open (struct bfd *abfd, void *inferior)
   return stream;
 }
 
+/* Helper for gdb_bfd_open_from_target when file descriptor is passed as
+   user data.  */
+
+static void *
+gdb_bfd_iovec_fileio_open_fd (struct bfd *abfd, void *fdp_voidp)
+{
+  int *stream, *fdp = fdp_voidp;
+
+  stream = XCNEW (int);
+  *stream = *fdp;
+  return stream;
+}
+
 /* Wrapper for target_fileio_pread suitable for passing as the
    PREAD_FUNC argument to gdb_bfd_openr_iovec.  */
 
@@ -362,11 +375,12 @@ gdb_bfd_open_from_target (const char *name, const char *target, int fd)
 {
   gdb_assert (is_target_filename (name));
   gdb_assert (!target_filesystem_is_local ());
-  gdb_assert (fd == -1);
 
   return gdb_bfd_openr_iovec (name, target,
-			      gdb_bfd_iovec_fileio_open,
-			      current_inferior (),
+			      (fd == -1 ? gdb_bfd_iovec_fileio_open
+					: gdb_bfd_iovec_fileio_open_fd),
+			      (fd == -1 ? (void *) current_inferior ()
+					: (void *) &fd),
 			      gdb_bfd_iovec_fileio_pread,
 			      gdb_bfd_iovec_fileio_close,
 			      gdb_bfd_iovec_fileio_fstat);

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 19/32] solib_find: Make it use file_location
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (14 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 16/32] gdb_bfd_open_from_target: Optionally do not close fd Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 18/32] Refactor openp() to return file_location Jan Kratochvil
                   ` (16 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

refactor the solib*() code to use file_location functions.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* nto-tdep.c: Include source.h.
	(nto_find_and_open_solib): Return file_location, remove parameter
	temp_pathname.  Change openp to openp_file.
	* nto-tdep.h (nto_find_and_open_solib): Update prototype.
	* solib.c (solib_find_2): Rename to ...
	(solib_find_3): ... here, return file_location, change parameter fd to
	opts.  Change gdb_open_cloexec to file_location_from_filename and openp
	to openp_file calls.
	(solib_find_1): Rename to ...
	(solib_find_2): ... here, return file_location, change parameter fd to
	opts.
	(solib_find_1): New function.
	(solib_find): Rename to ...
	(solib_find_file) ... here, return file_location, change parameter fd
	to opts.
	(solib_find): New function.
	* solist.h (find_and_open_solib): Return file_location, remove
	parameter temp_pathname.
---
 0 files changed

diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
index 7c8b4ce..9f9e3bc 100644
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -31,6 +31,7 @@
 #include "solib-svr4.h"
 #include "gdbcore.h"
 #include "objfiles.h"
+#include "source.h"
 
 #ifdef __CYGWIN__
 #include <sys/cygwin.h>
@@ -81,14 +82,15 @@ nto_map_arch_to_cputype (const char *arch)
   return CPUTYPE_UNKNOWN;
 }
 
-int
-nto_find_and_open_solib (char *solib, char **temp_pathname)
+struct file_location
+nto_find_and_open_solib (char *solib)
 {
   char *buf, *arch_path, *nto_root;
   const char *endian;
   const char *base;
   const char *arch;
-  int arch_len, len, ret;
+  int arch_len, len;
+  struct file_location file;
 #define PATH_FMT \
   "%s/lib:%s/usr/lib:%s/usr/photon/lib:%s/usr/photon/dll:%s/lib/dll"
 
@@ -127,22 +129,13 @@ nto_find_and_open_solib (char *solib, char **temp_pathname)
 	     arch_path);
 
   base = lbasename (solib);
-  ret = openp (buf, OPF_TRY_CWD_FIRST, base, temp_pathname);
-  if (ret < 0 && base != solib)
-    {
-      xsnprintf (arch_path, arch_len, "/%s", solib);
-      ret = open (arch_path, O_RDONLY | O_BINARY);
-      if (temp_pathname)
-	{
-	  if (ret >= 0)
-	    *temp_pathname = xstrdup (arch_path);
-	  else
-	    *temp_pathname = NULL;
-	}
-    }
-  if (ret >= 0)
-    *temp_pathname = gdb_realpath_and_xfree (*temp_pathname);
-  return ret;
+  file = openp_file (buf, OPF_TRY_CWD_FIRST | OPF_IS_BFD, base);
+  if (file_location_is_valid (&file) || base == solib)
+    return file;
+  file_location_free (&file);
+
+  xsnprintf (arch_path, arch_len, "/%s", solib);
+  return file_location_from_filename (arch_path, OPF_IS_BFD);
 }
 
 void
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
index 1f8045a..5828765 100644
--- a/gdb/nto-tdep.h
+++ b/gdb/nto-tdep.h
@@ -154,7 +154,7 @@ void nto_relocate_section_addresses (struct so_list *,
 
 int nto_map_arch_to_cputype (const char *);
 
-int nto_find_and_open_solib (char *, char **);
+struct file_location nto_find_and_open_solib (char *);
 
 enum gdb_osabi nto_elf_osabi_sniffer (bfd *abfd);
 
diff --git a/gdb/solib.c b/gdb/solib.c
index b16f47b..4fe4cb3 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -113,11 +113,7 @@ show_solib_search_path (struct ui_file *file, int from_tty,
 #  define DOS_BASED_FILE_SYSTEM 0
 #endif
 
-/* Return the full pathname of a binary file (the main executable
-   or a shared library file), or NULL if not found.  The returned
-   pathname is malloc'ed and must be freed by the caller.  If FD
-   is non-NULL, *FD is set to either -1 or an open file handle for
-   the binary file.
+/* Find a binary file (the main executable or a shared library file).
 
    Parameter SYSROOT is used as a prefix directory
    to search for binary files if they have an absolute path.
@@ -150,15 +146,16 @@ show_solib_search_path (struct ui_file *file, int from_tty,
    * machines since a sysroot will almost always be set.
 */
 
-static char *
-solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
+static struct file_location
+solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
+	      const char *sysroot)
 {
   const struct target_so_ops *ops = solib_ops (target_gdbarch ());
-  int found_file = -1;
-  char *temp_pathname = NULL;
+  char *temp_pathname;
   const char *fskind = effective_target_file_system_kind ();
   struct cleanup *old_chain = make_cleanup (null_cleanup, NULL);
-  int prefix_len, orig_prefix_len, temp_pathname_is_realpath;
+  int prefix_len, orig_prefix_len;
+  struct file_location file;
 
   /* If the absolute prefix starts with "target:" but the filesystem
      accessed by the target_fileio_* methods is the local filesystem
@@ -249,27 +246,23 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
 			      in_pathname, (char *) NULL);
     }
 
-  /* Handle files to be accessed via the target.  */
-  if (is_target_filename (temp_pathname))
+  /* Now see if we can open it.  */
+  file = file_location_from_filename (temp_pathname, opts);
+  if (file_location_is_valid (&file))
     {
-      if (fd != NULL)
-	*fd = -1;
       do_cleanups (old_chain);
-      return temp_pathname;
+      return file;
     }
+  file_location_free (&file);
 
-  /* Now see if we can open it.  */
-  found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
-  if (found_file < 0)
-    xfree (temp_pathname);
+  xfree (temp_pathname);
 
   /* If the search in gdb_sysroot failed, and the path name has a
      drive spec (e.g, c:/foo), try stripping ':' from the drive spec,
      and retrying in the sysroot:
        c:/foo/bar.dll ==> /sysroot/c/foo/bar.dll.  */
 
-  if (found_file < 0
-      && sysroot != NULL
+  if (sysroot != NULL
       && HAS_TARGET_DRIVE_SPEC (fskind, in_pathname))
     {
       int need_dir_separator = !IS_DIR_SEPARATOR (in_pathname[2]);
@@ -282,47 +275,46 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
 			      in_pathname + 2, (char *) NULL);
       xfree (drive);
 
-      found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
-      if (found_file < 0)
+      file = file_location_from_filename (temp_pathname, opts);
+      if (file_location_is_valid (&file))
 	{
-	  xfree (temp_pathname);
+	  do_cleanups (old_chain);
+	  return file;
+	}
+      file_location_free (&file);
+
+      xfree (temp_pathname);
 
-	  /* If the search in gdb_sysroot still failed, try fully
-	     stripping the drive spec, and trying once more in the
-	     sysroot before giving up.
+      /* If the search in gdb_sysroot still failed, try fully
+	 stripping the drive spec, and trying once more in the
+	 sysroot before giving up.
 
-	     c:/foo/bar.dll ==> /sysroot/foo/bar.dll.  */
+	 c:/foo/bar.dll ==> /sysroot/foo/bar.dll.  */
 
-	  temp_pathname = concat (sysroot,
-				  need_dir_separator ? SLASH_STRING : "",
-				  in_pathname + 2, (char *) NULL);
+      temp_pathname = concat (sysroot,
+			      need_dir_separator ? SLASH_STRING : "",
+			      in_pathname + 2, (char *) NULL);
 
-	  found_file = gdb_open_cloexec (temp_pathname, O_RDONLY | O_BINARY, 0);
-	  if (found_file < 0)
-	    xfree (temp_pathname);
+      file = file_location_from_filename (temp_pathname, opts);
+      if (file_location_is_valid (&file))
+	{
+	  do_cleanups (old_chain);
+	  return file;
 	}
+      file_location_free (&file);
+
+      xfree (temp_pathname);
     }
 
   do_cleanups (old_chain);
 
-  /* We try to find the library in various ways.  After each attempt,
-     either found_file >= 0 and temp_pathname is a malloc'd string, or
-     found_file < 0 and temp_pathname does not point to storage that
-     needs to be freed.  */
-
-  if (found_file < 0)
-    {
-      temp_pathname = NULL;
-      temp_pathname_is_realpath = 1;
-    }
-  else
-    temp_pathname_is_realpath = 0;
+  /* We try to find the library in various ways.  */
 
   /* If the search in gdb_sysroot failed, and the path name is
      absolute at this point, make it relative.  (openp will try and open the
      file according to its absolute path otherwise, which is not what we want.)
      Affects subsequent searches for this solib.  */
-  if (found_file < 0 && IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
+  if (IS_TARGET_ABSOLUTE_PATH (fskind, in_pathname))
     {
       /* First, get rid of any drive letters etc.  */
       while (!IS_TARGET_DIR_SEPARATOR (fskind, *in_pathname))
@@ -335,59 +327,87 @@ solib_find_2 (char *in_pathname, int *fd, int is_solib, const char *sysroot)
 
   /* If not found, and we're looking for a solib, search the
      solib_search_path (if any).  */
-  if (is_solib && found_file < 0 && solib_search_path != NULL)
-    found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-			in_pathname, &temp_pathname);
+  if (is_solib && solib_search_path != NULL)
+    {
+      file = openp_file (solib_search_path, OPF_TRY_CWD_FIRST | opts,
+			 in_pathname);
+      if (file_location_is_valid (&file))
+	{
+	  file.filename = gdb_realpath_and_xfree (file.filename);
+	  return file;
+	}
+      file_location_free (&file);
+    }
 
   /* If not found, and we're looking for a solib, next search the
      solib_search_path (if any) for the basename only (ignoring the
      path).  This is to allow reading solibs from a path that differs
      from the opened path.  */
-  if (is_solib && found_file < 0 && solib_search_path != NULL)
-    found_file = openp (solib_search_path, OPF_TRY_CWD_FIRST,
-			target_lbasename (fskind, in_pathname), &temp_pathname);
+  if (is_solib && solib_search_path != NULL)
+    {
+      file = openp_file (solib_search_path, OPF_TRY_CWD_FIRST | opts,
+			 target_lbasename (fskind, in_pathname));
+      if (file_location_is_valid (&file))
+	{
+	  file.filename = gdb_realpath_and_xfree (file.filename);
+	  return file;
+	}
+      file_location_free (&file);
+    }
 
   /* If not found, and we're looking for a solib, try to use target
      supplied solib search method.  */
-  if (is_solib && found_file < 0 && ops->find_and_open_solib)
-    found_file = ops->find_and_open_solib (in_pathname, &temp_pathname);
+  if (is_solib && ops->find_and_open_solib)
+    {
+      file = ops->find_and_open_solib (in_pathname);
+      if (file_location_is_valid (&file))
+	return file;
+      file_location_free (&file);
+    }
 
   /* If not found, next search the inferior's $PATH environment variable.  */
-  if (found_file < 0 && sysroot == NULL)
-    found_file = openp (get_in_environ (current_inferior ()->environment,
-					"PATH"),
-			OPF_TRY_CWD_FIRST, in_pathname, &temp_pathname);
+  if (sysroot == NULL)
+    {
+      file = openp_file (get_in_environ (current_inferior ()->environment,
+					 "PATH"),
+			 OPF_TRY_CWD_FIRST | opts, in_pathname);
+      if (file_location_is_valid (&file))
+	{
+	  file.filename = gdb_realpath_and_xfree (file.filename);
+	  return file;
+	}
+      file_location_free (&file);
+    }
 
   /* If not found, and we're looking for a solib, next search the
      inferior's $LD_LIBRARY_PATH environment variable.  */
-  if (is_solib && found_file < 0 && sysroot == NULL)
-    found_file = openp (get_in_environ (current_inferior ()->environment,
-					"LD_LIBRARY_PATH"),
-			OPF_TRY_CWD_FIRST, in_pathname, &temp_pathname);
-
-  if (found_file >= 0 && temp_pathname_is_realpath)
-    temp_pathname = gdb_realpath_and_xfree (temp_pathname);
-
-  if (fd == NULL)
+  if (is_solib && sysroot == NULL)
     {
-      if (found_file >= 0)
-	close (found_file);
+      file = openp_file (get_in_environ (current_inferior ()->environment,
+					 "LD_LIBRARY_PATH"),
+			 OPF_TRY_CWD_FIRST | opts, in_pathname);
+      if (file_location_is_valid (&file))
+	{
+	  file.filename = gdb_realpath_and_xfree (file.filename);
+	  return file;
+	}
+      file_location_free (&file);
     }
-  else
-    *fd = found_file;
 
-  return temp_pathname;
+  file_location_enoent (&file);
+  return file;
 }
 
-/* It is an solib_find_2 wrapper handling multiple directory components
+/* It is an solib_find_3 wrapper handling multiple directory components
    of GDB_SYSROOT.  */
 
-static char *
-solib_find_1 (char *in_pathname, int *fd, int is_solib)
+static struct file_location
+solib_find_2 (char *in_pathname, enum openp_flags opts, int is_solib)
 {
   VEC (char_ptr) *sysroot_vec;
   struct cleanup *back_to;
-  char *retval, *sysroot;
+  struct file_location file;
+  char *sysroot;
   int ix;
 
   sysroot_vec = dirnames_to_char_ptr_vec_target_exc (gdb_sysroot);
@@ -395,12 +415,45 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
 
   for (ix = 0; VEC_iterate (char_ptr, sysroot_vec, ix, sysroot); ++ix)
     {
-      retval = solib_find_2 (in_pathname, fd, is_solib, sysroot);
-      if (retval != NULL)
-	break;
+      file = solib_find_3 (in_pathname, opts, is_solib, sysroot);
+      if (file_location_is_valid (&file))
+	{
+	  do_cleanups (back_to);
+	  return file;
+	}
+      file_location_free (&file);
     }
 
   do_cleanups (back_to);
+  return file;
+}
+
+/* It is an solib_find_2 wrapper returning filename and optionally FD
+   for functions not yet converted to the file_location style.  */
+
+static char *
+solib_find_1 (char *in_pathname, int *fd, int is_solib)
+{
+  struct file_location file = solib_find_2 (in_pathname, OPF_NONE, is_solib);
+  char *retval;
+
+  if (!file_location_is_valid (&file))
+    {
+      retval = NULL;
+      if (fd != NULL)
+	*fd = -1;
+    }
+  else
+    {
+      retval = xstrdup (file.filename);
+      if (fd != NULL)
+	{
+	  gdb_assert (file.fd != -1);
+	  *fd = file.fd;
+	  file.fd = -1;
+	}
+    }
+  file_location_free (&file);
   return retval;
 }
 
@@ -444,8 +497,8 @@ exec_file_find (char *in_pathname, int *fd)
    The search algorithm used is described in solib_find_1's comment
    above.  */
 
-char *
-solib_find (char *in_pathname, int *fd)
+static struct file_location
+solib_find_file (char *in_pathname, enum openp_flags opts)
 {
   const char *solib_symbols_extension
     = gdbarch_solib_symbols_extension (target_gdbarch ());
@@ -473,7 +526,36 @@ solib_find (char *in_pathname, int *fd)
 	}
     }
 
-  return solib_find_1 (in_pathname, fd, 1);
+  return solib_find_2 (in_pathname, opts, 1 /* is_solib */);
+}
+
+/* It is an solib_find_file wrapper returning filename and optionally FD
+   for functions not yet converted to the file_location style.  */
+
+char *
+solib_find (char *in_pathname, int *fd)
+{
+  struct file_location file = solib_find_file (in_pathname, OPF_NONE);
+  char *retval;
+
+  if (!file_location_is_valid (&file))
+    {
+      retval = NULL;
+      if (fd != NULL)
+	*fd = -1;
+    }
+  else
+    {
+      retval = xstrdup (file.filename);
+      if (fd != NULL)
+	{
+	  gdb_assert (file.fd != -1);
+	  *fd = file.fd;
+	  file.fd = -1;
+	}
+    }
+  file_location_free (&file);
+  return retval;
 }
 
 /* Open and return a BFD for the shared library PATHNAME.  If FD is not -1,
diff --git a/gdb/solist.h b/gdb/solist.h
index 47e9d88..7d0a21e 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -142,11 +142,8 @@ struct target_so_ops
     /* Find and open shared library binary file.  */
     bfd *(*bfd_open) (char *pathname);
 
-    /* Optional extra hook for finding and opening a solib.
-       If TEMP_PATHNAME is non-NULL: If the file is successfully opened a
-       pointer to a malloc'd and realpath'd copy of SONAME is stored there,
-       otherwise NULL is stored there.  */
-    int (*find_and_open_solib) (char *soname, char **temp_pathname);
+    /* Optional extra hook for finding and opening a solib.  */
+    struct file_location (*find_and_open_solib) (char *soname);
 
     /* Hook for looking up global symbols in a library-specific way.  */
     struct block_symbol (*lookup_lib_global_symbol)

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 09/32] Change sysroot to ":target:"
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (17 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 17/32] Add file_location utility functions Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 13/32] Code cleanup: openp parameter filename_opened is never NULL Jan Kratochvil
                   ` (13 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

that is try "" first and "target:" second.

Various performance problems should be fixed by trying to look up the remote
file first on local filesystem.  Thanks to build-ids it is quick and safe to
verify both files are the same build.


Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* NEWS (Changes since GDB 7.10): Mention sysroot.
	* main.c (captured_main): Initialize new gdb_sysroot.

gdb/testsuite/ChangeLog

	* gdb.base/attach.exp (do_attach_tests): Update sysroot parsing.
	* gdb.base/break-probes.exp: Likewise.
---
 gdb/testsuite/gdb.base/attach.exp       |    7 +++++--
 gdb/testsuite/gdb.base/break-probes.exp |    7 +++++--
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index f5a01e8..a45aaa6 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -38,6 +38,9 @@ show debug bfd-cache
 * The "set sysroot" (and "show sysroot") commands now permit multiple
   directory paths.
 
+* Default sysroot has changed to ":target:", that is first host files
+  and then target files are tried.
+
 * New options
 
 set validate-build-id (on|off)
diff --git a/gdb/main.c b/gdb/main.c
index aecd60a..a17ee34 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -548,7 +548,11 @@ captured_main (void *data)
   if (gdb_sysroot == NULL || *gdb_sysroot == '\0')
     {
       xfree (gdb_sysroot);
-      gdb_sysroot = xstrdup (TARGET_SYSROOT_PREFIX);
+      
+      /* Try first the local filesystem,
+         TARGET_SYSROOT_PREFIX is a fallback.  */
+      gdb_sysroot = xstrprintf ("%c%s", DIRNAME_SEPARATOR,
+				TARGET_SYSROOT_PREFIX);
     }
 
   debug_file_directory = relocate_gdb_directory (DEBUGDIR,
diff --git a/gdb/testsuite/gdb.base/attach.exp b/gdb/testsuite/gdb.base/attach.exp
index bf0d84e..a879e33 100644
--- a/gdb/testsuite/gdb.base/attach.exp
+++ b/gdb/testsuite/gdb.base/attach.exp
@@ -67,7 +67,7 @@ proc do_attach_tests {} {
     global timeout
     
     # Figure out a regular expression that will match the sysroot,
-    # noting that the default sysroot is "target:", and also noting
+    # noting that the default sysroot is ":target:", and also noting
     # that GDB will strip "target:" from the start of filenames when
     # operating on the local filesystem
     set sysroot ""
@@ -77,7 +77,10 @@ proc do_attach_tests {} {
 	    set sysroot $expect_out(1,string)
 	}
     }
-    regsub "^target:" "$sysroot" "(target:)?" sysroot
+    # Use only the first element of $sysroot which will hopefully
+    # successfully match the filename.
+    regsub "^target:(\[^:\]*):.*$" "$sysroot" "" sysroot
+    regsub "^(?!target:)(\[^:\]*):.*$" "$sysroot" "" sysroot
 
     # Start the program running and then wait for a bit, to be sure
     # that it can be attached to.
diff --git a/gdb/testsuite/gdb.base/break-probes.exp b/gdb/testsuite/gdb.base/break-probes.exp
index 00ca458..0431aa3 100644
--- a/gdb/testsuite/gdb.base/break-probes.exp
+++ b/gdb/testsuite/gdb.base/break-probes.exp
@@ -67,8 +67,11 @@ if { $using_probes } {
     }
 
     # GDB strips "target:" from the start of filenames
-    # when operating on the local filesystem
-    regsub "^target:" "$sysroot" "(target:)?" sysroot
+    # when operating on the local filesystem.
+    # Also use only the first element of $sysroot which will hopefully
+    # successfully match the filename.
+    regsub "^target:(\[^:\]*):.*$" "$sysroot" "" sysroot
+    regsub "^(?!target:)(\[^:\]*):.*$" "$sysroot" "" sysroot
 
     # Run til it loads our library
     set test "run til our library loads"

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 14/32] Provide new gdb_bfd_open_from_target
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (11 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 20/32] symfile_bfd_open: Make it use openp_bfd() Jan Kratochvil
@ 2015-08-21 21:22 ` Jan Kratochvil
  2015-08-21 21:22 ` [PATCH v12 15/32] gdb_bfd_open_from_target: Support real fd Jan Kratochvil
                   ` (19 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:22 UTC (permalink / raw)
  To: gdb-patches

Hi,

later code needs to call the gdb_bfd_openr_iovec part of gdb_bfd_open with more
special parameters.  So it is refactored out first (and extended later in the
next patches).

Jan


gdb/ChangeLog
2015-08-18  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb_bfd.c (gdb_bfd_open_from_target): New function from ...
	(gdb_bfd_open): ... here.  Call it.
	* gdb_bfd.h (gdb_bfd_open_from_target): New prototype.
---
 0 files changed

diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 64712da..10031f8 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -353,6 +353,25 @@ gdb_bfd_iovec_fileio_fstat (struct bfd *abfd, void *stream,
   return result;
 }
 
+/* Open a read-only (FOPEN_RB) BFD using target fileio operations given
+   arguments like bfd_fopen.  Return value matches that of
+   gdb_bfd_openr_iovec.  */
+
+struct bfd *
+gdb_bfd_open_from_target (const char *name, const char *target, int fd)
+{
+  gdb_assert (is_target_filename (name));
+  gdb_assert (!target_filesystem_is_local ());
+  gdb_assert (fd == -1);
+
+  return gdb_bfd_openr_iovec (name, target,
+			      gdb_bfd_iovec_fileio_open,
+			      current_inferior (),
+			      gdb_bfd_iovec_fileio_pread,
+			      gdb_bfd_iovec_fileio_close,
+			      gdb_bfd_iovec_fileio_fstat);
+}
+
 /* See gdb_bfd.h.  */
 
 struct bfd *
@@ -367,16 +386,7 @@ gdb_bfd_open (const char *name, const char *target, int fd)
   if (is_target_filename (name))
     {
       if (!target_filesystem_is_local ())
-	{
-	  gdb_assert (fd == -1);
-
-	  return gdb_bfd_openr_iovec (name, target,
-				      gdb_bfd_iovec_fileio_open,
-				      current_inferior (),
-				      gdb_bfd_iovec_fileio_pread,
-				      gdb_bfd_iovec_fileio_close,
-				      gdb_bfd_iovec_fileio_fstat);
-	}
+	return gdb_bfd_open_from_target (name, target, fd);
 
       name += strlen (TARGET_SYSROOT_PREFIX);
     }
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index 8fbdf36..0e38d62 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -53,6 +53,9 @@ int gdb_bfd_has_target_filename (struct bfd *abfd);
 
 struct bfd *gdb_bfd_open (const char *name, const char *target, int fd);
 
+struct bfd *gdb_bfd_open_from_target (const char *name, const char *target,
+				      int fd);
+
 /* Increment the reference count of ABFD.  It is fine for ABFD to be
    NULL; in this case the function does nothing.  */
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 27/32] build_id_verify: Make it more verbose
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (24 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 23/32] build_id_to_bfd: Make it return file_location Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 24/32] solib_find: Search also by build-id Jan Kratochvil
                   ` (6 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

it was discussed on this list that if build-ids do not match they should be
printed for troubleshooting.  It is mostly independent from the other patches.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* build-id.c: Include rsp-low.h.
	(build_id_verify): Print non-matching build-ids, update the messages.
---
 0 files changed

diff --git a/gdb/build-id.c b/gdb/build-id.c
index 25ee606..48839cc 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -28,6 +28,7 @@
 #include "gdbcore.h"
 #include "gdbcmd.h"
 #include "source.h"
+#include "rsp-low.h"
 
 /* Boolean for command 'set validate-build-id'.  */
 int validate_build_id = 1;
@@ -64,21 +65,39 @@ int
 build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
 {
   const struct bfd_build_id *found;
-  int retval = 0;
+  char *message, *check_hex;
+  struct cleanup *back_to;
+
+  if (check_len == 0 || !validate_build_id)
+    return 1;
 
   found = build_id_bfd_get (abfd);
+  check_hex = alloca (check_len * 2 + 1);
+  bin2hex (check, check_hex, check_len);
 
   if (found == NULL)
-    warning (_("File \"%s\" has no build-id, file skipped"),
-	     bfd_get_filename (abfd));
+    message = xstrprintf (_("inferior build ID is %s but symbol file \"%s\" "
+			    "does not have build ID"),
+			  check_hex, bfd_get_filename (abfd));
   else if (found->size != check_len
            || memcmp (found->data, check, found->size) != 0)
-    warning (_("File \"%s\" has a different build-id, file skipped"),
-	     bfd_get_filename (abfd));
-  else
-    retval = 1;
+    {
+      char *abfd_hex = alloca (found->size * 2 + 1);
 
-  return retval;
+      bin2hex (found->data, abfd_hex, found->size);
+      message = xstrprintf (_("inferior build ID %s is not identical to "
+			      "symbol file \"%s\" build ID %s"),
+			    check_hex, bfd_get_filename (abfd), abfd_hex);
+    }
+  else
+    return 1;
+  back_to = make_cleanup (xfree, message);
+
+  warning (_("Symbol file \"%s\" could not be validated (%s) and "
+	     "will be ignored; or use 'set validate-build-id off'."),
+	   bfd_get_filename (abfd), message);
+  do_cleanups (back_to);
+  return 0;
 }
 
 /* Find and open a BFD given a build-id.  If no BFD can be found,

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 23/32] build_id_to_bfd: Make it return file_location
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (23 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 26/32] solib_bfd_open: Optimize opening twice Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 27/32] build_id_verify: Make it more verbose Jan Kratochvil
                   ` (7 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

refactor build_id_to_bfd so that it returns file_location.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* build-id.c: Include source.h.
	(build_id_to_bfd): Rename to ...
	(build_id_to_file): ... here, return file_location, add parameter opts,
	make it public.
	(build_id_to_debug_bfd): Use build_id_to_file.
	* build-id.h (build_id_to_file): New prototype.
---
 0 files changed

diff --git a/gdb/build-id.c b/gdb/build-id.c
index 8b45fec..25ee606 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -27,6 +27,7 @@
 #include "filenames.h"
 #include "gdbcore.h"
 #include "gdbcmd.h"
+#include "source.h"
 
 /* Boolean for command 'set validate-build-id'.  */
 int validate_build_id = 1;
@@ -84,15 +85,15 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
    return NULL.  Use "" or ".debug" for SUFFIX.  The returned reference to the
    BFD must be released by the caller.  */
 
-static bfd *
-build_id_to_bfd (size_t build_id_len, const bfd_byte *build_id,
-		 const char *suffix)
+struct file_location
+build_id_to_file (size_t build_id_len, const bfd_byte *build_id,
+		  const char *suffix, enum openp_flags opts)
 {
   char *link, *debugdir;
   VEC (char_ptr) *debugdir_vec;
   struct cleanup *back_to;
   int ix;
-  bfd *abfd = NULL;
+  struct file_location result;
 
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
   link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
@@ -110,8 +111,6 @@ build_id_to_bfd (size_t build_id_len, const bfd_byte *build_id,
       const gdb_byte *data = build_id;
       size_t size = build_id_len;
       char *s;
-      char *filename = NULL;
-      struct cleanup *inner;
 
       memcpy (link, debugdir, debugdir_len);
       s = &link[debugdir_len];
@@ -127,30 +126,18 @@ build_id_to_bfd (size_t build_id_len, const bfd_byte *build_id,
 	s += sprintf (s, "%02x", (unsigned) *data++);
       strcpy (s, suffix);
 
-      /* lrealpath() is expensive even for the usually non-existent files.  */
-      if (access (link, F_OK) == 0)
-	filename = lrealpath (link);
-
-      if (filename == NULL)
-	continue;
-
-      /* We expect to be silent on the non-existing files.  */
-      inner = make_cleanup (xfree, filename);
-      abfd = gdb_bfd_open (filename, gnutarget, -1);
-      do_cleanups (inner);
-
-      if (abfd == NULL)
-	continue;
-
-      if (build_id_verify (abfd, build_id_len, build_id))
-	break;
-
-      gdb_bfd_unref (abfd);
-      abfd = NULL;
+      result = file_location_from_filename (link, opts | OPF_BFD_CANONICAL,
+					    build_id_len, build_id);
+      if (file_location_is_valid (&result))
+	{
+	  do_cleanups (back_to);
+	  return result;
+	}
+      file_location_free (&result);
     }
 
-  do_cleanups (back_to);
-  return abfd;
+  file_location_enoent (&result);
+  return result;
 }
 
 /* See build-id.h.  */
@@ -158,7 +145,19 @@ build_id_to_bfd (size_t build_id_len, const bfd_byte *build_id,
 bfd *
 build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 {
-  return build_id_to_bfd (build_id_len, build_id, ".debug");
+  struct file_location result;
+  bfd *retval;
+
+  result = build_id_to_file (build_id_len, build_id, ".debug", OPF_IS_BFD);
+  if (result.abfd == NULL)
+    {
+      file_location_free (&result);
+      return NULL;
+    }
+  gdb_bfd_ref (result.abfd);
+  retval = result.abfd;
+  file_location_free (&result);
+  return retval;
 }
 
 /* See build-id.h.  */
diff --git a/gdb/build-id.h b/gdb/build-id.h
index 63b9d8d..bb93df2 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -30,6 +30,9 @@ extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
 extern int build_id_verify (bfd *abfd,
 			    size_t check_len, const bfd_byte *check);
 
+extern struct file_location
+  build_id_to_file (size_t build_id_len, const bfd_byte *build_id,
+		    const char *suffix, enum openp_flags opts);
 
 /* Find and open a BFD given a build-id.  If no BFD can be found,
    return NULL.  The returned reference to the BFD must be released by

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 24/32] solib_find: Search also by build-id
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (25 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 27/32] build_id_verify: Make it more verbose Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:24 ` [PATCH v12 28/32] Tests for validate symbol file using build-id Jan Kratochvil
                   ` (5 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

solib_find() can now try to search also by build-id.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* solib.c: Include build-id.h.
	(solib_find_3): Call build_id_to_file.
---
 0 files changed

diff --git a/gdb/solib.c b/gdb/solib.c
index b044e72..a425e4d 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -47,6 +47,7 @@
 #include "gdb_bfd.h"
 #include "filestuff.h"
 #include "source.h"
+#include "build-id.h"
 
 /* Architecture-specific operations.  */
 
@@ -313,6 +314,17 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
 
   /* We try to find the library in various ways.  */
 
+  if (build_idsz != 0)
+    {
+      file = build_id_to_file (build_idsz, build_id, "", opts);
+      if (file_location_is_valid (&file))
+	{
+	  do_cleanups (old_chain);
+	  return file;
+	}
+      file_location_free (&file);
+    }
+
   /* If the search in gdb_sysroot failed, and the path name is
      absolute at this point, make it relative.  (openp will try and open the
      file according to its absolute path otherwise, which is not what we want.)

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 25/32] Verify the build-id
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (20 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 21/32] build_id_to_debug_bfd: Make it also non-.debug capable Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 22/32] Add dummy build-id params to prototypes Jan Kratochvil
                   ` (10 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

now it is possible to filter-out from openp() search files with non-matching
build-id.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* source.c: Include build-id.h.
	(file_location_from_filename): Call build_id_verify for the build-id
	parameters.
---
 0 files changed

diff --git a/gdb/source.c b/gdb/source.c
index 9a38df4..e5684da 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -29,6 +29,7 @@
 #include "filestuff.h"
 #include "inferior.h"
 #include "gdb/fileio.h"
+#include "build-id.h"
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -848,7 +849,7 @@ file_location_from_filename (const char *filename, enum openp_flags opts,
 	}
     }
 
-  if ((opts & OPF_IS_BFD) == 0)
+  if ((build_idsz == 0 || !validate_build_id) && (opts & OPF_IS_BFD) == 0)
     {
       discard_cleanups (back_to);
       return file;
@@ -908,6 +909,27 @@ file_location_from_filename (const char *filename, enum openp_flags opts,
       return file;
     }
 
+  if (build_idsz == 0 || !validate_build_id)
+    {
+      gdb_assert ((opts & OPF_IS_BFD) != 0);
+      discard_cleanups (back_to);
+      return file;
+    }
+
+  if (!build_id_verify (file.abfd, build_idsz, build_id))
+    {
+      do_cleanups (back_to);
+      file_location_enoent (&file);
+      return file;
+    }
+
+  if ((opts & OPF_IS_BFD) == 0)
+    {
+      gdb_bfd_unref (file.abfd);
+      file.abfd = NULL;
+      gdb_assert (file.fd != -1);
+    }
+
   discard_cleanups (back_to);
   return file;
 }

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 21/32] build_id_to_debug_bfd: Make it also non-.debug capable
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (19 preceding siblings ...)
  2015-08-21 21:22 ` [PATCH v12 13/32] Code cleanup: openp parameter filename_opened is never NULL Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 25/32] Verify the build-id Jan Kratochvil
                   ` (11 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

generalize the function by adding 'suffix' parameter.  To be reused later.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* build-id.c (build_id_to_debug_bfd): Rename to ...
	(build_id_to_bfd): ... here, add parameter suffix.
	(build_id_to_debug_bfd): New function.
---
 0 files changed

diff --git a/gdb/build-id.c b/gdb/build-id.c
index 0b069fd..8b45fec 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -80,10 +80,13 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
   return retval;
 }
 
-/* See build-id.h.  */
+/* Find and open a BFD given a build-id.  If no BFD can be found,
+   return NULL.  Use "" or ".debug" for SUFFIX.  The returned reference to the
+   BFD must be released by the caller.  */
 
-bfd *
-build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
+static bfd *
+build_id_to_bfd (size_t build_id_len, const bfd_byte *build_id,
+		 const char *suffix)
 {
   char *link, *debugdir;
   VEC (char_ptr) *debugdir_vec;
@@ -93,7 +96,7 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 
   /* DEBUG_FILE_DIRECTORY/.build-id/ab/cdef */
   link = alloca (strlen (debug_file_directory) + (sizeof "/.build-id/" - 1) + 1
-		 + 2 * build_id_len + (sizeof ".debug" - 1) + 1);
+		 + 2 * build_id_len + strlen (suffix) + 1);
 
   /* Keep backward compatibility so that DEBUG_FILE_DIRECTORY being "" will
      cause "/.build-id/..." lookups.  */
@@ -122,7 +125,7 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 	*s++ = '/';
       while (size-- > 0)
 	s += sprintf (s, "%02x", (unsigned) *data++);
-      strcpy (s, ".debug");
+      strcpy (s, suffix);
 
       /* lrealpath() is expensive even for the usually non-existent files.  */
       if (access (link, F_OK) == 0)
@@ -152,6 +155,14 @@ build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
 
 /* See build-id.h.  */
 
+bfd *
+build_id_to_debug_bfd (size_t build_id_len, const bfd_byte *build_id)
+{
+  return build_id_to_bfd (build_id_len, build_id, ".debug");
+}
+
+/* See build-id.h.  */
+
 char *
 find_separate_debug_file_by_buildid (struct objfile *objfile)
 {

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 22/32] Add dummy build-id params to prototypes
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (21 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 25/32] Verify the build-id Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 26/32] solib_bfd_open: Optimize opening twice Jan Kratochvil
                   ` (9 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

it is a lot of text with no functionality.  Add build-id parameters where
needed, pass them where they are already available, otherwise pass 0 in the top
callers.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* cli/cli-cmds.c (find_and_open_script): Pass zero build-id.
	* defs.h (openp, openp_file, source_full_path_of): Add build-id
	parameters.
	* dwarf2read.c (try_open_dwop_file): Pass zero build-id.
	* exec.c (exec_file_locate_attach): Likewise.
	* infrun.c (follow_exec): Likewise.
	* nto-tdep.c (nto_find_and_open_solib): Add build-id parameters, pass
	them.
	* nto-tdep.h (nto_find_and_open_solib): Add build-id parameters.
	* solib-aix.c (solib_aix_bfd_open): Add build-id parameters, pass them.
	* solib-darwin.c (darwin_bfd_open): Likewise.
	* solib-dsbt.c (enable_break): Pass zero build-id.
	* solib-frv.c (enable_break2): Likewise.
	* solib-spu.c (spu_bfd_open): Add build-id parameters, pass them.
	* solib-svr4.c (enable_break): Pass zero build-id.
	* solib.c (solib_find_3, solib_find_2, solib_find_1, exec_file_find)
	(solib_find_file, solib_find, solib_bfd_open): Add build-id
	parameters, pass them.
	(solib_map_sections): Pass so->build-id* to bfd_open.
	(reload_shared_libraries_1): Pass so->build-id* to solib_bfd_open.
	* solist.h (struct target_so_ops): Add build-id parameters to bfd_open
	and find_and_open_solib.
	(exec_file_find, solib_find, solib_bfd_open): Add build-id parameters.
	* source.c (file_location_from_filename): Add build-id parameters.
	(filename_to_bfd): Pass zero build-id.
	(openp): Add build-id parameters, pass them.
	(openp_bfd): Pass zero build-id.
	(openp_file, source_full_path_of): Add build-id parameters, pass them.
	(find_and_open_source): Pass zero build-id.
	* source.h (file_location_from_filename): Add build-id parameters.
---
 0 files changed

diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index d495463..da47b03 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -510,7 +510,8 @@ find_and_open_script (const char *script_file, int search_path,
 
   /* Search for and open 'file' on the search path used for source
      files.  Put the full location in *FULL_PATHP.  */
-  fd = openp (source_path, search_flags, file, full_pathp);
+  fd = openp (source_path, search_flags, file, 0 /* build_idsz */,
+	      NULL /* build_id */, full_pathp);
 
   if (fd == -1)
     {
diff --git a/gdb/defs.h b/gdb/defs.h
index ac735c2..1bc7b69 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -347,15 +347,18 @@ enum openp_flags
   OPF_BFD_CANONICAL   = (1 << 3),
 };
 
-extern int openp (const char *, enum openp_flags, const char *, char **);
+extern int openp (const char *, enum openp_flags, const char *,
+		  size_t build_idsz, const gdb_byte *build_id, char **);
 
 extern bfd *openp_bfd (const char *path, enum openp_flags opts,
 		       const char *string);
 
 extern struct file_location openp_file (const char *path, enum openp_flags opts,
-					const char *string);
+					const char *string, size_t build_idsz,
+					const gdb_byte *build_id);
 
-extern int source_full_path_of (const char *, char **);
+extern int source_full_path_of (const char *, size_t build_idsz,
+				const gdb_byte *build_id, char **);
 
 extern void mod_path (char *, char **);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ae06e14..3fb446f 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -10473,7 +10473,8 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
   flags = OPF_NONE;
   if (is_dwp)
     flags |= OPF_SEARCH_IN_PATH;
-  desc = openp (search_path, flags, file_name, &absolute_name);
+  desc = openp (search_path, flags, file_name, 0 /* build_idsz */,
+		NULL /* build_id */, &absolute_name);
   xfree (search_path);
   if (desc < 0)
     return NULL;
diff --git a/gdb/exec.c b/gdb/exec.c
index 6dd2aa6..0593478 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -155,7 +155,8 @@ exec_file_locate_attach (int pid, int from_tty)
   /* If gdb_sysroot is not empty and the discovered filename
      is absolute then prefix the filename with gdb_sysroot.  */
   if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file))
-    full_exec_path = exec_file_find (exec_file, NULL);
+    full_exec_path = exec_file_find (exec_file, 0 /* build_idsz */,
+				     NULL /* build_id */, NULL);
 
   if (full_exec_path == NULL)
     {
@@ -166,7 +167,8 @@ exec_file_locate_attach (int pid, int from_tty)
 	 Attempt to qualify the filename against the source path.
 	 (If that fails, we'll just fall back on the original
 	 filename.  Not much more we can do...)  */
-      if (!source_full_path_of (exec_file, &full_exec_path))
+      if (!source_full_path_of (exec_file, 0 /* build_idsz */,
+				NULL /* build_id */, &full_exec_path))
 	full_exec_path = xstrdup (exec_file);
     }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 25036a4..c1beafd 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1165,7 +1165,8 @@ follow_exec (ptid_t ptid, char *execd_pathname)
 
   if (*gdb_sysroot != '\0')
     {
-      char *name = exec_file_find (execd_pathname, NULL);
+      char *name = exec_file_find (execd_pathname, 0 /* build_idsz */,
+				   NULL /* build_id */, NULL);
 
       execd_pathname = alloca (strlen (name) + 1);
       strcpy (execd_pathname, name);
diff --git a/gdb/nto-tdep.c b/gdb/nto-tdep.c
index 9f9e3bc..48a0005 100644
--- a/gdb/nto-tdep.c
+++ b/gdb/nto-tdep.c
@@ -83,7 +83,8 @@ nto_map_arch_to_cputype (const char *arch)
 }
 
 struct file_location
-nto_find_and_open_solib (char *solib)
+nto_find_and_open_solib (char *solib, size_t build_idsz,
+			 const gdb_byte *build_id)
 {
   char *buf, *arch_path, *nto_root;
   const char *endian;
@@ -129,13 +130,15 @@ nto_find_and_open_solib (char *solib)
 	     arch_path);
 
   base = lbasename (solib);
-  file = openp_file (buf, OPF_TRY_CWD_FIRST | OPF_IS_BFD, base);
+  file = openp_file (buf, OPF_TRY_CWD_FIRST | OPF_IS_BFD, base, build_idsz,
+		     build_id);
   if (file_location_is_valid (&file) || base == solib)
     return file;
   file_location_free (&file);
 
   xsnprintf (arch_path, arch_len, "/%s", solib);
-  return file_location_from_filename (arch_path, OPF_IS_BFD);
+  return file_location_from_filename (arch_path, OPF_IS_BFD, build_idsz,
+				      build_id);
 }
 
 void
diff --git a/gdb/nto-tdep.h b/gdb/nto-tdep.h
index 5828765..73e5dd6 100644
--- a/gdb/nto-tdep.h
+++ b/gdb/nto-tdep.h
@@ -154,7 +154,8 @@ void nto_relocate_section_addresses (struct so_list *,
 
 int nto_map_arch_to_cputype (const char *);
 
-struct file_location nto_find_and_open_solib (char *);
+struct file_location nto_find_and_open_solib (char *, size_t build_idsz,
+					      const gdb_byte *build_id);
 
 enum gdb_osabi nto_elf_osabi_sniffer (bfd *abfd);
 
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 99258f6..c376430 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -633,7 +633,7 @@ solib_aix_in_dynsym_resolve_code (CORE_ADDR pc)
 /* Implement the "bfd_open" target_so_ops method.  */
 
 static bfd *
-solib_aix_bfd_open (char *pathname)
+solib_aix_bfd_open (char *pathname, size_t build_idsz, const gdb_byte *build_id)
 {
   /* The pathname is actually a synthetic filename with the following
      form: "/path/to/sharedlib(member.o)" (double-quotes excluded).
@@ -650,7 +650,7 @@ solib_aix_bfd_open (char *pathname)
   struct cleanup *cleanup;
 
   if (pathname[path_len - 1] != ')')
-    return solib_bfd_open (pathname);
+    return solib_bfd_open (pathname, build_idsz, build_id);
 
   /* Search for the associated parens.  */
   sep = strrchr (pathname, '(');
@@ -660,7 +660,7 @@ solib_aix_bfd_open (char *pathname)
 	 to open pathname without decoding, possibly leading to
 	 a failure), rather than triggering an assert failure).  */
       warning (_("missing '(' in shared object pathname: %s"), pathname);
-      return solib_bfd_open (pathname);
+      return solib_bfd_open (pathname, build_idsz, build_id);
     }
   filename_len = sep - pathname;
 
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 2a33cd7..be0bb54 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -578,7 +578,7 @@ darwin_lookup_lib_symbol (struct objfile *objfile,
 }
 
 static bfd *
-darwin_bfd_open (char *pathname)
+darwin_bfd_open (char *pathname, size_t build_idsz, const gdb_byte *build_id)
 {
   char *found_pathname;
   int found_file;
@@ -586,7 +586,7 @@ darwin_bfd_open (char *pathname)
   bfd *res;
 
   /* Search for shared library file.  */
-  found_pathname = solib_find (pathname, &found_file);
+  found_pathname = solib_find (pathname, build_idsz, build_id, &found_file);
   if (found_pathname == NULL)
     perror_with_name (pathname);
 
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 7da5833..d55a9ed 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -835,7 +835,7 @@ enable_break (void)
 
       TRY
 	{
-	  tmp_bfd = solib_bfd_open (buf);
+	  tmp_bfd = solib_bfd_open (buf, 0, NULL);
 	}
       CATCH (ex, RETURN_MASK_ALL)
 	{
diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c
index f7ef38b..87b0a68 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -558,7 +558,7 @@ enable_break2 (void)
 
       TRY
         {
-          tmp_bfd = solib_bfd_open (buf);
+          tmp_bfd = solib_bfd_open (buf, 0, NULL);
         }
       CATCH (ex, RETURN_MASK_ALL)
 	{
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index 64a5c9c..8358f93 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -344,7 +344,7 @@ spu_bfd_fopen (char *name, CORE_ADDR addr)
 
 /* Open shared library BFD.  */
 static bfd *
-spu_bfd_open (char *pathname)
+spu_bfd_open (char *pathname, size_t build_idsz, const gdb_byte *build_id)
 {
   char *original_name = strrchr (pathname, '@');
   bfd *abfd;
@@ -354,7 +354,7 @@ spu_bfd_open (char *pathname)
 
   /* Handle regular SVR4 libraries.  */
   if (!original_name)
-    return svr4_so_ops.bfd_open (pathname);
+    return svr4_so_ops.bfd_open (pathname, build_idsz, build_id);
 
   /* Decode object ID.  */
   if (sscanf (original_name, "@0x%llx <%d>", &addr, &fd) != 2)
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 070b95f..8739c31 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -2366,7 +2366,7 @@ enable_break (struct svr4_info *info, int from_tty)
 
       TRY
         {
-	  tmp_bfd = solib_bfd_open (interp_name);
+	  tmp_bfd = solib_bfd_open (interp_name, 0, NULL);
 	}
       CATCH (ex, RETURN_MASK_ALL)
 	{
diff --git a/gdb/solib.c b/gdb/solib.c
index 4fe4cb3..b044e72 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -148,7 +148,7 @@ show_solib_search_path (struct ui_file *file, int from_tty,
 
 static struct file_location
 solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
-	      const char *sysroot)
+	      const char *sysroot, size_t build_idsz, const gdb_byte *build_id)
 {
   const struct target_so_ops *ops = solib_ops (target_gdbarch ());
   char *temp_pathname;
@@ -247,7 +247,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
     }
 
   /* Now see if we can open it.  */
-  file = file_location_from_filename (temp_pathname, opts);
+  file = file_location_from_filename (temp_pathname, opts, build_idsz,
+				      build_id);
   if (file_location_is_valid (&file))
     {
       do_cleanups (old_chain);
@@ -275,7 +276,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
 			      in_pathname + 2, (char *) NULL);
       xfree (drive);
 
-      file = file_location_from_filename (temp_pathname, opts);
+      file = file_location_from_filename (temp_pathname, opts, build_idsz,
+					  build_id);
       if (file_location_is_valid (&file))
 	{
 	  do_cleanups (old_chain);
@@ -295,7 +297,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
 			      need_dir_separator ? SLASH_STRING : "",
 			      in_pathname + 2, (char *) NULL);
 
-      file = file_location_from_filename (temp_pathname, opts);
+      file = file_location_from_filename (temp_pathname, opts, build_idsz,
+					  build_id);
       if (file_location_is_valid (&file))
 	{
 	  do_cleanups (old_chain);
@@ -330,7 +333,7 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
   if (is_solib && solib_search_path != NULL)
     {
       file = openp_file (solib_search_path, OPF_TRY_CWD_FIRST | opts,
-			 in_pathname);
+			 in_pathname, build_idsz, build_id);
       if (file_location_is_valid (&file))
 	{
 	  file.filename = gdb_realpath_and_xfree (file.filename);
@@ -346,7 +349,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
   if (is_solib && solib_search_path != NULL)
     {
       file = openp_file (solib_search_path, OPF_TRY_CWD_FIRST | opts,
-			 target_lbasename (fskind, in_pathname));
+			 target_lbasename (fskind, in_pathname), build_idsz,
+			 build_id);
       if (file_location_is_valid (&file))
 	{
 	  file.filename = gdb_realpath_and_xfree (file.filename);
@@ -359,7 +363,7 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
      supplied solib search method.  */
   if (is_solib && ops->find_and_open_solib)
     {
-      file = ops->find_and_open_solib (in_pathname);
+      file = ops->find_and_open_solib (in_pathname, build_idsz, build_id);
       if (file_location_is_valid (&file))
 	return file;
       file_location_free (&file);
@@ -370,7 +374,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
     {
       file = openp_file (get_in_environ (current_inferior ()->environment,
 					 "PATH"),
-			 OPF_TRY_CWD_FIRST | opts, in_pathname);
+			 OPF_TRY_CWD_FIRST | opts, in_pathname, build_idsz,
+			 build_id);
       if (file_location_is_valid (&file))
 	{
 	  file.filename = gdb_realpath_and_xfree (file.filename);
@@ -385,7 +390,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
     {
       file = openp_file (get_in_environ (current_inferior ()->environment,
 					 "LD_LIBRARY_PATH"),
-			 OPF_TRY_CWD_FIRST | opts, in_pathname);
+			 OPF_TRY_CWD_FIRST | opts, in_pathname, build_idsz,
+			 build_id);
       if (file_location_is_valid (&file))
 	{
 	  file.filename = gdb_realpath_and_xfree (file.filename);
@@ -402,7 +408,8 @@ solib_find_3 (char *in_pathname, enum openp_flags opts, int is_solib,
    of GDB_SYSROOT.  */
 
 static struct file_location
-solib_find_2 (char *in_pathname, enum openp_flags opts, int is_solib)
+solib_find_2 (char *in_pathname, enum openp_flags opts, int is_solib,
+	      size_t build_idsz, const gdb_byte *build_id)
 {
   VEC (char_ptr) *sysroot_vec;
   struct cleanup *back_to;
@@ -415,7 +422,8 @@ solib_find_2 (char *in_pathname, enum openp_flags opts, int is_solib)
 
   for (ix = 0; VEC_iterate (char_ptr, sysroot_vec, ix, sysroot); ++ix)
     {
-      file = solib_find_3 (in_pathname, opts, is_solib, sysroot);
+      file = solib_find_3 (in_pathname, opts, is_solib, sysroot, build_idsz,
+			   build_id);
       if (file_location_is_valid (&file))
 	{
 	  do_cleanups (back_to);
@@ -432,9 +440,11 @@ solib_find_2 (char *in_pathname, enum openp_flags opts, int is_solib)
    for functions not yet converted to the file_location style.  */
 
 static char *
-solib_find_1 (char *in_pathname, int *fd, int is_solib)
+solib_find_1 (char *in_pathname, size_t build_idsz, const gdb_byte *build_id,
+	      int *fd, int is_solib)
 {
-  struct file_location file = solib_find_2 (in_pathname, OPF_NONE, is_solib);
+  struct file_location file = solib_find_2 (in_pathname, OPF_NONE, is_solib,
+					    build_idsz, build_id);
   char *retval;
 
   if (!file_location_is_valid (&file))
@@ -466,9 +476,11 @@ solib_find_1 (char *in_pathname, int *fd, int is_solib)
    above.  */
 
 char *
-exec_file_find (char *in_pathname, int *fd)
+exec_file_find (char *in_pathname, size_t build_idsz, const gdb_byte *build_id,
+		int *fd)
 {
-  char *result = solib_find_1 (in_pathname, fd, 0);
+  char *result = solib_find_1 (in_pathname, build_idsz, build_id, fd,
+			       0 /* is_solib */);
 
   if (result == NULL)
     {
@@ -482,7 +494,8 @@ exec_file_find (char *in_pathname, int *fd)
 	  strcpy (new_pathname, in_pathname);
 	  strcat (new_pathname, ".exe");
 
-	  result = solib_find_1 (new_pathname, fd, 0);
+	  result = solib_find_1 (new_pathname, build_idsz, build_id, fd,
+				 0 /* is_solib */);
 	}
     }
 
@@ -498,7 +511,8 @@ exec_file_find (char *in_pathname, int *fd)
    above.  */
 
 static struct file_location
-solib_find_file (char *in_pathname, enum openp_flags opts)
+solib_find_file (char *in_pathname, enum openp_flags opts, size_t build_idsz,
+		 const gdb_byte *build_id)
 {
   const char *solib_symbols_extension
     = gdbarch_solib_symbols_extension (target_gdbarch ());
@@ -526,16 +540,19 @@ solib_find_file (char *in_pathname, enum openp_flags opts)
 	}
     }
 
-  return solib_find_2 (in_pathname, opts, 1 /* is_solib */);
+  return solib_find_2 (in_pathname, opts, 1 /* is_solib */, build_idsz,
+		       build_id);
 }
 
 /* It is an solib_find_file wrapper returning filename and optionally FD
    for functions not yet converted to the file_location style.  */
 
 char *
-solib_find (char *in_pathname, int *fd)
+solib_find (char *in_pathname, size_t build_idsz, const gdb_byte *build_id,
+	    int *fd)
 {
-  struct file_location file = solib_find_file (in_pathname, OPF_NONE);
+  struct file_location file = solib_find_file (in_pathname, OPF_NONE,
+					       build_idsz, build_id);
   char *retval;
 
   if (!file_location_is_valid (&file))
@@ -589,7 +606,7 @@ solib_bfd_fopen (char *pathname, int fd)
 /* Find shared library PATHNAME and open a BFD for it.  */
 
 bfd *
-solib_bfd_open (char *pathname)
+solib_bfd_open (char *pathname, size_t build_idsz, const gdb_byte *build_id)
 {
   char *found_pathname;
   int found_file;
@@ -597,7 +614,7 @@ solib_bfd_open (char *pathname)
   const struct bfd_arch_info *b;
 
   /* Search for shared library file.  */
-  found_pathname = solib_find (pathname, &found_file);
+  found_pathname = solib_find (pathname, build_idsz, build_id, &found_file);
   if (found_pathname == NULL)
     {
       /* Return failure if the file could not be found, so that we can
@@ -652,7 +669,7 @@ solib_map_sections (struct so_list *so)
 
   filename = tilde_expand (so->so_name);
   old_chain = make_cleanup (xfree, filename);
-  abfd = ops->bfd_open (filename);
+  abfd = ops->bfd_open (filename, so->build_idsz, so->build_id);
   do_cleanups (old_chain);
 
   if (abfd == NULL)
@@ -1475,7 +1492,7 @@ reload_shared_libraries_1 (int from_tty)
 
       filename = tilde_expand (so->so_original_name);
       make_cleanup (xfree, filename);
-      abfd = solib_bfd_open (filename);
+      abfd = solib_bfd_open (filename, so->build_idsz, so->build_id);
       if (abfd != NULL)
 	{
 	  found_pathname = xstrdup (bfd_get_filename (abfd));
diff --git a/gdb/solist.h b/gdb/solist.h
index 7d0a21e..34af30f 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -140,10 +140,13 @@ struct target_so_ops
     int (*in_dynsym_resolve_code) (CORE_ADDR pc);
 
     /* Find and open shared library binary file.  */
-    bfd *(*bfd_open) (char *pathname);
+    bfd *(*bfd_open) (char *pathname, size_t build_idsz,
+		      const gdb_byte *build_id);
 
     /* Optional extra hook for finding and opening a solib.  */
-    struct file_location (*find_and_open_solib) (char *soname);
+    struct file_location (*find_and_open_solib) (char *soname,
+						 size_t build_idsz,
+						 const gdb_byte *build_id);
 
     /* Hook for looking up global symbols in a library-specific way.  */
     struct block_symbol (*lookup_lib_global_symbol)
@@ -187,16 +190,19 @@ void free_so (struct so_list *so);
 struct so_list *master_so_list (void);
 
 /* Find main executable binary file.  */
-extern char *exec_file_find (char *in_pathname, int *fd);
+extern char *exec_file_find (char *in_pathname, size_t build_idsz,
+			     const gdb_byte *build_id, int *fd);
 
 /* Find shared library binary file.  */
-extern char *solib_find (char *in_pathname, int *fd);
+extern char *solib_find (char *in_pathname, size_t build_idsz,
+			 const gdb_byte *build_id, int *fd);
 
 /* Open BFD for shared library file.  */
 extern bfd *solib_bfd_fopen (char *pathname, int fd);
 
 /* Find solib binary file and open it.  */
-extern bfd *solib_bfd_open (char *in_pathname);
+extern bfd *solib_bfd_open (char *in_pathname, size_t build_idsz,
+			    const gdb_byte *build_id);
 
 /* FIXME: gdbarch needs to control this variable.  */
 extern struct target_so_ops *current_target_so_ops;
diff --git a/gdb/source.c b/gdb/source.c
index 029c3b5..9a38df4 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -795,7 +795,8 @@ file_location_is_valid (const struct file_location *file)
 /* Return new file_location from FILENAME and OPTS.  */
 
 struct file_location
-file_location_from_filename (const char *filename, enum openp_flags opts)
+file_location_from_filename (const char *filename, enum openp_flags opts,
+			     size_t build_idsz, const gdb_byte *build_id)
 {
   struct file_location file;
   struct cleanup *back_to;
@@ -954,7 +955,9 @@ bfd *
 filename_to_bfd (const char *filename)
 {
   return file_location_to_bfd (file_location_from_filename (filename,
-							    OPF_IS_BFD));
+							    OPF_IS_BFD,
+							    0 /* build_idsz */,
+							  NULL /* build_id */));
 }
 
 /* Wrapper of openp_file returning filename string.
@@ -967,14 +970,14 @@ filename_to_bfd (const char *filename)
 
 int
 openp (const char *path, enum openp_flags opts, const char *string,
-       char **filename_opened)
+       size_t build_idsz, const gdb_byte *build_id, char **filename_opened)
 {
   struct file_location file;
   int retval;
 
   gdb_assert ((opts & OPF_IS_BFD) == 0);
 
-  file = openp_file (path, opts, string);
+  file = openp_file (path, opts, string, build_idsz, build_id);
   gdb_assert (file.abfd == NULL);
   if (file.fd == -1)
     {
@@ -1002,7 +1005,9 @@ openp_bfd (const char *path, enum openp_flags opts, const char *string)
 {
   gdb_assert ((opts & OPF_IS_BFD) == 0);
 
-  return file_location_to_bfd (openp_file (path, opts | OPF_IS_BFD, string));
+  return file_location_to_bfd (openp_file (path, opts | OPF_IS_BFD, string,
+					   0 /* build_idsz */,
+					   NULL /* build_id */));
 }
 
 /* Open a file named STRING, searching path PATH (dir names sep by some char).
@@ -1010,6 +1015,9 @@ openp_bfd (const char *path, enum openp_flags opts, const char *string)
 
    OPTS specifies the function behaviour in specific cases.
 
+   If BUILD_IDSZ is non-zero then BUILD_ID (of BUILD_IDSZ length) specifies
+   required build-id of the file.
+
    Call file_location_is_valid on returned file_location to check
    whether this function has succeeded.  */
 
@@ -1017,7 +1025,8 @@ openp_bfd (const char *path, enum openp_flags opts, const char *string)
     >>>>  eg executable, non-directory.  */
 
 struct file_location
-openp_file (const char *path, enum openp_flags opts, const char *string)
+openp_file (const char *path, enum openp_flags opts, const char *string,
+	    size_t build_idsz, const gdb_byte *build_id)
 {
   int fd;
   char *filename;
@@ -1055,7 +1064,8 @@ openp_file (const char *path, enum openp_flags opts, const char *string)
 	{
 	  filename = alloca (strlen (string) + 1);
 	  strcpy (filename, string);
-	  file = file_location_from_filename (filename, opts);
+	  file = file_location_from_filename (filename, opts, build_idsz,
+					      build_id);
 	  if (file_location_is_valid (&file))
 	    return file;
 	  file_location_free (&file);
@@ -1152,7 +1162,8 @@ openp_file (const char *path, enum openp_flags opts, const char *string)
 
       if (is_target_filename (filename) || is_regular_file (filename))
 	{
-	  file = file_location_from_filename (filename, opts);
+	  file = file_location_from_filename (filename, opts, build_idsz,
+					      build_id);
 	  if (file_location_is_valid (&file))
 	    {
 	      do_cleanups (back_to);
@@ -1181,12 +1192,13 @@ openp_file (const char *path, enum openp_flags opts, const char *string)
 
    Else, this functions returns 0, and FULL_PATHNAME is set to NULL.  */
 int
-source_full_path_of (const char *filename, char **full_pathname)
+source_full_path_of (const char *filename, size_t build_idsz,
+		     const gdb_byte *build_id, char **full_pathname)
 {
   int fd;
 
   fd = openp (source_path, OPF_TRY_CWD_FIRST | OPF_SEARCH_IN_PATH,
-	      filename, full_pathname);
+	      filename, build_idsz, build_id, full_pathname);
   if (fd < 0)
     {
       *full_pathname = NULL;
@@ -1361,7 +1373,8 @@ find_and_open_source (const char *filename,
     }
 
   gdb_assert (OPEN_MODE == (O_RDONLY | O_BINARY));
-  result = openp (path, OPF_SEARCH_IN_PATH, filename, fullname);
+  result = openp (path, OPF_SEARCH_IN_PATH, filename, 0 /* build_idsz */,
+		  NULL /* build_id */, fullname);
   if (result < 0)
     {
       /* Didn't work.  Try using just the basename.  */
@@ -1369,7 +1382,8 @@ find_and_open_source (const char *filename,
       if (p != filename)
 	{
 	  gdb_assert (OPEN_MODE == (O_RDONLY | O_BINARY));
-	  result = openp (path, OPF_SEARCH_IN_PATH, p, fullname);
+	  result = openp (path, OPF_SEARCH_IN_PATH, p, 0 /* build_idsz */,
+			  NULL /* build_id */, fullname);
 	}
     }
 
diff --git a/gdb/source.h b/gdb/source.h
index f511959..e2e2044 100644
--- a/gdb/source.h
+++ b/gdb/source.h
@@ -140,8 +140,9 @@ extern void file_location_free (struct file_location *file);
 
 extern int file_location_is_valid (const struct file_location *file);
 
-extern struct file_location file_location_from_filename (const char *filename,
-							 enum openp_flags opts);
+extern struct file_location
+  file_location_from_filename (const char *filename, enum openp_flags opts,
+			       size_t build_idsz, const gdb_byte *build_id);
 
 extern bfd *file_location_to_bfd (struct file_location file);
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 26/32] solib_bfd_open: Optimize opening twice
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (22 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 22/32] Add dummy build-id params to prototypes Jan Kratochvil
@ 2015-08-21 21:23 ` Jan Kratochvil
  2015-08-21 21:23 ` [PATCH v12 23/32] build_id_to_bfd: Make it return file_location Jan Kratochvil
                   ` (8 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:23 UTC (permalink / raw)
  To: gdb-patches

Hi,

this is one of the optimizations allowed by file_location that prevents opening
file twice when target build-id is known and it needs to be verified.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* solib.c (solib_bfd_fopen): Replace solib_find and solib_bfd_fopen by
	solib_find_file.
---
 0 files changed

diff --git a/gdb/solib.c b/gdb/solib.c
index a425e4d..906cc5c 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -620,25 +620,30 @@ solib_bfd_fopen (char *pathname, int fd)
 bfd *
 solib_bfd_open (char *pathname, size_t build_idsz, const gdb_byte *build_id)
 {
-  char *found_pathname;
-  int found_file;
+  struct file_location file;
   bfd *abfd;
   const struct bfd_arch_info *b;
 
   /* Search for shared library file.  */
-  found_pathname = solib_find (pathname, build_idsz, build_id, &found_file);
-  if (found_pathname == NULL)
+  file = solib_find_file (pathname, OPF_IS_BFD, build_idsz, build_id);
+  if (!file_location_is_valid (&file))
     {
       /* Return failure if the file could not be found, so that we can
 	 accumulate messages about missing libraries.  */
-      if (errno == ENOENT)
-	return NULL;
+      if (file.file_errno == ENOENT)
+	{
+	  file_location_free (&file);
+	  return NULL;
+	}
 
+      file_location_free (&file);
       perror_with_name (pathname);
     }
 
   /* Open bfd for shared library.  */
-  abfd = solib_bfd_fopen (found_pathname, found_file);
+  gdb_bfd_ref (file.abfd);
+  abfd = file.abfd;
+  file_location_free (&file);
 
   /* Check bfd format.  */
   if (!bfd_check_format (abfd, bfd_object))

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 31/32] Make only user-specified executable and symbol filenames sticky
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (29 preceding siblings ...)
  2015-08-21 21:24 ` [PATCH v12 29/32] testcase: Test also locating shlibs by build-id Jan Kratochvil
@ 2015-08-21 21:24 ` Jan Kratochvil
  2015-08-21 21:24 ` [PATCH v12 30/32] Code cleanup: New hex2bin_allocate() Jan Kratochvil
  2015-09-02  3:57 ` [PATCH v12 00/32] Validate binary before use Doug Evans
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:24 UTC (permalink / raw)
  To: gdb-patches

Message-ID: <559A7C37.6020501@redhat.com>

On 07/03/2015 04:44 PM, Pedro Alves wrote:

> (I still suspect that if we reverse the sense of the flag, then
> its management ends up being more centralized, as then the
> place that sets it is also the place that needs to check it,
> instead of doing that in multiple places.  But, see below.)

It didn't seem fair to impose a subjective preference, so I tried
this in order to understand it myself, and I now agree that is really
doesn't make much difference, as then we'd have to mark
auto-discovered in a few more places that I wasn't originally
seeing.  There's at least the execd handling in infrun.c, and
also spu_symbol_file_add_from_memory.

As I was playing with this already, I poked at the other review
points I made, and came up with the variant of the patch below.

> This function is called while the passed in PID is not the
> current inferior.  E.g., the remote_add_inferior path.
>
> Therefore seems to me that these symbol_file_add_main / exec_file_attach
> calls can change the symbols of the wrong inferior.

...

> I also notice that reread_symbols has an exec_file_attach
> call which seems to me results in losing the is_user_supplied
> flag if the executable's timestamp changed, at least here:
>
>> +  /* Attempt to open the file that was executed to create this
>> +     inferior.  If the user has explicitly specified executable
>> +     and/or symbol files then warn the user if their choices do
>> +     not match.  Otherwise, set exec_file and symfile_objfile to
>> +     the new file.  */
>> +  exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
>> +
>> +  if (exec_file_is_user_supplied)
>>      {
>>        reopen_exec_file ();
>>        reread_symbols ();
>
>
> I also notice that the clone-inferior command ends up with
> an exec_file_attach call in clone_program_space.  That one
> should probably be setting the is_user_supplied flag too,
> I'd think.  Or at least, copying it from the original.
>
> At this point, I'm wondering about adding a parameter to
> exec_file_attach to force considering (now and in future)
> the right value to put in the flag in each case.

I tried this too (see patch below).  As this requires touching the user-supplied
paths anyway, it didn't really matter to tag files user-supplied or
auto-discovered, so I reverted back to user-supplied.  For symbols,
we already have the add_flags, so I added SYMFILE_USER_SUPPLIED instead
of a new boolean.

>
>> @@ -2490,11 +2490,14 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
>>    inferior = current_inferior ();
>>    inferior->control.stop_soon = NO_STOP_QUIETLY;
>>
>> -  /* If no exec file is yet known, try to determine it from the
>> -     process itself.  */
>> -  if (get_exec_file (0) == NULL)
>> -    exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
>> -  else
>> +  /* Attempt to open the file that was executed to create this
>> +     inferior.  If the user has explicitly specified executable
>> +     and/or symbol files then warn the user if their choices do
>> +     not match.  Otherwise, set exec_file and symfile_objfile to
>> +     the new file.  */
>> +  exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
>> +
>> +  if (exec_file_is_user_supplied)
>>      {
>>        reopen_exec_file ();
>>        reread_symbols ();
>
> It seems to me that we should be able to move these reopen/reread
> calls inside exec_file_locate_attach.

I did this too.

What do you think of the version below?

I also tweaked the warnings a bit, to explicitly say "mismatch".

This would still need docs/NEWS changes, and a test would be good too.

----------

- pass user-supplied / auto-discovered as arguments to exec_file_attach and
  symbol_file_add_main

- Change exec_file_locate_attach parameter from pid to inferior
  pointer.

- Flip current program space temporarily to make sure we add/reload
  symbols to/of the right inferior/program space.

- Move reopen_exec_file and reread_symbols calls inside
  exec_file_locate_attach.

- Warning message tweaks.

- Rename exec_file_locate_attach -> exec_file_and_symbols_resync
---
 0 files changed

diff --git a/gdb/corefile.c b/gdb/corefile.c
index 5246f71..5d861de 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -146,7 +146,7 @@ reopen_exec_file (void)
   res = stat (filename, &st);
 
   if (exec_bfd_mtime && exec_bfd_mtime != st.st_mtime)
-    exec_file_attach (filename, 0);
+    exec_file_attach (exec_file_was_user_supplied, filename, 0);
   else
     /* If we accessed the file since last opening it, close it now;
        this stops GDB from holding the executable open after it
diff --git a/gdb/exec.c b/gdb/exec.c
index 0593478..056516b 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -78,7 +78,7 @@ static void
 exec_open (const char *args, int from_tty)
 {
   target_preopen (from_tty);
-  exec_file_attach (args, from_tty);
+  exec_file_attach (1, args, from_tty);
 }
 
 /* Close and clear exec_bfd.  If we end up with no target sections to
@@ -102,6 +102,7 @@ exec_close (void)
 
       xfree (exec_filename);
       exec_filename = NULL;
+      exec_file_was_user_supplied = 0;
     }
 }
 
@@ -138,42 +139,70 @@ exec_file_clear (int from_tty)
 /* See gdbcore.h.  */
 
 void
-exec_file_locate_attach (int pid, int from_tty)
+exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
 {
   char *exec_file, *full_exec_path = NULL;
+  struct cleanup *old_chain = save_current_program_space ();
 
-  /* Do nothing if we already have an executable filename.  */
-  exec_file = (char *) get_exec_file (0);
-  if (exec_file != NULL)
-    return;
+  /* Switch over temporarily, while reading executable and
+     symbols.  */
+  set_current_program_space (inf->pspace);
 
   /* Try to determine a filename from the process itself.  */
-  exec_file = target_pid_to_exec_file (pid);
-  if (exec_file == NULL)
-    return;
+  exec_file = target_pid_to_exec_file (inf->pid);
+  if (exec_file != NULL)
+    {
+      /* If gdb_sysroot is not empty and the discovered filename
+	 is absolute then prefix the filename with gdb_sysroot.  */
+      if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file))
+	full_exec_path = exec_file_find (exec_file, 0 /* build_idsz */,
+					 NULL /* build_id */, NULL);
+
+      if (full_exec_path == NULL)
+	{
+	  /* It's possible we don't have a full path, but rather just a
+	     filename.  Some targets, such as HP-UX, don't provide the
+	     full path, sigh.
+
+	     Attempt to qualify the filename against the source path.
+	     (If that fails, we'll just fall back on the original
+	     filename.  Not much more we can do...)  */
+	  if (!source_full_path_of (exec_file, 0 /* build_idsz */,
+				    NULL /* build_id */, &full_exec_path))
+	    full_exec_path = xstrdup (exec_file);
+	}
+    }
 
-  /* If gdb_sysroot is not empty and the discovered filename
-     is absolute then prefix the filename with gdb_sysroot.  */
-  if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file))
-    full_exec_path = exec_file_find (exec_file, 0 /* build_idsz */,
-				     NULL /* build_id */, NULL);
+  if (exec_filename != NULL && exec_file_was_user_supplied)
+    {
+      if (full_exec_path != NULL && strcmp (full_exec_path, exec_filename) != 0)
+	warning (_("Detected exec-file mismatch on %s.  Running %s; Loaded %s"),
+		 target_pid_to_str (pid_to_ptid (inf->pid)),
+		 full_exec_path, exec_filename);
+      reopen_exec_file ();
+    }
+  else if (full_exec_path != NULL)
+    exec_file_attach (0, full_exec_path, from_tty);
 
-  if (full_exec_path == NULL)
+  if (symfile_objfile != NULL && symfile_objfile_was_user_supplied)
     {
-      /* It's possible we don't have a full path, but rather just a
-	 filename.  Some targets, such as HP-UX, don't provide the
-	 full path, sigh.
-
-	 Attempt to qualify the filename against the source path.
-	 (If that fails, we'll just fall back on the original
-	 filename.  Not much more we can do...)  */
-      if (!source_full_path_of (exec_file, 0 /* build_idsz */,
-				NULL /* build_id */, &full_exec_path))
-	full_exec_path = xstrdup (exec_file);
+      const char *symbol_filename = objfile_filename (symfile_objfile);
+
+      if (full_exec_path != NULL
+	  && strcmp (full_exec_path, symbol_filename) != 0)
+	warning (_("Detected symbol-file mismatch on %s.  "
+		   "Running %s; Loaded %s"),
+		 target_pid_to_str (pid_to_ptid (inf->pid)),
+		 full_exec_path, symbol_filename);
     }
+  else if (full_exec_path != NULL)
+    symbol_file_add_main (0, full_exec_path, from_tty);
 
-  exec_file_attach (full_exec_path, from_tty);
-  symbol_file_add_main (full_exec_path, from_tty);
+  /* Re-read symbol files that were modified since we last loaded
+     them.  */
+  reread_symbols ();
+
+  do_cleanups (old_chain);
 }
 
 /* Set FILENAME as the new exec file.
@@ -194,7 +223,7 @@ exec_file_locate_attach (int pid, int from_tty)
    we're supplying the exec pathname late for good reason.)  */
 
 void
-exec_file_attach (const char *filename, int from_tty)
+exec_file_attach (int user_supplied, const char *filename, int from_tty)
 {
   struct cleanup *cleanups;
 
@@ -283,6 +312,8 @@ exec_file_attach (const char *filename, int from_tty)
 
   do_cleanups (cleanups);
 
+  exec_file_was_user_supplied = user_supplied;
+
   bfd_cache_close_all ();
   observer_notify_executable_changed ();
 }
@@ -324,12 +355,12 @@ exec_file_command (char *args, int from_tty)
 
       filename = tilde_expand (*argv);
       make_cleanup (xfree, filename);
-      exec_file_attach (filename, from_tty);
+      exec_file_attach (1, filename, from_tty);
 
       do_cleanups (cleanups);
     }
   else
-    exec_file_attach (NULL, from_tty);
+    exec_file_attach (1, NULL, from_tty);
 }
 
 /* Set both the exec file and the symbol file, in one command.
diff --git a/gdb/exec.h b/gdb/exec.h
index c7f3b56..aef2926 100644
--- a/gdb/exec.h
+++ b/gdb/exec.h
@@ -32,6 +32,8 @@ struct objfile;
 #define exec_bfd current_program_space->ebfd
 #define exec_bfd_mtime current_program_space->ebfd_mtime
 #define exec_filename current_program_space->pspace_exec_filename
+#define exec_file_was_user_supplied \
+  current_program_space->pspace_exec_file_was_user_supplied
 
 /* Builds a section table, given args BFD, SECTABLE_PTR, SECEND_PTR.
    Returns 0 if OK, 1 on error.  */
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
index 0c08b37..f34ee77 100644
--- a/gdb/gdbcore.h
+++ b/gdb/gdbcore.h
@@ -146,14 +146,23 @@ extern int write_files;
 
 extern void core_file_command (char *filename, int from_tty);
 
-extern void exec_file_attach (const char *filename, int from_tty);
-
-/* If the filename of the main executable is unknown, attempt to
-   determine it.  If a filename is determined, proceed as though
-   it was just specified with the "file" command.  Do nothing if
-   the filename of the main executable is already known.  */
-
-extern void exec_file_locate_attach (int pid, int from_tty);
+extern void exec_file_attach (int user_supplied, const char *filename,
+			      int from_tty);
+
+/* Resync executable and symbols.  Fetch the filename of the main
+   executable based on what the target is running.  If a filename can
+   be determined, and the current exec file loaded was not previously
+   user supplied, then load the discovered filename as exec file.  If
+   the executable loaded had been user supplied (with e.g., the "file"
+   command), issue a warning if there's a mismatch, and reload the
+   previously user-specified executable (in case the program was
+   recompiled since the last time we loaded it).  Likewise, if the
+   currenly load main symbol file was not user supplied, load the
+   discovered filename as symbol file; otherwise, if there's a
+   mismatch, warn.  End by reading all symbol files that have been
+   modified since the last time we loaded them.  */
+
+extern void exec_file_and_symbols_resync (struct inferior *inf, int from_tty);
 
 extern void exec_file_clear (int from_tty);
 
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 82399a4..b6d9474 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2492,15 +2492,12 @@ attach_command_post_wait (char *args, int from_tty, int async_exec)
   inferior = current_inferior ();
   inferior->control.stop_soon = NO_STOP_QUIETLY;
 
-  /* If no exec file is yet known, try to determine it from the
-     process itself.  */
-  if (get_exec_file (0) == NULL)
-    exec_file_locate_attach (ptid_get_pid (inferior_ptid), from_tty);
-  else
-    {
-      reopen_exec_file ();
-      reread_symbols ();
-    }
+  /* Attempt to open the file that was executed to create this
+     inferior.  If the user has explicitly specified executable
+     and/or symbol files then warn the user if their choices do
+     not match.  Otherwise, set exec_file and symfile_objfile to
+     the new file.  */
+  exec_file_and_symbols_resync (inferior, from_tty);
 
   /* Take any necessary post-attaching actions for this platform.  */
   target_post_attach (ptid_get_pid (inferior_ptid));
diff --git a/gdb/inferior.c b/gdb/inferior.c
index 2e44f17..ec667ce 100644
--- a/gdb/inferior.c
+++ b/gdb/inferior.c
@@ -869,13 +869,13 @@ add_inferior_command (char *args, int from_tty)
       if (exec != NULL)
 	{
 	  /* Switch over temporarily, while reading executable and
-	     symbols.q.  */
+	     symbols.  */
 	  set_current_program_space (inf->pspace);
 	  set_current_inferior (inf);
 	  switch_to_thread (null_ptid);
 
-	  exec_file_attach (exec, from_tty);
-	  symbol_file_add_main (exec, from_tty);
+	  exec_file_attach (1, exec, from_tty);
+	  symbol_file_add_main (SYMFILE_USER_SPECIFIED, exec, from_tty);
 	}
     }
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c1beafd..ff00e18 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1212,7 +1212,7 @@ follow_exec (ptid_t ptid, char *execd_pathname)
   gdb_assert (current_program_space == inf->pspace);
 
   /* That a.out is now the one to use.  */
-  exec_file_attach (execd_pathname, 0);
+  exec_file_attach (0, execd_pathname, 0);
 
   /* SYMFILE_DEFER_BP_RESET is used as the proper displacement for PIE
      (Position Independent Executable) main symbol file will get applied by
diff --git a/gdb/main.c b/gdb/main.c
index a17ee34..3cc3d47 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -405,6 +405,29 @@ catch_command_errors_const (catch_command_errors_const_ftype *command,
   return 1;
 }
 
+/* Like catch_command_errors, but specifically for symbol/exec load
+   routines.  */
+
+typedef void (catch_exec_or_symbol_errors_ftype) (int, const char *, int);
+
+static int
+catch_exec_or_symbol_errors (catch_exec_or_symbol_errors_ftype *func,
+			     int arg, const char *filename, int from_tty)
+{
+  TRY
+    {
+      func (arg, filename, from_tty);
+    }
+  CATCH (e, RETURN_MASK_ALL)
+    {
+      exception_print (gdb_stderr, e);
+      return 0;
+    }
+  END_CATCH
+
+  return 1;
+}
+
 /* Type of this option.  */
 enum cmdarg_kind
 {
@@ -1051,20 +1074,23 @@ captured_main (void *data)
     {
       /* The exec file and the symbol-file are the same.  If we can't
          open it, better only print one error message.
-         catch_command_errors returns non-zero on success!  */
-      if (catch_command_errors_const (exec_file_attach, execarg,
-				      !batch_flag))
-	catch_command_errors_const (symbol_file_add_main, symarg,
-				    !batch_flag);
+         catch_exec_or_symbol_errors returns non-zero on success.  */
+      if (catch_exec_or_symbol_errors (exec_file_attach,
+				       1, execarg, !batch_flag))
+	catch_exec_or_symbol_errors (symbol_file_add_main,
+				     SYMFILE_USER_SPECIFIED,
+				     symarg, !batch_flag);
     }
   else
     {
       if (execarg != NULL)
-	catch_command_errors_const (exec_file_attach, execarg,
-				    !batch_flag);
+	catch_exec_or_symbol_errors (exec_file_attach, 1,
+				     execarg, !batch_flag);
+
       if (symarg != NULL)
-	catch_command_errors_const (symbol_file_add_main, symarg,
-				    !batch_flag);
+	catch_exec_or_symbol_errors (symbol_file_add_main,
+				     SYMFILE_USER_SPECIFIED,
+				     symarg, !batch_flag);
     }
 
   if (corearg && pidarg)
diff --git a/gdb/progspace.c b/gdb/progspace.c
index ea2f8ec..1b3f689 100644
--- a/gdb/progspace.c
+++ b/gdb/progspace.c
@@ -182,10 +182,11 @@ clone_program_space (struct program_space *dest, struct program_space *src)
   set_current_program_space (dest);
 
   if (src->pspace_exec_filename != NULL)
-    exec_file_attach (src->pspace_exec_filename, 0);
+    exec_file_attach (1, src->pspace_exec_filename, 0);
 
   if (src->symfile_object_file != NULL)
-    symbol_file_add_main (objfile_name (src->symfile_object_file), 0);
+    symbol_file_add_main (SYMFILE_USER_SPECIFIED,
+			  objfile_name (src->symfile_object_file), 0);
 
   do_cleanups (old_chain);
   return dest;
diff --git a/gdb/progspace.h b/gdb/progspace.h
index 48f206e..01fd9a3 100644
--- a/gdb/progspace.h
+++ b/gdb/progspace.h
@@ -154,6 +154,12 @@ struct program_space
        It needs to be freed by xfree.  It is not NULL iff EBFD is not NULL.  */
     char *pspace_exec_filename;
 
+    /* Nonzero if pspace_exec_filename was supplied by the user,
+       either at startup (on the command-line) or via the "file" or
+       "add-inferior -exec" commands.  Zero if pspace_exec_filename is
+       unset or was discovered by GDB.  */
+    int pspace_exec_file_was_user_supplied;
+
     /* The address space attached to this program space.  More than one
        program space may be bound to the same address space.  In the
        traditional unix-like debugging scenario, this will usually
@@ -183,6 +189,12 @@ struct program_space
        (e.g. the argument to the "symbol-file" or "file" command).  */
     struct objfile *symfile_object_file;
 
+    /* Nonzero if symfile_object_file is set and was discovered by
+       GDB.  Zero if symfile_object_file is not set or was supplied
+       by the user, either at startup (on the command-line) or via the
+       "file" or "add-inferior -exec" commands.  */
+    int symfile_object_file_was_user_supplied;
+
     /* All known objfiles are kept in a linked list.  This points to
        the head of this list.  */
     struct objfile *objfiles;
@@ -215,6 +227,11 @@ struct program_space
 
 #define symfile_objfile current_program_space->symfile_object_file
 
+/* See program_space->symfile_object_file_was_user_supplied.  */
+
+#define symfile_objfile_was_user_supplied \
+  current_program_space->symfile_object_file_was_user_supplied
+
 /* All known objfiles are kept in a linked list.  This points to the
    root of this list.  */
 #define object_files current_program_space->objfiles
diff --git a/gdb/remote.c b/gdb/remote.c
index 12294bc..e2befcf 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -1673,10 +1673,13 @@ remote_add_inferior (int fake_pid_p, int pid, int attached,
   inf->attach_flag = attached;
   inf->fake_pid_p = fake_pid_p;
 
-  /* If no main executable is currently open then attempt to
-     open the file that was executed to create this inferior.  */
-  if (try_open_exec && get_exec_file (0) == NULL)
-    exec_file_locate_attach (pid, 1);
+  /* Attempt to open the file that was executed to create this
+     inferior.  If the user has explicitly specified executable
+     and/or symbol files then warn the user if their choices do
+     not match.  Otherwise, set exec_file and symfile_objfile to
+     the new file.  */
+  if (try_open_exec)
+    exec_file_and_symbols_resync (inf, 1);
 
   return inf;
 }
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index c725683..858b942 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1071,7 +1071,7 @@ open_symbol_file_object (void *from_ttyp)
     }
 
   /* Have a pathname: read the symbol file.  */
-  symbol_file_add_main (filename, from_tty);
+  symbol_file_add_main (0, filename, from_tty);
 
   do_cleanups (cleanups);
   return 1;
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 1e34c5f..38fd3f1 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -85,7 +85,8 @@ int readnow_symbol_files;	/* Read full symbols immediately.  */
 
 static void load_command (char *, int);
 
-static void symbol_file_add_main_1 (const char *args, int from_tty, int flags);
+static void symbol_file_add_main_1 (int add_flags, const char *args,
+				    int from_tty, int flags);
 
 static void add_symbol_file_command (char *, int);
 
@@ -1306,16 +1307,17 @@ symbol_file_add (const char *name, int add_flags,
    command itself.  */
 
 void
-symbol_file_add_main (const char *args, int from_tty)
+symbol_file_add_main (int add_flags, const char *args, int from_tty)
 {
-  symbol_file_add_main_1 (args, from_tty, 0);
+  symbol_file_add_main_1 (add_flags, args, from_tty, 0);
 }
 
 static void
-symbol_file_add_main_1 (const char *args, int from_tty, int flags)
+symbol_file_add_main_1 (int add_flags, const char *args, int from_tty,
+			int flags)
 {
-  const int add_flags = (current_inferior ()->symfile_flags
-			 | SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0));
+  add_flags |= (current_inferior ()->symfile_flags
+		| SYMFILE_MAINLINE | (from_tty ? SYMFILE_VERBOSE : 0));
 
   symbol_file_add (args, add_flags, NULL, flags);
 
@@ -1325,6 +1327,9 @@ symbol_file_add_main_1 (const char *args, int from_tty, int flags)
 
   if ((flags & SYMFILE_NO_READ) == 0)
     set_initial_language ();
+
+  symfile_objfile_was_user_supplied
+    = (add_flags & SYMFILE_USER_SPECIFIED) != 0;
 }
 
 void
@@ -1347,6 +1352,8 @@ symbol_file_clear (int from_tty)
   gdb_assert (symfile_objfile == NULL);
   if (from_tty)
     printf_unfiltered (_("No symbol file now.\n"));
+
+  symfile_objfile_was_user_supplied = 0;
 }
 
 static int
@@ -1663,7 +1670,8 @@ symbol_file_command (char *args, int from_tty)
 	    error (_("unknown option `%s'"), *argv);
 	  else
 	    {
-	      symbol_file_add_main_1 (*argv, from_tty, flags);
+	      symbol_file_add_main_1 (SYMFILE_USER_SPECIFIED,
+				      *argv, from_tty, flags);
 	      name = *argv;
 	    }
 
@@ -2527,7 +2535,8 @@ reread_symbols (void)
 	    {
 	      /* Reload EXEC_BFD without asking anything.  */
 
-	      exec_file_attach (bfd_get_filename (objfile->obfd), 0);
+	      exec_file_attach (exec_file_was_user_supplied,
+				bfd_get_filename (objfile->obfd), 0);
 	    }
 
 	  /* Keep the calls order approx. the same as in free_objfile.  */
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 9ef3f0b..9ef3d19 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -457,7 +457,11 @@ enum symfile_add_flags
 
     /* Do not immediately read symbols for this file.  By default,
        symbols are read when the objfile is created.  */
-    SYMFILE_NO_READ = 1 << 4
+    SYMFILE_NO_READ = 1 << 4,
+
+    /* Whether the symbol file was user-supplied, as opposed to
+       auto-discovered by GDB.  */
+    SYMFILE_USER_SPECIFIED = 1 << 5,
   };
 
 extern struct objfile *symbol_file_add (const char *, int,
@@ -556,7 +560,8 @@ extern CORE_ADDR overlay_unmapped_address (CORE_ADDR, struct obj_section *);
 extern CORE_ADDR symbol_overlayed_address (CORE_ADDR, struct obj_section *);
 
 /* Load symbols from a file.  */
-extern void symbol_file_add_main (const char *args, int from_tty);
+extern void symbol_file_add_main (int add_flags,
+				  const char *args, int from_tty);
 
 /* Clear GDB symbol tables.  */
 extern void symbol_file_clear (int from_tty);

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 30/32] Code cleanup: New hex2bin_allocate()
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (30 preceding siblings ...)
  2015-08-21 21:24 ` [PATCH v12 31/32] Make only user-specified executable and symbol filenames sticky Jan Kratochvil
@ 2015-08-21 21:24 ` Jan Kratochvil
  2015-09-02  3:57 ` [PATCH v12 00/32] Validate binary before use Doug Evans
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:24 UTC (permalink / raw)
  To: gdb-patches

Hi,

make hex->bin parsing standalone, to be reused in later patch.


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* solib-svr4.c (hex2bin_allocate): New function from ...
	(library_list_start_library): ... here, call it.
---
 0 files changed

diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 8739c31..c725683 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -1160,6 +1160,47 @@ svr4_copy_library_list (struct so_list *src)
 
 #include "xml-support.h"
 
+/* Conver text hexadecimal representation HEX into its binary form,
+   store it to newly allocated memory *BINP sized *BINSZP.  For errors
+   reporting use FILENAME.  */
+
+static void
+hex2bin_allocate (const char *hex, gdb_byte **binp, size_t *binszp,
+		  const char *filename)
+{
+  size_t hex_len, binsz;
+
+  if (hex == NULL)
+    return;
+  hex_len = strlen (hex);
+  if (hex_len == 0)
+    {
+      warning (_("Shared library \"%s\" received empty build-id "
+		 "from gdbserver"), filename);
+      return;
+    }
+  if ((hex_len & 1U) != 0)
+    {
+      warning (_("Shared library \"%s\" received odd number "
+		 "of build-id \"%s\" hex characters from gdbserver"),
+	       filename, hex);
+      return;
+    }
+  binsz = hex_len / 2;
+  *binp = xmalloc (binsz);
+  *binszp = hex2bin (hex, *binp, binsz);
+  if (*binszp != binsz)
+    {
+      warning (_("Shared library \"%s\" received invalid "
+		 "build-id \"%s\" hex character at encoded byte "
+		 "position %s (first as 0) from gdbserver"),
+	       filename, hex, pulongest (*binszp));
+      xfree (*binp);
+      *binp = NULL;
+      *binszp = 0;
+    }
+}
+
 /* Handle the start of a <library> element.  Note: new elements are added
    at the tail of the list, keeping the list in order.  */
 
@@ -1187,37 +1228,8 @@ library_list_start_library (struct gdb_xml_parser *parser,
   strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1);
   new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0;
   strcpy (new_elem->so_original_name, new_elem->so_name);
-  if (hex_build_id != NULL)
-    {
-      const size_t hex_build_id_len = strlen (hex_build_id);
-
-      if (hex_build_id_len == 0)
-	warning (_("Shared library \"%s\" received empty build-id "
-	           "from gdbserver"), new_elem->so_original_name);
-      else if ((hex_build_id_len & 1U) != 0)
-	warning (_("Shared library \"%s\" received odd number "
-		   "of build-id \"%s\" hex characters from gdbserver"),
-		 new_elem->so_original_name, hex_build_id);
-      else
-	{
-	  const size_t build_idsz = hex_build_id_len / 2;
-
-	  new_elem->build_id = xmalloc (build_idsz);
-	  new_elem->build_idsz = hex2bin (hex_build_id, new_elem->build_id,
-					  build_idsz);
-	  if (new_elem->build_idsz != build_idsz)
-	    {
-	      warning (_("Shared library \"%s\" received invalid "
-			 "build-id \"%s\" hex character at encoded byte "
-			 "position %s (first as 0) from gdbserver"),
-		       new_elem->so_original_name, hex_build_id,
-		       pulongest (new_elem->build_idsz));
-	      xfree (new_elem->build_id);
-	      new_elem->build_id = NULL;
-	      new_elem->build_idsz = 0;
-	    }
-	}
-    }
+  hex2bin_allocate (hex_build_id, &new_elem->build_id, &new_elem->build_idsz,
+		    new_elem->so_original_name);
 
   *list->tailp = new_elem;
   list->tailp = &new_elem->next;

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 29/32] testcase: Test also locating shlibs by build-id
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (28 preceding siblings ...)
  2015-08-21 21:24 ` [PATCH v12 32/32] Support build-id for main executables Jan Kratochvil
@ 2015-08-21 21:24 ` Jan Kratochvil
  2015-08-21 21:24 ` [PATCH v12 31/32] Make only user-specified executable and symbol filenames sticky Jan Kratochvil
                   ` (2 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:24 UTC (permalink / raw)
  To: gdb-patches

Hi,

testcase from the previous patch tests verification of build-id in shared
libraries found by their name.  This test adds testing that a library can be
found by its build-id (debug-file-directory/.build-id/XX/YYYYY...YYYYY).


Jan


gdb/testsuite/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/solib-mismatch.exp (nocrlf, expected_header): Make them
	global.
	(solib_locate_test): New function.
---
 gdb/testsuite/gdb.base/solib-mismatch.exp |   46 ++++++++++++++++++++++++++++-
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/gdb/testsuite/gdb.base/solib-mismatch.exp b/gdb/testsuite/gdb.base/solib-mismatch.exp
index 4983429..4ae8ac8 100644
--- a/gdb/testsuite/gdb.base/solib-mismatch.exp
+++ b/gdb/testsuite/gdb.base/solib-mismatch.exp
@@ -59,6 +59,10 @@ set binlibfilegdb ${binlibfiledirgdb}/${binlibfilebase}
 set srcfile ${testfile}.c
 set executable ${testfile}
 
+# Pattern matching for 'info sharedlibrary'.
+set nocrlf "\[^\r\n\]*"
+set expected_header "From${nocrlf}To${nocrlf}Syms${nocrlf}Read${nocrlf}Shared${nocrlf}"
+
 file delete -force -- "${binlibfiledirrun}"
 file mkdir "${binlibfiledirrun}"
 
@@ -91,6 +95,8 @@ proc solib_matching_test { solibfile symsloaded } {
   global binlibfiledirrun
   global binlibfiledirgdb
   global srcfile
+  global expected_header
+  global nocrlf
 
   clean_restart ${binlibfiledirrun}/${executable}
 
@@ -110,8 +116,6 @@ proc solib_matching_test { solibfile symsloaded } {
 
   gdb_test "sharedlibrary" "" ""
 
-  set nocrlf "\[^\r\n\]*"
-  set expected_header "From${nocrlf}To${nocrlf}Syms${nocrlf}Read${nocrlf}Shared${nocrlf}"
   set expected_line "${symsloaded}${nocrlf}${solibfile}"
 
   gdb_test "info sharedlibrary ${solibfile}" \
@@ -121,6 +125,23 @@ proc solib_matching_test { solibfile symsloaded } {
   return 0
 }
 
+proc solib_locate_test { solibfile symsloaded } {
+  global binlibfiledirrun
+  global binlibfilerun
+  global nocrlf
+  global expected_header
+
+  gdb_test_no_output "set debug-file-directory ${binlibfiledirrun}" ""
+  gdb_test_no_output "nosharedlibrary" ""
+  gdb_test "sharedlibrary" "" ""
+
+  set expected_line "${symsloaded}${nocrlf}${solibfile}"
+
+  gdb_test "info sharedlibrary ${solibfile}" \
+    "${expected_header}\r\n.*${expected_line}.*" \
+    "Symbols for ${solibfile} loaded: expected '${symsloaded}'"
+}
+
 # Copy binary to working dir so it pulls in the library from that dir
 # (by the virtue of $ORIGIN).
 file copy -force "${binlibfiledirgdb}/${executable}" \
@@ -144,9 +165,30 @@ with_test_prefix "test --only-keep-debug" {
   solib_matching_test "${binlibfilebase}" "No"
 }
 
+# Test locating file by its build-id - if the regular filename does not match.
+# build-id file has to be a symlink - otherwise so_list->so_name shown in 'info
+# sharedlibrary' would contain the build-id hash and not the library name.
+set build_id_debug_relative [build_id_debug_filename_get $binlibfilerun]
+if { ![regexp {^(.*)\.debug$} $build_id_debug_relative trash build_id_relative] } {
+    fail "strip debug $build_id_debug_relative"
+    return
+}
+set build_id_filename "${binlibfiledirrun}/$build_id_relative"
+file mkdir [file dirname $build_id_filename]
+remote_exec host "ln -sf $binlibfilerun $build_id_filename"
+with_test_prefix "locate non-matching shared library" {
+  solib_locate_test "${binlibfilebase}" "Yes"
+}
+
 # Keep previous so for debugging puroses
 file copy -force "${binlibfilegdb}" "${binlibfilegdb}-orig1"
 
+# Test locating file by its build-id - if the regular filename does not exist.
+file delete -force "${binlibfilegdb}"
+with_test_prefix "locate non-existing shared library" {
+  solib_locate_test "${binlibfilebase}" "Yes"
+}
+
 # Copy loaded so over the one gdb will find
 file copy -force "${binlibfilerun}" "${binlibfilegdb}"
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 28/32] Tests for validate symbol file using build-id
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (26 preceding siblings ...)
  2015-08-21 21:23 ` [PATCH v12 24/32] solib_find: Search also by build-id Jan Kratochvil
@ 2015-08-21 21:24 ` Jan Kratochvil
  2015-08-21 21:24 ` [PATCH v12 32/32] Support build-id for main executables Jan Kratochvil
                   ` (4 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:24 UTC (permalink / raw)
  To: gdb-patches

Hi,

new testcase only.

Jan


gdb/testsuite/ChangeLog
2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com

	Tests for validate symbol file using build-id.
	* gdb.base/solib-mismatch-lib.c: New file.
	* gdb.base/solib-mismatch-libmod.c: New file.
	* gdb.base/solib-mismatch.c: New file.
	* gdb.base/solib-mismatch.exp: New file.
---
 gdb/testsuite/gdb.base/solib-mismatch-lib.c    |   30 +++++
 gdb/testsuite/gdb.base/solib-mismatch-libmod.c |   30 +++++
 gdb/testsuite/gdb.base/solib-mismatch.c        |   56 +++++++++
 gdb/testsuite/gdb.base/solib-mismatch.exp      |  156 ++++++++++++++++++++++++
 4 files changed, 272 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch-lib.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch-libmod.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch.c
 create mode 100644 gdb/testsuite/gdb.base/solib-mismatch.exp

diff --git a/gdb/testsuite/gdb.base/solib-mismatch-lib.c b/gdb/testsuite/gdb.base/solib-mismatch-lib.c
new file mode 100644
index 0000000..508ebbd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-mismatch-lib.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   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/>.  */
+
+int _bar = 42;
+
+int
+bar (void)
+{
+  return _bar + 21;
+}
+
+int
+foo (void)
+{
+  return _bar;
+}
diff --git a/gdb/testsuite/gdb.base/solib-mismatch-libmod.c b/gdb/testsuite/gdb.base/solib-mismatch-libmod.c
new file mode 100644
index 0000000..aebcdb5
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-mismatch-libmod.c
@@ -0,0 +1,30 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   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/>.  */
+
+int _bar = 21;
+
+int
+bar (void)
+{
+  return 42 - _bar;
+}
+
+int
+foo (void)
+{
+  return 24 + bar();
+}
diff --git a/gdb/testsuite/gdb.base/solib-mismatch.c b/gdb/testsuite/gdb.base/solib-mismatch.c
new file mode 100644
index 0000000..f739f3b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-mismatch.c
@@ -0,0 +1,56 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+/* The following defines must correspond to solib-mismatch.exp .  */
+
+/* DIRNAME and LIB must be defined at compile time.  */
+#ifndef DIRNAME
+# error DIRNAME not defined
+#endif
+#ifndef LIB
+# error LIB not defined
+#endif
+
+int
+main (int argc, char *argv[])
+{
+  void *h;
+  int (*foo) (void);
+
+  if (chdir (DIRNAME) != 0)
+    {
+      printf ("ERROR - Could not cd to %s\n", DIRNAME);
+      return 1;
+    }
+
+  h = dlopen (LIB, RTLD_NOW);
+
+  if (h == NULL)
+    {
+      printf ("ERROR - could not open lib %s\n", LIB);
+      return 1;
+    }
+  foo = dlsym (h, "foo"); /* set breakpoint 1 here */
+  dlclose (h);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/solib-mismatch.exp b/gdb/testsuite/gdb.base/solib-mismatch.exp
new file mode 100644
index 0000000..4983429
--- /dev/null
+++ b/gdb/testsuite/gdb.base/solib-mismatch.exp
@@ -0,0 +1,156 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# 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/>.  */
+
+standard_testfile
+set executable $testfile
+
+if ![is_remote target] {
+  untested "only gdbserver supports build-id reporting"
+  return -1
+}
+if [is_remote host] {
+  untested "only local host is currently supported"
+  return -1
+}
+
+# Test overview:
+#  generate two shared objects. One that will be used by the process
+#  and another, modified, that will be found by gdb. Gdb should
+#  detect the mismatch and refuse to use mismatched shared object.
+
+if { [get_compiler_info] } {
+  untested "get_compiler_info failed."
+  return -1
+}
+
+# First version of the object, to be loaded by ld.
+set srclibfilerun ${testfile}-lib.c
+
+# Modified version of the object to be loaded by gdb
+# Code in -libmod.c is tuned so it gives a mismatch but
+# leaves .dynamic at the same point.
+set srclibfilegdb ${testfile}-libmod.c
+
+# So file name:
+set binlibfilebase lib${testfile}.so
+
+# Setup run directory (where program is run from)
+#   It contains executable and '-lib' version of the library.
+set binlibfiledirrun [standard_output_file ${testfile}_wd]
+set binlibfilerun ${binlibfiledirrun}/${binlibfilebase}
+
+# Second solib version is in current directory, '-libmod' version.
+set binlibfiledirgdb [standard_output_file ""]
+set binlibfilegdb ${binlibfiledirgdb}/${binlibfilebase}
+
+# Executable
+set srcfile ${testfile}.c
+set executable ${testfile}
+
+file delete -force -- "${binlibfiledirrun}"
+file mkdir "${binlibfiledirrun}"
+
+set exec_opts {}
+
+if { ![istarget "*-*-nto-*"] } {
+  lappend exec_opts "shlib_load"
+}
+
+lappend exec_opts "additional_flags=-DDIRNAME\=\"${binlibfiledirrun}\" -DLIB\=\"./${binlibfilebase}\""
+lappend exec_opts "debug"
+
+if { [build_executable $testfile.exp $executable $srcfile $exec_opts] != 0 } {
+  return -1
+}
+
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfilerun}" "${binlibfilerun}" [list debug ldflags=-Wl,--build-id]] != ""
+     || [gdb_gnu_strip_debug "${binlibfilerun}"]
+     || [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfilegdb}" "${binlibfilegdb}" [list debug ldflags=-Wl,--build-id]] != "" } {
+  untested "compilation failed."
+  return -1
+}
+
+proc solib_matching_test { solibfile symsloaded } {
+  global gdb_prompt
+  global testfile
+  global executable
+  global srcdir
+  global subdir
+  global binlibfiledirrun
+  global binlibfiledirgdb
+  global srcfile
+
+  clean_restart ${binlibfiledirrun}/${executable}
+
+  gdb_test_no_output "set solib-search-path \"${binlibfiledirgdb}\"" ""
+  if { [gdb_test "cd ${binlibfiledirgdb}" "" ""] != 0 } {
+    untested "cd ${binlibfiledirgdb}"
+    return -1
+  }
+
+  # Do not auto load shared libraries, the test needs to have control
+  # over when the relevant output gets printed.
+  gdb_test_no_output "set auto-solib-add off" ""
+
+  if ![runto "${srcfile}:[gdb_get_line_number "set breakpoint 1 here"]"] {
+    return -1
+  }
+
+  gdb_test "sharedlibrary" "" ""
+
+  set nocrlf "\[^\r\n\]*"
+  set expected_header "From${nocrlf}To${nocrlf}Syms${nocrlf}Read${nocrlf}Shared${nocrlf}"
+  set expected_line "${symsloaded}${nocrlf}${solibfile}"
+
+  gdb_test "info sharedlibrary ${solibfile}" \
+    "${expected_header}\r\n.*${expected_line}.*" \
+    "Symbols for ${solibfile} loaded: expected '${symsloaded}'"
+
+  return 0
+}
+
+# Copy binary to working dir so it pulls in the library from that dir
+# (by the virtue of $ORIGIN).
+file copy -force "${binlibfiledirgdb}/${executable}" \
+		 "${binlibfiledirrun}/${executable}"
+
+# Test unstripped, .dynamic matching
+with_test_prefix "test unstripped, .dynamic matching" {
+  solib_matching_test "${binlibfilebase}" "No"
+}
+
+# Keep original so for debugging purposes
+file copy -force "${binlibfilegdb}" "${binlibfilegdb}-orig"
+set objcopy_program [transform objcopy]
+set result [catch "exec $objcopy_program --only-keep-debug ${binlibfilegdb}"]
+if {$result != 0} {
+  untested "test --only-keep-debug (objcopy)"
+}
+
+# Test --only-keep-debug, .dynamic matching so
+with_test_prefix "test --only-keep-debug" {
+  solib_matching_test "${binlibfilebase}" "No"
+}
+
+# Keep previous so for debugging puroses
+file copy -force "${binlibfilegdb}" "${binlibfilegdb}-orig1"
+
+# Copy loaded so over the one gdb will find
+file copy -force "${binlibfilerun}" "${binlibfilegdb}"
+
+# Now test it does not mis-invalidate matching libraries
+with_test_prefix "test matching libraries" {
+  solib_matching_test "${binlibfilebase}" "Yes"
+}

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v12 32/32] Support build-id for main executables
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (27 preceding siblings ...)
  2015-08-21 21:24 ` [PATCH v12 28/32] Tests for validate symbol file using build-id Jan Kratochvil
@ 2015-08-21 21:24 ` Jan Kratochvil
  2015-08-21 21:24 ` [PATCH v12 29/32] testcase: Test also locating shlibs by build-id Jan Kratochvil
                   ` (3 subsequent siblings)
  32 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-21 21:24 UTC (permalink / raw)
  To: gdb-patches

Hi,

make all the existing shlibs build-id functionality working also for the main
executables.

I think target_so_ops::open_symbol_file_object() is already replaced by what
exec_file_and_symbols_resync(), target_pid_to_exec_file() etc. does but
open_symbol_file_object() has been forgotten.

This patch adds target_so_ops::main_build_id() which could be possibly marged
with open_symbol_file_object() but I made it a separate function as I think it
is easier to rather remove target_so_ops::open_symbol_file_object().


Jan


gdb/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* NEWS (Changes since GDB 7.10): Mention also main-build-id.
	* build-id.c (build_id_verify): Add parameter advice.
	* build-id.h (build_id_verify): Likewise.
	* dwarf2read.c (dwarf2_get_dwz_file): Update build_id_verify caller.
	* exec.c: Include build-id.h.
	(exec_file_and_symbols_resync): Detect and use build-id by
	solib_main_build_id.
	* features/library-list-svr4.dtd: Add main-build-id.
	* solib-svr4.c (struct svr4_info, struct svr4_library_list): Add fields
	main_build_idsz and main_build_id.
	(hex2bin_allocate): Generalize messages to binary files.
	(svr4_library_list_start_list): Parse main-build-id.
	(svr4_library_list_attributes): Add main-build-id.
	(svr4_current_sos_direct): Set svr4_info main_build_id*.
	(svr4_main_build_id): New function.
	(svr4_clear_solib): Clear svr4_info main_build_id*.
	(_initialize_svr4_solib): Install svr4_main_build_id.
	* solib.c (solib_main_build_id): New function.
	* solist.h (struct target_so_ops): Add method main_build_id.
	(solib_main_build_id): New prototype.
	* source.c (file_location_from_filename): Update build_id_verify caller.

gdb/gdbserver/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linux-low.c (linux_qxfer_libraries_svr4): Print main-build-id.

gdb/doc/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.texinfo (Files): Add 'set validate-build-id'
	and 'show validate-build-id'.

gdb/testsuite/ChangeLog
2015-08-20  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.base/main-mismatch-mod.c: New file.
	* gdb.base/main-mismatch.c: New file.
	* gdb.base/main-mismatch.exp: New file.
---
 gdb/testsuite/gdb.base/main-mismatch-mod.c |   39 +++++++
 gdb/testsuite/gdb.base/main-mismatch.c     |   39 +++++++
 gdb/testsuite/gdb.base/main-mismatch.exp   |  158 ++++++++++++++++++++++++++++
 3 files changed, 236 insertions(+)
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch-mod.c
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch.c
 create mode 100644 gdb/testsuite/gdb.base/main-mismatch.exp

diff --git a/gdb/NEWS b/gdb/NEWS
index a45aaa6..28c319e 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -52,8 +52,8 @@ show validate-build-id
 * New features in the GDB remote stub, GDBserver
 
   ** library-list-svr4 contains also optional attribute 'build-id' for
-     each library.  GDB does not load library with build-id that
-     does not match such attribute.
+     each library and one optional attribute 'main-build-id'.  GDB does
+     not load binaries with build-id that does not match such attribute.
 
 *** Changes in GDB 7.10
 
diff --git a/gdb/build-id.c b/gdb/build-id.c
index 48839cc..289c356 100644
--- a/gdb/build-id.c
+++ b/gdb/build-id.c
@@ -62,7 +62,7 @@ build_id_bfd_get (bfd *abfd)
 /* See build-id.h.  */
 
 int
-build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
+build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check, int advice)
 {
   const struct bfd_build_id *found;
   char *message, *check_hex;
@@ -93,9 +93,12 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check)
     return 1;
   back_to = make_cleanup (xfree, message);
 
-  warning (_("Symbol file \"%s\" could not be validated (%s) and "
-	     "will be ignored; or use 'set validate-build-id off'."),
-	   bfd_get_filename (abfd), message);
+  if (!advice)
+    warning ("%s", message);
+  else
+    warning (_("Symbol file \"%s\" could not be validated (%s) and "
+	       "will be ignored; or use 'set validate-build-id off'."),
+	     bfd_get_filename (abfd), message);
   do_cleanups (back_to);
   return 0;
 }
diff --git a/gdb/build-id.h b/gdb/build-id.h
index bb93df2..bb5e65d 100644
--- a/gdb/build-id.h
+++ b/gdb/build-id.h
@@ -25,10 +25,11 @@
 extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd);
 
 /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value.
-   Otherwise, issue a warning and return false.  */
+   Otherwise, issue a warning and return false.  Boolean ADVICE says whether
+   the warning should suggest to user there is the 'validate-build-id' flag.  */
 
-extern int build_id_verify (bfd *abfd,
-			    size_t check_len, const bfd_byte *check);
+extern int build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check,
+			    int advice);
 
 extern struct file_location
   build_id_to_file (size_t build_id_len, const bfd_byte *build_id,
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index fa30007..40f0f14 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -18109,6 +18109,41 @@ libraries that were loaded by explicit user requests are not
 discarded.
 @end table
 
+@table @code
+@kindex set validate-build-id
+@cindex override @value{GDBN} build-id check
+@item set validate-build-id @var{mode}
+Setting to override @value{GDBN} build-id check.
+
+Inferior binaries (shared libraries or main executable) and symbol files
+(for all of those) may contain unique build-id.  @value{GDBN} expects
+the build-ids of each binary and its corresponding symbol file to be
+identical.  If they are not identical, then by default @value{GDBN} will
+@value{GDBN} will ignore symbol files with non-matching build-id while
+printing:
+
+@smallexample
+  warning: Symbol file "libfoo.so.1" could not be validated (inferior
+  build ID 66f87872 is not identical to symbol file "libfoo.so.1" build
+  ID df81e8db) and will be ignored; or use 'set validate-build-id off'.
+@end smallexample
+
+Turning off this setting would load such symbol file without any warning.
+
+If remote build-id is present but it does not match local build-id (or local
+build-id is not present) then this setting enables (@var{mode} is @code{off}) or
+disables (@var{mode} is @code{on}) loading of such symbol file.  On systems
+where build-id is not present in the remote system this setting has no effect.
+The default value is @code{on}.
+
+Loading non-matching symbol file may confuse debugging including breakage
+of backtrace output.
+
+@kindex show validate-build-id
+@item show validate-build-id
+Display the current mode of build-id check override.
+@end table
+
 Sometimes you may wish that @value{GDBN} stops and gives you control
 when any of shared library events happen.  The best way to do this is
 to use @code{catch load} and @code{catch unload} (@pxref{Set
@@ -39763,7 +39798,9 @@ address the file was prelinked to during the library load.
 
 Additionally the single @code{main-lm} attribute specifies address of
 @code{struct link_map} used for the main executable.  This parameter is used
-for TLS access and its presence is optional.
+for TLS access and its presence is optional.  Similarly the single
+@code{main-build-id} optional attribute specifies hex encoded
+@code{NT_GNU_BUILD_ID} note for the main executable.
 
 @value{GDBN} must be linked with the Expat library to support XML
 SVR4 library lists.  @xref{Expat}.
@@ -39772,7 +39809,8 @@ A simple memory map, with two loaded libraries (which do not use prelink),
 looks like this:
 
 @smallexample
-<library-list-svr4 version="1.0" main-lm="0xe4f8f8">
+<library-list-svr4 version="1.0" main-lm="0xe4f8f8"
+    main-build-id="b96b2f6fbfb7d144b676cb66f56b6100">
   <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"
@@ -39785,8 +39823,9 @@ The format of an SVR4 library list is described by this DTD:
 @smallexample
 <!-- library-list-svr4: Root element with versioning -->
 <!ELEMENT library-list-svr4  (library)*>
-<!ATTLIST library-list-svr4  version  CDATA   #FIXED  "1.0">
-<!ATTLIST library-list-svr4  main-lm  CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  version       CDATA   #FIXED  "1.0">
+<!ATTLIST library-list-svr4  main-lm       CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  main-build-id CDATA   #IMPLIED>
 <!ELEMENT library            EMPTY>
 <!ATTLIST library            name     CDATA   #REQUIRED>
 <!ATTLIST library            lm       CDATA   #REQUIRED>
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3fb446f..d6054e9 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2498,7 +2498,7 @@ dwarf2_get_dwz_file (void)
   dwz_bfd = gdb_bfd_open (filename, gnutarget, -1);
   if (dwz_bfd != NULL)
     {
-      if (!build_id_verify (dwz_bfd, buildid_len, buildid))
+      if (!build_id_verify (dwz_bfd, buildid_len, buildid, 1 /* advice */))
 	{
 	  gdb_bfd_unref (dwz_bfd);
 	  dwz_bfd = NULL;
diff --git a/gdb/exec.c b/gdb/exec.c
index 056516b..dc39ed2 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -35,6 +35,7 @@
 #include "progspace.h"
 #include "gdb_bfd.h"
 #include "gcore.h"
+#include "build-id.h"
 
 #include <fcntl.h>
 #include "readline/readline.h"
@@ -143,11 +144,16 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
 {
   char *exec_file, *full_exec_path = NULL;
   struct cleanup *old_chain = save_current_program_space ();
+  size_t build_idsz;
+  gdb_byte *build_id;
 
   /* Switch over temporarily, while reading executable and
      symbols.  */
   set_current_program_space (inf->pspace);
 
+  solib_main_build_id (&build_idsz, &build_id);
+  make_cleanup (xfree, build_id);
+
   /* Try to determine a filename from the process itself.  */
   exec_file = target_pid_to_exec_file (inf->pid);
   if (exec_file != NULL)
@@ -155,8 +161,7 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
       /* If gdb_sysroot is not empty and the discovered filename
 	 is absolute then prefix the filename with gdb_sysroot.  */
       if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file))
-	full_exec_path = exec_file_find (exec_file, 0 /* build_idsz */,
-					 NULL /* build_id */, NULL);
+	full_exec_path = exec_file_find (exec_file, build_idsz, build_id, NULL);
 
       if (full_exec_path == NULL)
 	{
@@ -167,8 +172,8 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
 	     Attempt to qualify the filename against the source path.
 	     (If that fails, we'll just fall back on the original
 	     filename.  Not much more we can do...)  */
-	  if (!source_full_path_of (exec_file, 0 /* build_idsz */,
-				    NULL /* build_id */, &full_exec_path))
+	  if (!source_full_path_of (exec_file, build_idsz, build_id,
+				    &full_exec_path))
 	    full_exec_path = xstrdup (exec_file);
 	}
     }
@@ -179,6 +184,7 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
 	warning (_("Detected exec-file mismatch on %s.  Running %s; Loaded %s"),
 		 target_pid_to_str (pid_to_ptid (inf->pid)),
 		 full_exec_path, exec_filename);
+      build_id_verify (exec_bfd, build_idsz, build_id, 0 /* advice */);
       reopen_exec_file ();
     }
   else if (full_exec_path != NULL)
@@ -194,6 +200,9 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty)
 		   "Running %s; Loaded %s"),
 		 target_pid_to_str (pid_to_ptid (inf->pid)),
 		 full_exec_path, symbol_filename);
+
+      build_id_verify (symfile_objfile->obfd, build_idsz, build_id,
+		       0 /* advice */);
     }
   else if (full_exec_path != NULL)
     symbol_file_add_main (0, full_exec_path, from_tty);
diff --git a/gdb/features/library-list-svr4.dtd b/gdb/features/library-list-svr4.dtd
index 5741f03..27799a6 100644
--- a/gdb/features/library-list-svr4.dtd
+++ b/gdb/features/library-list-svr4.dtd
@@ -6,8 +6,9 @@
 
 <!-- library-list-svr4: Root element with versioning -->
 <!ELEMENT library-list-svr4  (library)*>
-<!ATTLIST library-list-svr4  version  CDATA   #FIXED  "1.0">
-<!ATTLIST library-list-svr4  main-lm  CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  version       CDATA   #FIXED  "1.0">
+<!ATTLIST library-list-svr4  main-lm       CDATA   #IMPLIED>
+<!ATTLIST library-list-svr4  main-build-id CDATA   #IMPLIED>
 
 <!ELEMENT library            EMPTY>
 <!ATTLIST library            name     CDATA   #REQUIRED>
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index ee8563e..6783dc2 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -6915,8 +6915,25 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
 	 exited above due to failed get_r_debug.  */
       if (lm_prev == 0)
 	{
+	  const char *hex_enc_build_id = get_hex_build_id (l_addr, l_ld, &data);
+
 	  sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr);
 	  p = p + strlen (p);
+
+	  if (hex_enc_build_id != NULL)
+	    {
+	      while (allocated
+		     < p - document + 200 + strlen (hex_enc_build_id))
+		{
+		  /* Expand to guarantee sufficient storage.  */
+		  uintptr_t document_len = p - document;
+
+		  document = xrealloc (document, 2 * allocated);
+		  allocated *= 2;
+		  p = document + document_len;
+		}
+	      p += sprintf (p, " main-build-id=\"%s\"", hex_enc_build_id);
+	    }
 	}
       else
 	{
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 858b942..fd83128 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -358,6 +358,8 @@ struct svr4_info
 
   /* Load map address for the main executable.  */
   CORE_ADDR main_lm_addr;
+  size_t main_build_idsz;
+  gdb_byte *main_build_id;
 
   CORE_ADDR interp_text_sect_low;
   CORE_ADDR interp_text_sect_high;
@@ -1087,6 +1089,9 @@ struct svr4_library_list
   /* Inferior address of struct link_map used for the main executable.  It is
      NULL if not known.  */
   CORE_ADDR main_lm;
+
+  size_t main_build_idsz;
+  gdb_byte *main_build_id;
 };
 
 /* Implementation for target_so_ops.free_so.  */
@@ -1175,13 +1180,13 @@ hex2bin_allocate (const char *hex, gdb_byte **binp, size_t *binszp,
   hex_len = strlen (hex);
   if (hex_len == 0)
     {
-      warning (_("Shared library \"%s\" received empty build-id "
+      warning (_("Binary file \"%s\" received empty build-id "
 		 "from gdbserver"), filename);
       return;
     }
   if ((hex_len & 1U) != 0)
     {
-      warning (_("Shared library \"%s\" received odd number "
+      warning (_("Binary file \"%s\" received odd number "
 		 "of build-id \"%s\" hex characters from gdbserver"),
 	       filename, hex);
       return;
@@ -1191,7 +1196,7 @@ hex2bin_allocate (const char *hex, gdb_byte **binp, size_t *binszp,
   *binszp = hex2bin (hex, *binp, binsz);
   if (*binszp != binsz)
     {
-      warning (_("Shared library \"%s\" received invalid "
+      warning (_("Binary file \"%s\" received invalid "
 		 "build-id \"%s\" hex character at encoded byte "
 		 "position %s (first as 0) from gdbserver"),
 	       filename, hex, pulongest (*binszp));
@@ -1245,6 +1250,10 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser,
   struct svr4_library_list *list = user_data;
   const char *version = xml_find_attribute (attributes, "version")->value;
   struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm");
+  const struct gdb_xml_value *const att_main_build_id
+    = xml_find_attribute (attributes, "main-build-id");
+  const char *const main_hex_build_id = (att_main_build_id
+					 ? att_main_build_id->value : NULL);
 
   if (strcmp (version, "1.0") != 0)
     gdb_xml_error (parser,
@@ -1253,6 +1262,8 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser,
 
   if (main_lm)
     list->main_lm = *(ULONGEST *) main_lm->value;
+  hex2bin_allocate (main_hex_build_id, &list->main_build_id,
+		    &list->main_build_idsz, _("main executable"));
 }
 
 /* The allowed elements and attributes for an XML library list.
@@ -1282,6 +1293,7 @@ static const struct gdb_xml_attribute svr4_library_list_attributes[] =
 {
   { "version", GDB_XML_AF_NONE, NULL, NULL },
   { "main-lm", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL },
+  { "main-build-id", GDB_XML_AF_OPTIONAL, NULL, NULL },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
@@ -1509,15 +1521,24 @@ svr4_current_sos_direct (struct svr4_info *info)
      Unfortunately statically linked inferiors will also fall back through this
      suboptimal code path.  */
 
+  library_list.main_build_id = NULL;
+  library_list.main_build_idsz = 0;
   info->using_xfer = svr4_current_sos_via_xfer_libraries (&library_list,
 							  NULL);
   if (info->using_xfer)
     {
       if (library_list.main_lm)
 	info->main_lm_addr = library_list.main_lm;
+      if (library_list.main_build_id != NULL)
+	{
+	  xfree (info->main_build_id);
+	  info->main_build_id = library_list.main_build_id;
+	  info->main_build_idsz = library_list.main_build_idsz;
+	}
 
       return library_list.head ? library_list.head : svr4_default_sos ();
     }
+  xfree (library_list.main_build_id);
 
   /* Always locate the debug struct, in case it has moved.  */
   info->debug_base = 0;
@@ -1576,6 +1597,25 @@ svr4_current_sos_1 (void)
   return svr4_current_sos_direct (info);
 }
 
+/* Implement svr4_so_ops's target_so_ops method main_build_id.  */
+
+static void
+svr4_main_build_id (size_t *build_idszp, gdb_byte **build_idp)
+{
+  struct svr4_info *info = get_svr4_info ();
+
+  /* If the solib list has been read and stored by the probes
+     interface then even main_build_id should be valid there.  */
+  if (info->solib_list == NULL)
+    svr4_current_sos_direct (info);
+
+  *build_idszp = info->main_build_idsz;
+  if (*build_idszp == 0)
+    *build_idp = NULL;
+  else
+    *build_idp = xmemdup (info->main_build_id, *build_idszp, *build_idszp);
+}
+
 /* Implement the "current_sos" target_so_ops method.  */
 
 static struct so_list *
@@ -3125,6 +3165,9 @@ svr4_clear_solib (void)
   info->debug_loader_offset = 0;
   xfree (info->debug_loader_name);
   info->debug_loader_name = NULL;
+  xfree (info->main_build_id);
+  info->main_build_id = NULL;
+  info->main_build_idsz = 0;
 }
 
 /* Clear any bits of ADDR that wouldn't fit in a target-format
@@ -3336,6 +3379,7 @@ _initialize_svr4_solib (void)
   svr4_so_ops.special_symbol_handling = svr4_special_symbol_handling;
   svr4_so_ops.current_sos = svr4_current_sos;
   svr4_so_ops.open_symbol_file_object = open_symbol_file_object;
+  svr4_so_ops.main_build_id = svr4_main_build_id;
   svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code;
   svr4_so_ops.bfd_open = solib_bfd_open;
   svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol;
diff --git a/gdb/solib.c b/gdb/solib.c
index 906cc5c..616cbc1 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1669,6 +1669,20 @@ solib_global_lookup (struct objfile *objfile,
   return (struct block_symbol) {NULL, NULL};
 }
 
+/* See solist.h.  */
+
+void
+solib_main_build_id (size_t *build_idszp, gdb_byte **build_idp)
+{
+  const struct target_so_ops *ops = ops = solib_ops (target_gdbarch ());
+
+  if (ops->main_build_id != NULL)
+    return ops->main_build_id (build_idszp, build_idp);
+
+  *build_idszp = 0;
+  *build_idp = NULL;
+}
+
 /* Lookup the value for a specific symbol from dynamic symbol table.  Look
    up symbol from ABFD.  MATCH_SYM is a callback function to determine
    whether to pick up a symbol.  DATA is the input of this callback
diff --git a/gdb/solist.h b/gdb/solist.h
index 34af30f..2947c6a 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -135,6 +135,13 @@ struct target_so_ops
        catch_errors requires a pointer argument.  */
     int (*open_symbol_file_object) (void *from_ttyp);
 
+    /* Report build-id of the main executable.  Both BUILD_IDSZP and
+       BUILD_IDP must not be NULL.  If returned *BUILD_IDSZP is zero
+       build-id is not known.  Returned *BUILD_IDP must be xfree-d by
+       the caller.  This pointer can be NULL, in which case this
+       functionality is not supported for this target.  */
+    void (*main_build_id) (size_t *build_idszp, gdb_byte **build_idp);
+
     /* Determine if PC lies in the dynamic symbol resolution code of
        the run time loader.  */
     int (*in_dynsym_resolve_code) (CORE_ADDR pc);
@@ -212,4 +219,7 @@ struct block_symbol solib_global_lookup (struct objfile *objfile,
 					    const char *name,
 					    const domain_enum domain);
 
+/* See target_so_ops's main_build_id.  */
+void solib_main_build_id (size_t *build_idszp, gdb_byte **build_idp);
+
 #endif
diff --git a/gdb/source.c b/gdb/source.c
index e5684da..6842c52 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -916,7 +916,7 @@ file_location_from_filename (const char *filename, enum openp_flags opts,
       return file;
     }
 
-  if (!build_id_verify (file.abfd, build_idsz, build_id))
+  if (!build_id_verify (file.abfd, build_idsz, build_id, 1 /* advice */))
     {
       do_cleanups (back_to);
       file_location_enoent (&file);
diff --git a/gdb/testsuite/gdb.base/main-mismatch-mod.c b/gdb/testsuite/gdb.base/main-mismatch-mod.c
new file mode 100644
index 0000000..83d0710
--- /dev/null
+++ b/gdb/testsuite/gdb.base/main-mismatch-mod.c
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#include <unistd.h>
+
+int _bar = 21;
+
+int
+bar (void)
+{
+  return 42 - _bar;
+}
+
+int
+foo (void)
+{
+  return 24 + bar();
+}
+
+int
+main (void)
+{
+  sleep (60);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/main-mismatch.c b/gdb/testsuite/gdb.base/main-mismatch.c
new file mode 100644
index 0000000..8ea17dc
--- /dev/null
+++ b/gdb/testsuite/gdb.base/main-mismatch.c
@@ -0,0 +1,39 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2015 Free Software Foundation, Inc.
+
+   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/>.  */
+
+#include <unistd.h>
+
+int _bar = 42;
+
+int
+bar (void)
+{
+  return _bar + 21;
+}
+
+int
+foo (void)
+{
+  return _bar;
+}
+
+int
+main (void)
+{
+  sleep (60);
+  return 0;
+}
diff --git a/gdb/testsuite/gdb.base/main-mismatch.exp b/gdb/testsuite/gdb.base/main-mismatch.exp
new file mode 100644
index 0000000..1aefab0
--- /dev/null
+++ b/gdb/testsuite/gdb.base/main-mismatch.exp
@@ -0,0 +1,158 @@
+# Copyright 2015 Free Software Foundation, Inc.
+
+# 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/>.  */
+
+standard_testfile
+
+if [is_remote target] {
+    untested "only local remote is currently supported"
+    return -1
+}
+if [is_remote host] {
+    untested "only local host is currently supported"
+    return -1
+}
+if [target_info exists use_gdb_stub] {
+    untested "only extended-remote target is supported for this test"
+    return -1
+}
+
+clean_restart
+
+if ![gdb_is_target_remote] {
+    untested "only gdbserver supports build-id reporting"
+    return -1
+}
+if ![target_is_gdbserver] {
+    untested "only FSF gdbserver supports build-id reporting"
+    return -1
+}
+
+# Test overview:
+#  generate two executable. One that will be used by the process
+#  and another, modified, that will be found by gdb. Gdb should
+#  detect the mismatch and refuse to use mismatched executable.
+
+# First version of the object.
+set srcmainfilerun ${testfile}.c
+
+# Modified version of the object.
+# Code in -mod.c is tuned so it gives a mismatch.
+set srcmainfilegdb ${testfile}-mod.c
+
+# So file name:
+set binmainfilebase {testfile}
+
+# Setup run directory (where program is run from)
+#   It contains the right executable.
+set binmainfiledirrun [standard_output_file ${testfile}_wd]
+set binmainfilerun ${binmainfiledirrun}/${binmainfilebase}
+
+# Second executable version is in current directory, '-mod' version.
+set binmainfiledirgdb [standard_output_file ""]
+set binmainfilegdb ${binmainfiledirgdb}/${binmainfilebase}
+
+file delete -force -- "${binmainfiledirrun}"
+file mkdir "${binmainfiledirrun}"
+
+set exec_opts {}
+lappend exec_opts "additional_flags=-DDIRNAME\=\"${binmainfiledirrun}\""
+lappend exec_opts "debug"
+lappend exec_opts "ldflags=-Wl,--build-id"
+
+if { [build_executable $testfile.exp $binmainfilerun $srcmainfilerun $exec_opts] != 0 } {
+    return -1
+}
+if { [build_executable $testfile.exp $binmainfilegdb $srcmainfilegdb $exec_opts] != 0 } {
+    return -1
+}
+
+set test_spawn_id [spawn_wait_for_attach $binmainfilerun]
+set testpid [spawn_id_get_pid $test_spawn_id]
+
+file copy -force $binmainfilerun $binmainfilerun-backup
+file copy -force $binmainfilegdb $binmainfilerun
+
+with_test_prefix "forced wrong executable" {
+    clean_restart $binmainfilerun
+
+    set test "attach"
+    gdb_test_multiple "attach $testpid" "$test" {
+	-re "Attaching to program: .*\r\nwarning: Detected exec-file mismatch .*\r\nwarning: inferior build ID .*\r\n$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+
+    gdb_test "detach"
+}
+
+with_test_prefix "unavailable autodetected executable" {
+    clean_restart
+
+    set test "attach"
+    gdb_test_multiple "attach $testpid" "$test" {
+	-re "Attaching to process $testpid\r\n.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+
+    set test "bt"
+    gdb_test_multiple $test $test {
+	-re " in main \[^\r\n\]*\r\n$gdb_prompt $" {
+	    fail $test
+	}
+	-re "\r\n$gdb_prompt $" {
+	    pass $test
+	}
+    }
+
+    gdb_test "detach"
+}
+
+# Test locating file by its build-id - if the regular filename does not match.
+# build-id file has to be a symlink - otherwise so_list->so_name shown in 'info
+# sharedlibrary' would contain the build-id hash and not the library name.
+set build_id_debug_relative [build_id_debug_filename_get $binmainfilerun-backup]
+if { ![regexp {^(.*)\.debug$} $build_id_debug_relative trash build_id_relative] } {
+    fail "strip debug $build_id_debug_relative"
+    return
+}
+set build_id_filename "${binmainfiledirrun}/$build_id_relative"
+file mkdir [file dirname $build_id_filename]
+remote_exec host "ln -sf $binmainfilerun-backup $build_id_filename"
+
+with_test_prefix "build-id autodetected executable" {
+    clean_restart
+
+    gdb_test_no_output "set debug-file-directory $binmainfiledirrun" "set debug-file-directory"
+
+    set test "attach"
+    gdb_test_multiple "attach $testpid" "$test" {
+	-re "\r\nwarning: Detected exec-file mismatch .*\r\n$gdb_prompt $" {
+	    fail "$test"
+	}
+	-re "\r\nwarning: inferior build ID .*\r\n$gdb_prompt $" {
+	    fail "$test"
+	}
+	-re "Attaching to process $testpid\r\n.*\r\n$gdb_prompt $" {
+	    pass "$test"
+	}
+    }
+
+    gdb_test "bt" " in main \[^\r\n\]*"
+
+    gdb_test "detach"
+}
+
+kill_wait_spawned_process $test_spawn_id

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 05/32] gdbserver build-id attribute generator
  2015-08-21 21:20 ` [PATCH v12 05/32] gdbserver build-id attribute generator Jan Kratochvil
@ 2015-08-22  7:17   ` Eli Zaretskii
  0 siblings, 0 replies; 46+ messages in thread
From: Eli Zaretskii @ 2015-08-22  7:17 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Date: Fri, 21 Aug 2015 23:20:49 +0200
> 
> Producer part of the new "build-id" XML attribute.
> 
> gdb/ChangeLog
> 2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	gdbserver build-id attribute generator.
> 	* features/library-list-svr4.dtd (library-list-svr4): New
> 	'build-id' attribute.
> 
> gdb/doc/ChangeLog
> 2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	gdbserver build-id attribute generator.
> 	* gdb.texinfo (Library List Format for SVR4 Targets): Add
> 	'build-id' in description, example, new attribute in dtd.
> 
> gdb/gdbserver/ChangeLog
> 2015-07-15  Aleksandar Ristovski  <aristovski@qnx.com
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
> 
> 	gdbserver build-id attribute generator.
> 	* linux-low.c (linux-maps.h, search.h, rsp-low.h): Include.
> 	(ElfXX_Ehdr, ElfXX_Phdr, ElfXX_Nhdr): New.
> 	(ELFXX_FLD, ELFXX_SIZEOF, ELFXX_ROUNDUP, BUILD_ID_INVALID): New.
> 	(find_phdr): New.
> 	(get_dynamic): Use find_pdhr to traverse program headers.
> 	(struct mapping_entry, mapping_entry_s, free_mapping_entry_vec)
> 	(compare_mapping_entry_range, struct find_memory_region_callback_data)
> 	(read_build_id, find_memory_region_callback, lrfind_mapping_entry)
> 	(get_hex_build_id): New.
> 	(linux_qxfer_libraries_svr4): Add optional build-id attribute
> 	to reply XML document.

The documentation parts are OK.

Thanks.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 06/32] Validate symbol file using build-id
  2015-08-21 21:21 ` [PATCH v12 06/32] Validate symbol file using build-id Jan Kratochvil
@ 2015-08-22  7:23   ` Eli Zaretskii
  2015-08-22 19:19     ` Jan Kratochvil
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2015-08-22  7:23 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Date: Fri, 21 Aug 2015 23:20:57 +0200
> 
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -35,6 +35,20 @@ show debug bfd-cache
>    The "/m" option is now considered deprecated: its "source-centric"
>    output hasn't proved useful in practice.
>  
> +* New options
> +
> +set validate-build-id (on|off)
> +show validate-build-id
> +  Inferior shared library and symbol file may contain unique build-id.
> +  If both build-ids are present but they do not match then this setting
> +  enables (off) or disables (on) loading of such symbol file.
> +
> +* New features in the GDB remote stub, GDBserver
> +
> +  ** library-list-svr4 contains also optional attribute 'build-id' for
> +     each library.  GDB does not load library with build-id that
> +     does not match such attribute.
> +
>  *** Changes in GDB 7.10

This is OK.

> +static void
> +show_validate_build_id (struct ui_file *file, int from_tty,
> +			struct cmd_list_element *c, const char *value)
> +{
> +  fprintf_filtered (file, _("Validation a build-id matches to load a shared "
> +			    "library is %s.\n"),

I think this message is not a valid English sentence.  I suggest this
instead:

  Validation of build-id match when loading a shared library is %s.\n

> +void
> +_initialize_build_id (void)
> +{
> +  add_setshow_boolean_cmd ("validate-build-id", class_support,
> +			   &validate_build_id, _("\
> +Set validation a build-id matches to load a shared library."), _("\

Likewise here, I suggest this alternative:

 Set whether to validate build-id match when loading a shared library.

> +SHow validation a build-id matches to load a shared library."), _("\
   ^^
Capitalization.  Also, if you accept my suggestion above, change this
text accordingly.

> +Inferior shared library and symbol file may contain unique build-id.\n\
> +If both build-ids are present but they do not match then this setting\n\
                                ^                     ^
Commas missing where indicated.

Thanks.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 08/32] Permit multiple sysroot directories
  2015-08-21 21:21 ` [PATCH v12 08/32] Permit multiple sysroot directories Jan Kratochvil
@ 2015-08-22  7:31   ` Eli Zaretskii
  2015-08-22 19:24     ` Jan Kratochvil
  0 siblings, 1 reply; 46+ messages in thread
From: Eli Zaretskii @ 2015-08-22  7:31 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Date: Fri, 21 Aug 2015 23:21:11 +0200
> 
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -35,6 +35,9 @@ show debug bfd-cache
>    The "/m" option is now considered deprecated: its "source-centric"
>    output hasn't proved useful in practice.
>  
> +* The "set sysroot" (and "show sysroot") commands now permit multiple
> +  directory paths.

A "path" is already a list, so I suggest this variant instead:

  The "set sysroot" (and "show sysroot") commands now accept PATH-style
  lists of directories.

> -Use @var{path} as the system root for the program being debugged.  Any
> +Use @var{path} as the system root (or list of system roots) for the
> +program being debugged.  Any

"or a list of system root directories" is more clear, I think.

> -If @var{path} starts with the sequence @file{target:} and the target
> +Multiple entries may be delimited by the host platform path separator in use.

Suggest a rewording:

  "Multiple sysroot directories can be specified in @var{path},
  separated by the host platform's path separator character (colon
  @samp{:} on Unix, semi-colon @samp{;} on MS-Windows, etc.)."

> +If @var{path} starts with the sequence @file{target:} (even if the host
> +platform path separator is character @file{:}) and the target
                              ^^^^^^^^^^^^^^^^^^
The "character" part is redundant, and please use @samp instead of
@file.

> -Display the current executable and shared library prefix.
> +Display the current executable and shared library prefix(es).

I think "prefix" is wrong here.  Why not simplify like this:

  Display the current value of sysroot, which is used to look for
  executable and shared libraries.

?

Thanks.

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 06/32] Validate symbol file using build-id
  2015-08-22  7:23   ` Eli Zaretskii
@ 2015-08-22 19:19     ` Jan Kratochvil
  0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-22 19:19 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Sat, 22 Aug 2015 09:23:06 +0200, Eli Zaretskii wrote:
> I think this message is not a valid English sentence.  I suggest this
> instead:
> 
>   Validation of build-id match when loading a shared library is %s.\n

I have additionally changed it a bit as the meaning has been changed:
	Validation of build-id match when loading a binary is %s.\n


> Likewise here, I suggest this alternative:
> 
>  Set whether to validate build-id match when loading a shared library.

Used:
	Set whether to validate build-id match when loading a binary.


> > +Inferior shared library and symbol file may contain unique build-id.\n\
> > +If both build-ids are present but they do not match then this setting\n\
>                                 ^                     ^
> Commas missing where indicated.

Done.  Plus again s/shared library/binary/.


Set whether to validate build-id match when loading a binary."), _("\
Show whether to validate build-id match when loading a binary."), _("\
Inferior binary and symbol file may contain unique build-id.\n\
If both build-ids are present, but they do not match, then this setting\n\
enables (off) or disables (on) loading of such symbol file.\n\
Loading non-matching symbol file may confuse debugging including breakage\n\
of backtrace output."),



All changed only in GIT.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 08/32] Permit multiple sysroot directories
  2015-08-22  7:31   ` Eli Zaretskii
@ 2015-08-22 19:24     ` Jan Kratochvil
  0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-22 19:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Sat, 22 Aug 2015 09:31:17 +0200, Eli Zaretskii wrote:
> > -Display the current executable and shared library prefix.
> > +Display the current executable and shared library prefix(es).
> 
> I think "prefix" is wrong here.  Why not simplify like this:
> 
>   Display the current value of sysroot, which is used to look for
>   executable and shared libraries.

Updated all the cases in GIT.


Thanks,
Jan

^ permalink raw reply	[flat|nested] 46+ messages in thread

* [PATCH v13 18/32] Refactor openp() to return file_location
  2015-08-21 21:22 ` [PATCH v12 18/32] Refactor openp() to return file_location Jan Kratochvil
@ 2015-08-25 19:07   ` Jan Kratochvil
  0 siblings, 0 replies; 46+ messages in thread
From: Jan Kratochvil @ 2015-08-25 19:07 UTC (permalink / raw)
  To: gdb-patches

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

Hi,

openp() remains as a backward compatibility wrapper around renamed
openp->openp_file().


Jan


gdb/ChangeLog
2015-08-19  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* defs.h (enum openp_flags): Remove OPF_OPEN_RW_TMP, add
	OPF_BFD_CANONICAL.
	(openp_bfd, openp_file): Add prototypes.
	* exec.c (exec_file_attach): Replace openp by openp_bfd calls.
	* source.c (file_location_from_filename): Support OPF_BFD_CANONICAL.
	(openp, openp_bfd): New functions.
	(openp): Rename to ...
	(openp_file): ... here, return file_location, remove filename_opened
	parameter.
---
 0 files changed

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

diff --git a/gdb/defs.h b/gdb/defs.h
index 07739cc..02ff94c 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -339,12 +339,20 @@ enum openp_flags
   /* Ask for bfd * to be returned in file_location.  */
   OPF_IS_BFD          = (1 << 2),
 
-  /* Open the file in read/write mode if WRITE_FILES says so.  */
-  OPF_OPEN_RW_TMP     = (1 << 3),
+  /* bfd_get_filename can be incorrect then, use only if you keep your
+     original filename separate from resulting bfd.
+     Returned file_location.filename is not canonicalized.  */
+  OPF_BFD_CANONICAL   = (1 << 3),
 };
 
 extern int openp (const char *, enum openp_flags, const char *, char **);
 
+extern bfd *openp_bfd (const char *path, enum openp_flags opts,
+		       const char *string);
+
+extern struct file_location openp_file (const char *path, enum openp_flags opts,
+					const char *string);
+
 extern int source_full_path_of (const char *, char **);
 
 extern void mod_path (char *, char **);
diff --git a/gdb/exec.c b/gdb/exec.c
index e87d154..8222e51 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -216,81 +216,37 @@ exec_file_attach (const char *filename, int from_tty)
     }
   else
     {
-      int load_via_target = 0;
-      char *scratch_pathname, *canonical_pathname;
-      int scratch_chan;
       struct target_section *sections = NULL, *sections_end = NULL;
       char **matching;
 
-      if (is_target_filename (filename))
-	{
-	  if (target_filesystem_is_local ())
-	    filename += strlen (TARGET_SYSROOT_PREFIX);
-	  else
-	    load_via_target = 1;
-	}
-
-      if (load_via_target)
+      exec_bfd = openp_bfd (getenv ("PATH"),
+			    OPF_TRY_CWD_FIRST | OPF_BFD_CANONICAL, filename);
+#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
+      if (exec_bfd == NULL)
 	{
-	  /* gdb_bfd_fopen does not support "target:" filenames.  */
-	  if (write_files)
-	    warning (_("writing into executable files is "
-		       "not supported for %s sysroots"),
-		     TARGET_SYSROOT_PREFIX);
-
-	  scratch_pathname = xstrdup (filename);
-	  make_cleanup (xfree, scratch_pathname);
+	  char *exename = alloca (strlen (filename) + 5);
 
-	  scratch_chan = -1;
-
-	  canonical_pathname = scratch_pathname;
+	  strcat (strcpy (exename, filename), ".exe");
+	  exec_bfd = openp_bfd (getenv ("PATH"),
+				OPF_TRY_CWD_FIRST | OPF_BFD_CANONICAL, exename);
 	}
-      else
-	{
-	  scratch_chan = openp (getenv ("PATH"),
-				OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
-				filename, &scratch_pathname);
-#if defined(__GO32__) || defined(_WIN32) || defined(__CYGWIN__)
-	  if (scratch_chan < 0)
-	    {
-	      char *exename = alloca (strlen (filename) + 5);
-
-	      strcat (strcpy (exename, filename), ".exe");
-	      scratch_chan = openp (getenv ("PATH"),
-	                            OPF_TRY_CWD_FIRST | OPF_OPEN_RW_TMP,
-				    exename, &scratch_pathname);
-	    }
 #endif
-	  if (scratch_chan < 0)
-	    perror_with_name (filename);
-
-	  make_cleanup (xfree, scratch_pathname);
-
-	  /* gdb_bfd_open (and its variants) prefers canonicalized
-	     pathname for better BFD caching.  */
-	  canonical_pathname = gdb_realpath (scratch_pathname);
-	  make_cleanup (xfree, canonical_pathname);
-	}
-
-      if (write_files && !load_via_target)
-	exec_bfd = gdb_bfd_fopen (canonical_pathname, gnutarget,
-				  FOPEN_RUB, scratch_chan);
-      else
-	exec_bfd = gdb_bfd_open (canonical_pathname, gnutarget, scratch_chan);
-
-      if (!exec_bfd)
-	{
-	  error (_("\"%s\": could not open as an executable file: %s."),
-		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
-	}
+      if (exec_bfd == NULL)
+	error (_("\"%s\": could not open as an executable file: %s."),
+	       filename, bfd_errmsg (bfd_get_error ()));
 
       /* gdb_realpath_keepfile resolves symlinks on the local
 	 filesystem and so cannot be used for "target:" files.  */
       gdb_assert (exec_filename == NULL);
-      if (load_via_target)
+      if (is_target_filename (filename))
 	exec_filename = xstrdup (bfd_get_filename (exec_bfd));
       else
-	exec_filename = gdb_realpath_keepfile (scratch_pathname);
+	{
+	  char *abspath = gdb_abspath (filename);
+
+	  exec_filename = gdb_realpath_keepfile (abspath);
+	  xfree (abspath);
+	}
 
       if (!bfd_check_format_matches (exec_bfd, bfd_object, &matching))
 	{
@@ -298,7 +254,7 @@ exec_file_attach (const char *filename, int from_tty)
 	     it.  */
 	  exec_close ();
 	  error (_("\"%s\": not in executable format: %s"),
-		 scratch_pathname,
+		 filename,
 		 gdb_bfd_errmsg (bfd_get_error (), matching));
 	}
 
@@ -308,7 +264,7 @@ exec_file_attach (const char *filename, int from_tty)
 	     it.  */
 	  exec_close ();
 	  error (_("\"%s\": can't find the file sections: %s"),
-		 scratch_pathname, bfd_errmsg (bfd_get_error ()));
+		 filename, bfd_errmsg (bfd_get_error ()));
 	}
 
       exec_bfd_mtime = bfd_get_mtime (exec_bfd);
diff --git a/gdb/source.c b/gdb/source.c
index d06cc84..029c3b5 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -868,8 +868,21 @@ file_location_from_filename (const char *filename, enum openp_flags opts)
     {
       if (write_files)
 	file.abfd = gdb_bfd_fopen (filename, gnutarget, FOPEN_RUB, file.fd);
-      else
+      else if ((opts & OPF_BFD_CANONICAL) == 0)
 	file.abfd = gdb_bfd_open (filename, gnutarget, file.fd);
+      else
+	{
+	  char *canonical;
+
+	  /* gdb_bfd_open (and its variants) prefers canonicalized
+	     pathname for better BFD caching.  */
+	  struct cleanup *canonical_cleanup;
+
+	  canonical = gdb_realpath (filename);
+	  canonical_cleanup = make_cleanup (xfree, canonical);
+	  file.abfd = gdb_bfd_open (canonical, gnutarget, file.fd);
+	  do_cleanups (canonical_cleanup);
+	}
       if ((opts & OPF_IS_BFD) != 0)
 	file.fd = -1;
       else
@@ -944,35 +957,79 @@ filename_to_bfd (const char *filename)
 							    OPF_IS_BFD));
 }
 
-/* Open a file named STRING, searching path PATH (dir names sep by some char).
-   You cannot use this function to create files.
-
-   OPTS specifies the function behaviour in specific cases.
+/* Wrapper of openp_file returning filename string.
 
-   FILENAME_OPENED must be non-null.  Set it to a newly allocated string naming
-   the actual file opened (this string will always start with a "/").  We
-   have to take special pains to avoid doubling the "/" between the directory
-   and the file, sigh!  Emacs gets confuzzed by this when we print the
-   source file name!!! 
+   FILENAME_OPENED must be non-null.  It is set to
+   file_location.filename returned from openp_file.
 
    If a file is found, return the descriptor.
    Otherwise, return -1, with errno set for the last name we tried to open.  */
 
-/*  >>>> This should only allow files of certain types,
-    >>>>  eg executable, non-directory.  */
 int
 openp (const char *path, enum openp_flags opts, const char *string,
        char **filename_opened)
 {
+  struct file_location file;
+  int retval;
+
+  gdb_assert ((opts & OPF_IS_BFD) == 0);
+
+  file = openp_file (path, opts, string);
+  gdb_assert (file.abfd == NULL);
+  if (file.fd == -1)
+    {
+      int save_errno = file.file_errno;
+
+      gdb_assert (file.filename == NULL);
+      file_location_free (&file);
+      *filename_opened = NULL;
+      errno = save_errno;
+      return -1;
+    }
+  gdb_assert (file.filename != NULL);
+  *filename_opened = xstrdup (file.filename);
+  retval = file.fd;
+  file.fd = -1;
+  file_location_free (&file);
+  return retval;
+}
+
+/* Wrapper of openp_file returning bfd *.  See file_location_to_bfd how
+   the function behaves in the case of failure.  */
+
+bfd *
+openp_bfd (const char *path, enum openp_flags opts, const char *string)
+{
+  gdb_assert ((opts & OPF_IS_BFD) == 0);
+
+  return file_location_to_bfd (openp_file (path, opts | OPF_IS_BFD, string));
+}
+
+/* Open a file named STRING, searching path PATH (dir names sep by some char).
+   You cannot use this function to create files.
+
+   OPTS specifies the function behaviour in specific cases.
+
+   Call file_location_is_valid on returned file_location to check
+   whether this function has succeeded.  */
+
+/*  >>>> This should only allow files of certain types,
+    >>>>  eg executable, non-directory.  */
+
+struct file_location
+openp_file (const char *path, enum openp_flags opts, const char *string)
+{
   int fd;
   char *filename;
   int alloclen;
   VEC (char_ptr) *dir_vec;
   struct cleanup *back_to;
-  int ix, mode;
+  int ix;
   char *dir;
+  struct file_location file;
 
   gdb_assert (string != NULL);
+  gdb_assert ((opts & (OPF_IS_BFD | OPF_BFD_CANONICAL)) != OPF_BFD_CANONICAL);
 
   /* A file with an empty name cannot possibly exist.  Report a failure
      without further checking.
@@ -983,16 +1040,13 @@ openp (const char *path, enum openp_flags opts, const char *string,
      when the debugger is started with an empty argument.  */
   if (string[0] == '\0')
     {
-      errno = ENOENT;
-      return -1;
+      file_location_enoent (&file);
+      return file;
     }
 
   if (!path)
     path = ".";
 
-  mode = (O_BINARY | (((opts & OPF_OPEN_RW_TMP) && write_files)
-		      ? O_RDWR : O_RDONLY));
-
   if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string))
     {
       int i;
@@ -1001,20 +1055,19 @@ openp (const char *path, enum openp_flags opts, const char *string,
 	{
 	  filename = alloca (strlen (string) + 1);
 	  strcpy (filename, string);
-	  fd = gdb_open_cloexec (filename, mode, 0);
-	  if (fd >= 0)
-	    goto done;
-	}
-      else
-	{
-	  filename = NULL;
-	  fd = -1;
+	  file = file_location_from_filename (filename, opts);
+	  if (file_location_is_valid (&file))
+	    return file;
+	  file_location_free (&file);
 	}
 
       if (!(opts & OPF_SEARCH_IN_PATH))
 	for (i = 0; string[i]; i++)
 	  if (IS_DIR_SEPARATOR (string[i]))
-	    goto done;
+	    {
+	      file_location_enoent (&file);
+	      return file;
+	    }
     }
 
   /* For dos paths, d:/foo -> /foo, and d:foo -> foo.  */
@@ -1033,7 +1086,7 @@ openp (const char *path, enum openp_flags opts, const char *string,
   filename = alloca (alloclen);
   fd = -1;
 
-  dir_vec = dirnames_to_char_ptr_vec (path);
+  dir_vec = dirnames_to_char_ptr_vec_target_exc (path);
   back_to = make_cleanup_free_char_ptr_vec (dir_vec);
 
   for (ix = 0; VEC_iterate (char_ptr, dir_vec, ix, dir); ++ix)
@@ -1097,23 +1150,22 @@ openp (const char *path, enum openp_flags opts, const char *string,
       strcat (filename + len, SLASH_STRING);
       strcat (filename, string);
 
-      if (is_regular_file (filename))
+      if (is_target_filename (filename) || is_regular_file (filename))
 	{
-	  fd = gdb_open_cloexec (filename, mode, 0);
-	  if (fd >= 0)
-	    break;
+	  file = file_location_from_filename (filename, opts);
+	  if (file_location_is_valid (&file))
+	    {
+	      do_cleanups (back_to);
+	      return file;
+	    }
+	  file_location_free (&file);
 	}
     }
 
   do_cleanups (back_to);
 
-done:
-  if (fd < 0)
-    *filename_opened = NULL;
-  else
-    *filename_opened = xstrdup (filename);
-
-  return fd;
+  file_location_enoent (&file);
+  return file;
 }
 
 

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
                   ` (31 preceding siblings ...)
  2015-08-21 21:24 ` [PATCH v12 30/32] Code cleanup: New hex2bin_allocate() Jan Kratochvil
@ 2015-09-02  3:57 ` Doug Evans
  2015-09-02  7:41   ` Jan Kratochvil
  32 siblings, 1 reply; 46+ messages in thread
From: Doug Evans @ 2015-09-02  3:57 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

On Fri, Aug 21, 2015 at 2:20 PM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> Hi,
>
> git://sourceware.org/git/archer.git
> jankratochvil/gdbserverbuildid
>
> The new file-locating parts are freshly coded, there are many possible future
> improvements but I find the patchset as a minimal functional upstreamable
> support for locating files from gdbserver build-ids.
>
> It does not support build-ids from linux-nat and core files (as Fedora GDB
> supports).  It also does not ask librpm for debuginfo-install suggestions.

Hi. Which Fedora patches support build-ids in core files?

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02  3:57 ` [PATCH v12 00/32] Validate binary before use Doug Evans
@ 2015-09-02  7:41   ` Jan Kratochvil
  2015-09-02 14:58     ` Doug Evans
  0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-09-02  7:41 UTC (permalink / raw)
  To: Doug Evans; +Cc: gdb-patches

On Wed, 02 Sep 2015 05:56:48 +0200, Doug Evans wrote:
> On Fri, Aug 21, 2015 at 2:20 PM, Jan Kratochvil <jan.kratochvil@redhat.com> wrote:
> > It does not support build-ids from linux-nat and core files (as Fedora GDB
> > supports).  It also does not ask librpm for debuginfo-install suggestions.
> 
> Which Fedora patches support build-ids in core files?

The primary patch from 2007 is:
	http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-buildid-locate.patch
But there are related all the gdb-6.6-buildid-locate*.patch files in:
	http://pkgs.fedoraproject.org/cgit/gdb.git/tree/

That means on Fedora people can do what newbie users expect to work, that is:
	gdb core.34523
and GDB finds and loads all the needed executable + shared libraries (and it
does not load non-matching shared libraries which only confuse the
backtraces).


Jan

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02  7:41   ` Jan Kratochvil
@ 2015-09-02 14:58     ` Doug Evans
  2015-09-02 15:14       ` Jan Kratochvil
  0 siblings, 1 reply; 46+ messages in thread
From: Doug Evans @ 2015-09-02 14:58 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Doug Evans, gdb-patches

On Wed, Sep 2, 2015 at 12:41 AM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> On Wed, 02 Sep 2015 05:56:48 +0200, Doug Evans wrote:
>> On Fri, Aug 21, 2015 at 2:20 PM, Jan Kratochvil <jan.kratochvil@redhat.com> wrote:
>> > It does not support build-ids from linux-nat and core files (as Fedora GDB
>> > supports).  It also does not ask librpm for debuginfo-install suggestions.
>>
>> Which Fedora patches support build-ids in core files?
>
> The primary patch from 2007 is:
>         http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-buildid-locate.patch
> But there are related all the gdb-6.6-buildid-locate*.patch files in:
>         http://pkgs.fedoraproject.org/cgit/gdb.git/tree/
>
> That means on Fedora people can do what newbie users expect to work, that is:
>         gdb core.34523
> and GDB finds and loads all the needed executable + shared libraries (and it
> does not load non-matching shared libraries which only confuse the
> backtraces).

Thanks.

Is there a patch that given "gdb random-program random-core"
will verify the build-ids match?

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02 14:58     ` Doug Evans
@ 2015-09-02 15:14       ` Jan Kratochvil
  2015-09-02 15:22         ` Doug Evans
  0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-09-02 15:14 UTC (permalink / raw)
  To: Doug Evans; +Cc: Doug Evans, gdb-patches

On Wed, 02 Sep 2015 16:58:06 +0200, Doug Evans wrote:
> Is there a patch that given "gdb random-program random-core"
> will verify the build-ids match?

No.

This posted patchset cannot fetch build-ids for local files.

The Fedora patchset intentionally disables build-ids verification/lookup if
random-program is specified as it was breaking some compatibility and IMO it
does not make sense to specify random-program if build-ids are available.


Jan

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02 15:14       ` Jan Kratochvil
@ 2015-09-02 15:22         ` Doug Evans
  2015-09-02 19:12           ` Jan Kratochvil
  0 siblings, 1 reply; 46+ messages in thread
From: Doug Evans @ 2015-09-02 15:22 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: Doug Evans, gdb-patches

On Wed, Sep 2, 2015 at 8:14 AM, Jan Kratochvil
<jan.kratochvil@redhat.com> wrote:
> The Fedora patchset intentionally disables build-ids verification/lookup if
> random-program is specified as it was breaking some compatibility

Interesting. What kind of compatibility?

> and IMO it
> does not make sense to specify random-program if build-ids are available.

Why is that?
[Just because one has a build id doesn't necessarily mean one knows where
a program is. Or did I misunderstand?]

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02 15:22         ` Doug Evans
@ 2015-09-02 19:12           ` Jan Kratochvil
  2015-09-15  1:37             ` Doug Evans
  0 siblings, 1 reply; 46+ messages in thread
From: Jan Kratochvil @ 2015-09-02 19:12 UTC (permalink / raw)
  To: Doug Evans; +Cc: Doug Evans, gdb-patches

Hello Doug,

this discussion is offtopic for this patchset and it touches areas I am not
yet sure how I will change/rewrite before posting the linux-nat/corefile next
part.  OTOH that's also good as it can be at least designed ahead of coding.


On Wed, 02 Sep 2015 17:22:35 +0200, Doug Evans wrote:
> On Wed, Sep 2, 2015 at 8:14 AM, Jan Kratochvil
> <jan.kratochvil@redhat.com> wrote:
> > The Fedora patchset intentionally disables build-ids verification/lookup if
> > random-program is specified as it was breaking some compatibility
> 
> Interesting. What kind of compatibility?

I was looking up what it really was and there are two reasons:

(1) I did not want to change behavior of Fedora fork of GDB against upstream.
    This is why I tried to keep the behavior of case
      "gdb random-program random-core"
    the same as upstream GDB has.

    This can be sure changed now when/if the feature gets upstreamed.

(2) As discussed below for "Fedora native" loading of core-files fully
    according to build-ids any behavior is OK as such case does not work for
    upstream GDB at all.  In such case the strict build-id matching is the
    best one for user IMO as shown in:
      non-matching build-id libraries should not be loaded for `gdb -c'
      https://bugzilla.redhat.com/show_bug.cgi?id=524572
    +
      Base the backtrace strictly on build-id
      https://bugzilla.redhat.com/show_bug.cgi?id=525721


> > and IMO it
> > does not make sense to specify random-program if build-ids are available.
> 
> Why is that?
> [Just because one has a build id doesn't necessarily mean one knows where
> a program is. Or did I misunderstand?]

On Fedora for build-id -> filename mapping one needs the appropriate
n-debuginfo-v-r.a.rpm installed.  IMO on development machines they are
installed most of the time because otherwise Fedora GDB all the time annoys
users by complaints they should get installed.  If it is missing for any reason
one can easily get it installed as shown at the end of this mail.  (OK, maybe
it can be made even easier but that would require better integration with the
ever-changing packaging front-ends on Fedora.)

There were some discussions how the build-id -> filename mapping should be
stored.  Currently it is done by on-disk symlinks in /usr/lib/debug/.build-id/
stored in *-debuginfo.rpm (therefore to get just the build-id -> filename
mapping symlink even for an already installed binary one needs to install
*-debuginfo.rpm).
# ls -l /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9*
lrwxrwxrwx 1 root root 21 Jul 16 10:42 /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9 -> ../../../../bin/sleep*
lrwxrwxrwx 1 root root 25 Jul 16 10:42 /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9.debug -> ../../usr/bin/sleep.debug
# rpm -qf /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9{,.debug} /bin/sleep /usr/lib/debug/usr/bin/sleep.debug
coreutils-debuginfo-8.24-2.fc23.x86_64
coreutils-debuginfo-8.24-2.fc23.x86_64
coreutils-8.24-2.fc23.x86_64
coreutils-debuginfo-8.24-2.fc23.x86_64

Other possibilities would be to store build-ids into .rpm tags even in the main
binary .rpms; but that would make dependency of the build-ids resolving on rpm.
Another possibility is to include the build-id symlinks into the main binary
packages; but those symlinks can take a lot of disk space even when no
debugging is required. Or to have some global or per-package sqlite database
etc.


Jan


$ gdb -q core.23526 
[New LWP 23526]
Missing separate debuginfo for the main executable file
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9
Core was generated by `sleep 1h'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f2810648bf0 in ?? ()
"/home/jkratoch/t/core.23526" is a core file.
Please specify an executable to debug.
(gdb) q
# dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9
[...]
Installed:
  coreutils-debuginfo.x86_64 8.24-2.fc23                                                                                                 
$ gdb -q core.23526 
[New LWP 23526]
Reading symbols from /usr/bin/sleep...Reading symbols from /usr/lib/debug/usr/bin/sleep.debug...done.
done.

warning: Ignoring non-absolute filename: <linux-vdso.so.1>
Missing separate debuginfo for linux-vdso.so.1
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
Core was generated by `sleep 1h'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f2810648bf0 in __nanosleep_nocancel () from /lib64/libc.so.6
Missing separate debuginfos, use: dnf debuginfo-install glibc-2.21.90-21.fc23.x86_64
(gdb) q
# dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
Last metadata expiration check performed 0:03:45 ago on Wed Sep  2 20:53:07 2015.
No package /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5 available.
Error: no package matched
 --- Because matching kernel.rpm running on host OS is not available in this guest OS.
# dnf debuginfo-install glibc-2.21.90-21.fc23.x86_64
[...]
Installed:
  glibc-debuginfo.x86_64 2.22-2.fc23     glibc-debuginfo-common.x86_64 2.22-2.fc23     nss-softokn-debuginfo.x86_64 3.20.0-1.0.fc23    
$ gdb -q core.26016 
[New LWP 26016]
Reading symbols from /usr/bin/sleep...Reading symbols from /usr/lib/debug/usr/bin/sleep.debug...done.
done.

warning: Ignoring non-absolute filename: <linux-vdso.so.1>
Missing separate debuginfo for linux-vdso.so.1
Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
Core was generated by `sleep 1h'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f3fd8bd6870 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
84	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) bt
#0  0x00007f3fd8bd6870 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
#1  0x000055f9f5bf829f in rpl_nanosleep (requested_delay=requested_delay@entry=0x7ffe1323cb80, 
    remaining_delay=remaining_delay@entry=0x0) at lib/nanosleep.c:85
#2  0x000055f9f5bf8100 in xnanosleep (seconds=<optimized out>) at lib/xnanosleep.c:51
#3  0x000055f9f5bf5a1d in main (argc=<optimized out>, argv=<optimized out>) at src/sleep.c:145
(gdb) q

^ permalink raw reply	[flat|nested] 46+ messages in thread

* Re: [PATCH v12 00/32] Validate binary before use
  2015-09-02 19:12           ` Jan Kratochvil
@ 2015-09-15  1:37             ` Doug Evans
  0 siblings, 0 replies; 46+ messages in thread
From: Doug Evans @ 2015-09-15  1:37 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

Jan Kratochvil <jan.kratochvil@redhat.com> writes:
> Hello Doug,
>
> this discussion is offtopic for this patchset and it touches areas I am not
> yet sure how I will change/rewrite before posting the linux-nat/corefile next
> part.  OTOH that's also good as it can be at least designed ahead of coding.

Yeah.
[FAOD, I'm only seeking information at this point.
This particular subthread isn't part of a formal review of the patch.]

> On Wed, 02 Sep 2015 17:22:35 +0200, Doug Evans wrote:
>> On Wed, Sep 2, 2015 at 8:14 AM, Jan Kratochvil
>> <jan.kratochvil@redhat.com> wrote:
>> > The Fedora patchset intentionally disables build-ids verification/lookup if
>> > random-program is specified as it was breaking some compatibility
>> 
>> Interesting. What kind of compatibility?
>
> I was looking up what it really was and there are two reasons:
>
> (1) I did not want to change behavior of Fedora fork of GDB against upstream.
>     This is why I tried to keep the behavior of case
>       "gdb random-program random-core"
>     the same as upstream GDB has.
>
>     This can be sure changed now when/if the feature gets upstreamed.
>
> (2) As discussed below for "Fedora native" loading of core-files fully
>     according to build-ids any behavior is OK as such case does not work for
>     upstream GDB at all.  In such case the strict build-id matching is the
>     best one for user IMO as shown in:
>       non-matching build-id libraries should not be loaded for `gdb -c'
>       https://bugzilla.redhat.com/show_bug.cgi?id=524572
>     +
>       Base the backtrace strictly on build-id
>       https://bugzilla.redhat.com/show_bug.cgi?id=525721

Thanks.
I think upstream will definitely want the verification
if both program + core are provided.
[plus a way to turn the verification off!]
Set aside vendor-provided binaries.
Imagine Joe User has a binary and a core file.
Or imagine an entire community of programmers, binaries, and cores.
Making sure one is using the right core file with the right
program is important.


>> > and IMO it
>> > does not make sense to specify random-program if build-ids are available.
>> 
>> Why is that?
>> [Just because one has a build id doesn't necessarily mean one knows where
>> a program is. Or did I misunderstand?]
>
> On Fedora for build-id -> filename mapping one needs the appropriate
> n-debuginfo-v-r.a.rpm installed.  IMO on development machines they are
> installed most of the time because otherwise Fedora GDB all the time annoys
> users by complaints they should get installed.  If it is missing for any reason
> one can easily get it installed as shown at the end of this mail.  (OK, maybe
> it can be made even easier but that would require better integration with the
> ever-changing packaging front-ends on Fedora.)
>
> There were some discussions how the build-id -> filename mapping should be
> stored.  Currently it is done by on-disk symlinks in /usr/lib/debug/.build-id/
> stored in *-debuginfo.rpm (therefore to get just the build-id -> filename
> mapping symlink even for an already installed binary one needs to install
> *-debuginfo.rpm).
> # ls -l /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9*
> lrwxrwxrwx 1 root root 21 Jul 16 10:42 /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9 -> ../../../../bin/sleep*
> lrwxrwxrwx 1 root root 25 Jul 16 10:42 /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9.debug -> ../../usr/bin/sleep.debug
> # rpm -qf /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9{,.debug} /bin/sleep /usr/lib/debug/usr/bin/sleep.debug
> coreutils-debuginfo-8.24-2.fc23.x86_64
> coreutils-debuginfo-8.24-2.fc23.x86_64
> coreutils-8.24-2.fc23.x86_64
> coreutils-debuginfo-8.24-2.fc23.x86_64
>
> Other possibilities would be to store build-ids into .rpm tags even in the main
> binary .rpms; but that would make dependency of the build-ids resolving on rpm.
> Another possibility is to include the build-id symlinks into the main binary
> packages; but those symlinks can take a lot of disk space even when no
> debugging is required. Or to have some global or per-package sqlite database
> etc.
>
>
> Jan
>
>
> $ gdb -q core.23526 
> [New LWP 23526]
> Missing separate debuginfo for the main executable file
> Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9
> Core was generated by `sleep 1h'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  0x00007f2810648bf0 in ?? ()
> "/home/jkratoch/t/core.23526" is a core file.
> Please specify an executable to debug.
> (gdb) q
> # dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/b3/e636b621bb16456d201edca942442bdbf045f9
> [...]
> Installed:
>   coreutils-debuginfo.x86_64 8.24-2.fc23                                                                                                 
> $ gdb -q core.23526 
> [New LWP 23526]
> Reading symbols from /usr/bin/sleep...Reading symbols from /usr/lib/debug/usr/bin/sleep.debug...done.
> done.
>
> warning: Ignoring non-absolute filename: <linux-vdso.so.1>
> Missing separate debuginfo for linux-vdso.so.1
> Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
> Core was generated by `sleep 1h'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  0x00007f2810648bf0 in __nanosleep_nocancel () from /lib64/libc.so.6
> Missing separate debuginfos, use: dnf debuginfo-install glibc-2.21.90-21.fc23.x86_64
> (gdb) q
> # dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
> Last metadata expiration check performed 0:03:45 ago on Wed Sep  2 20:53:07 2015.
> No package /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5 available.
> Error: no package matched
>  --- Because matching kernel.rpm running on host OS is not available in this guest OS.
> # dnf debuginfo-install glibc-2.21.90-21.fc23.x86_64
> [...]
> Installed:
>   glibc-debuginfo.x86_64 2.22-2.fc23     glibc-debuginfo-common.x86_64 2.22-2.fc23     nss-softokn-debuginfo.x86_64 3.20.0-1.0.fc23    
> $ gdb -q core.26016 
> [New LWP 26016]
> Reading symbols from /usr/bin/sleep...Reading symbols from /usr/lib/debug/usr/bin/sleep.debug...done.
> done.
>
> warning: Ignoring non-absolute filename: <linux-vdso.so.1>
> Missing separate debuginfo for linux-vdso.so.1
> Try: dnf --enablerepo='*debug*' install /usr/lib/debug/.build-id/2b/fef7432912bcc87752ef9e66b1ddb71d7485f5
> Core was generated by `sleep 1h'.
> Program terminated with signal SIGSEGV, Segmentation fault.
> #0  0x00007f3fd8bd6870 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
> 84	T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
> (gdb) bt
> #0  0x00007f3fd8bd6870 in __nanosleep_nocancel () at ../sysdeps/unix/syscall-template.S:84
> #1  0x000055f9f5bf829f in rpl_nanosleep (requested_delay=requested_delay@entry=0x7ffe1323cb80, 
>     remaining_delay=remaining_delay@entry=0x0) at lib/nanosleep.c:85
> #2  0x000055f9f5bf8100 in xnanosleep (seconds=<optimized out>) at lib/xnanosleep.c:51
> #3  0x000055f9f5bf5a1d in main (argc=<optimized out>, argv=<optimized out>) at src/sleep.c:145
> (gdb) q

^ permalink raw reply	[flat|nested] 46+ messages in thread

end of thread, other threads:[~2015-09-15  1:37 UTC | newest]

Thread overview: 46+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-21 21:20 [PATCH v12 00/32] Validate binary before use Jan Kratochvil
2015-08-21 21:20 ` [PATCH v12 02/32] Move gdb_regex* to common/ Jan Kratochvil
2015-08-21 21:20 ` [PATCH v12 03/32] Prepare linux_find_memory_regions_full & co. for move Jan Kratochvil
2015-08-21 21:20 ` [PATCH v12 01/32] Create empty common/linux-maps.[ch] and common/target-utils.[ch] Jan Kratochvil
2015-08-21 21:20 ` [PATCH v12 04/32] Move linux_find_memory_regions_full & co Jan Kratochvil
2015-08-21 21:20 ` [PATCH v12 05/32] gdbserver build-id attribute generator Jan Kratochvil
2015-08-22  7:17   ` Eli Zaretskii
2015-08-21 21:21 ` [PATCH v12 10/32] Code cleanup: Add enum for openp_flags Jan Kratochvil
2015-08-21 21:21 ` [PATCH v12 11/32] Code cleanup: Remove OPF_RETURN_REALPATH Jan Kratochvil
2015-08-21 21:21 ` [PATCH v12 07/32] Code cleanup: Make solib_find_1 variable const Jan Kratochvil
2015-08-21 21:21 ` [PATCH v12 06/32] Validate symbol file using build-id Jan Kratochvil
2015-08-22  7:23   ` Eli Zaretskii
2015-08-22 19:19     ` Jan Kratochvil
2015-08-21 21:21 ` [PATCH v12 12/32] Code cleanup: Remove openp parameter mode Jan Kratochvil
2015-08-21 21:21 ` [PATCH v12 08/32] Permit multiple sysroot directories Jan Kratochvil
2015-08-22  7:31   ` Eli Zaretskii
2015-08-22 19:24     ` Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 20/32] symfile_bfd_open: Make it use openp_bfd() Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 14/32] Provide new gdb_bfd_open_from_target Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 15/32] gdb_bfd_open_from_target: Support real fd Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 16/32] gdb_bfd_open_from_target: Optionally do not close fd Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 19/32] solib_find: Make it use file_location Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 18/32] Refactor openp() to return file_location Jan Kratochvil
2015-08-25 19:07   ` [PATCH v13 " Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 17/32] Add file_location utility functions Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 09/32] Change sysroot to ":target:" Jan Kratochvil
2015-08-21 21:22 ` [PATCH v12 13/32] Code cleanup: openp parameter filename_opened is never NULL Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 21/32] build_id_to_debug_bfd: Make it also non-.debug capable Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 25/32] Verify the build-id Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 22/32] Add dummy build-id params to prototypes Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 26/32] solib_bfd_open: Optimize opening twice Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 23/32] build_id_to_bfd: Make it return file_location Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 27/32] build_id_verify: Make it more verbose Jan Kratochvil
2015-08-21 21:23 ` [PATCH v12 24/32] solib_find: Search also by build-id Jan Kratochvil
2015-08-21 21:24 ` [PATCH v12 28/32] Tests for validate symbol file using build-id Jan Kratochvil
2015-08-21 21:24 ` [PATCH v12 32/32] Support build-id for main executables Jan Kratochvil
2015-08-21 21:24 ` [PATCH v12 29/32] testcase: Test also locating shlibs by build-id Jan Kratochvil
2015-08-21 21:24 ` [PATCH v12 31/32] Make only user-specified executable and symbol filenames sticky Jan Kratochvil
2015-08-21 21:24 ` [PATCH v12 30/32] Code cleanup: New hex2bin_allocate() Jan Kratochvil
2015-09-02  3:57 ` [PATCH v12 00/32] Validate binary before use Doug Evans
2015-09-02  7:41   ` Jan Kratochvil
2015-09-02 14:58     ` Doug Evans
2015-09-02 15:14       ` Jan Kratochvil
2015-09-02 15:22         ` Doug Evans
2015-09-02 19:12           ` Jan Kratochvil
2015-09-15  1:37             ` Doug Evans

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).