Revert the previous 7 commits of: Validate binary before use

ddc98fbf2f Create empty nat/linux-maps.[ch] and common/target-utils.[ch]
6e5b4429db Move gdb_regex* to common/
f7af1fcd75 Prepare linux_find_memory_regions_full & co. for move
9904185cfd Move linux_find_memory_regions_full & co.
700ca40f6f gdbserver build-id attribute generator
ca5268b6be Validate symbol file using build-id
0a94970d66 Tests for validate symbol file using build-id

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

	Revert the previous 6 commits:
	Create empty nat/linux-maps.[ch] and common/target-utils.[ch].
	Move gdb_regex* to common/
	Prepare linux_find_memory_regions_full & co. for move
	Move linux_find_memory_regions_full & co.
	gdbserver build-id attribute generator
	Validate symbol file using build-id

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

	Revert the previous 3 commits:
	Move gdb_regex* to common/
	Move linux_find_memory_regions_full & co.
	gdbserver build-id attribute generator

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

	Revert the previous 2 commits:
	gdbserver build-id attribute generator
	Validate symbol file using build-id

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

	Revert the previous commit:
	Tests for validate symbol file using build-id.
This commit is contained in:
Jan Kratochvil 2015-07-15 20:27:32 +02:00
parent 0a94970d66
commit db1ff28b60
43 changed files with 830 additions and 1952 deletions

View File

@ -1,3 +1,13 @@
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
Revert the previous 6 commits:
Create empty nat/linux-maps.[ch] and common/target-utils.[ch].
Move gdb_regex* to common/
Prepare linux_find_memory_regions_full & co. for move
Move linux_find_memory_regions_full & co.
gdbserver build-id attribute generator
Validate symbol file using build-id
2015-07-15 Aleksandar Ristovski <aristovski@qnx.com
Jan Kratochvil <jan.kratochvil@redhat.com>

View File

@ -903,7 +903,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 nat/linux-maps.h \
common/gdb_signals.h nat/gdb_thread_db.h common/gdb_vecs.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 \
@ -937,7 +937,7 @@ extension.h extension-priv.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 common/gdb_regex.h xtensa-tdep.h inf-loop.h \
complaints.h gdb_proc_service.h 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 i387-tdep.h mn10300-tdep.h \
@ -983,7 +983,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 target/target-utils.h
nat/linux-namespaces.h
# Header files that already have srcdir in them, or which are in objdir.
@ -1083,8 +1083,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 target-utils.o \
gdb_regex.o \
common-exceptions.o btrace-common.o fileio.o \
$(SUBDIR_GCC_COMPILE_OBS)
TSOBS = inflow.o
@ -2222,10 +2221,6 @@ common-agent.o: $(srcdir)/common/agent.c
$(COMPILE) $(srcdir)/common/agent.c
$(POSTCOMPILE)
linux-maps.o: ${srcdir}/nat/linux-maps.c
$(COMPILE) $(srcdir)/nat/linux-maps.c
$(POSTCOMPILE)
vec.o: ${srcdir}/common/vec.c
$(COMPILE) $(srcdir)/common/vec.c
$(POSTCOMPILE)
@ -2242,10 +2237,6 @@ 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)
@ -2273,10 +2264,6 @@ 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
#

View File

@ -5,20 +5,6 @@
* Support for tracepoints on aarch64-linux was added in GDBserver.
* 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*

View File

@ -44,33 +44,4 @@ 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
])

View File

@ -1,73 +0,0 @@
/* 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);
}

View File

@ -3,7 +3,7 @@
NAT_FILE= config/nm-linux.h
NATDEPFILES= inf-ptrace.o fork-child.o \
x86-nat.o x86-dregs.o i386-linux-nat.o x86-linux-nat.o \
proc-service.o linux-thread-db.o linux-maps.o \
proc-service.o linux-thread-db.o \
linux-nat.o linux-osdata.o linux-fork.o linux-procfs.o linux-ptrace.o \
linux-btrace.o linux-waitpid.o linux-personality.o x86-linux.o \
x86-linux-dregs.o linux-namespaces.o

View File

@ -2,7 +2,7 @@
NATDEPFILES= inf-ptrace.o fork-child.o \
x86-nat.o x86-dregs.o amd64-nat.o amd64-linux-nat.o \
x86-linux-nat.o \
linux-maps.o linux-nat.o linux-osdata.o \
linux-nat.o linux-osdata.o \
proc-service.o linux-thread-db.o linux-fork.o \
linux-procfs.o linux-ptrace.o linux-btrace.o \
linux-waitpid.o linux-personality.o x86-linux.o \

102
gdb/configure vendored
View File

@ -11925,57 +11925,6 @@ $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. No canned test for
# this, so roll our own.
@ -12238,6 +12187,57 @@ 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>

View File

@ -1444,6 +1444,35 @@ 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>

View File

@ -1,3 +1,9 @@
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
Revert the previous 2 commits:
gdbserver build-id attribute generator
Validate symbol file using build-id
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.texinfo (Files): Add 'set validate-build-id'

View File

@ -17950,44 +17950,6 @@ 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 shared libraries and symbol files may contain unique build-id.
By default @value{GDBN} will ignore symbol files with non-matching build-id
while printing:
@smallexample
warning: Shared object "libfoo.so.1" could not be validated (remote
build ID 2bc1745e does not match local build ID a08f8767) and will be
ignored; or use 'set validate-build-id off'.
@end smallexample
Turning off this setting would load such symbol file while still printing:
@smallexample
warning: Shared object "libfoo.so.1" could not be validated (remote
build ID 2bc1745e does not match local build ID a08f8767) but it is
being loaded due to 'set validate-build-id off'.
@end smallexample
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
@ -39551,8 +39513,6 @@ 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
@ -39570,7 +39530,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" build-id="9afccf7cc41e6293476223fe72480854"/>
l_ld="0x152350"/>
</library-list-svr>
@end smallexample
@ -39579,14 +39539,13 @@ 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 build-id CDATA #IMPLIED>
<!ATTLIST library name CDATA #REQUIRED>
<!ATTLIST library lm CDATA #REQUIRED>
<!ATTLIST library l_addr CDATA #REQUIRED>
<!ATTLIST library l_ld CDATA #REQUIRED>
@end smallexample
@node Memory Map Format

View File

@ -6,12 +6,11 @@
<!-- 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 build-id CDATA #IMPLIED>
<!ATTLIST library name CDATA #REQUIRED>
<!ATTLIST library lm CDATA #REQUIRED>
<!ATTLIST library l_addr CDATA #REQUIRED>
<!ATTLIST library l_ld CDATA #REQUIRED>

View File

@ -16,8 +16,8 @@
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
#ifndef GDB_REGEX_H
#define GDB_REGEX_H 1
#ifdef USE_INCLUDED_REGEX
# include "xregex.h"
@ -27,9 +27,10 @@
# 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 COMMON_GDB_REGEX_H */
#endif /* not GDB_REGEX_H */

View File

@ -1,3 +1,10 @@
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
Revert the previous 3 commits:
Move gdb_regex* to common/
Move linux_find_memory_regions_full & co.
gdbserver build-id attribute generator
2015-07-15 Aleksandar Ristovski <aristovski@qnx.com
Jan Kratochvil <jan.kratochvil@redhat.com>

View File

@ -194,8 +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 target-utils.o \
gdb_regex.o \
common-exceptions.o symbol.o btrace-common.o fileio.o \
$(XML_BUILTIN) $(DEPFILES) $(LIBOBJS)
GDBREPLAY_OBS = gdbreplay.o version.o
GDBSERVER_LIBS = @GDBSERVER_LIBS@
@ -520,9 +519,6 @@ ax.o: ax.c
signals.o: ../common/signals.c
$(COMPILE) $<
$(POSTCOMPILE)
linux-maps.o: ../nat/linux-maps.c
$(COMPILE) $<
$(POSTCOMPILE)
print-utils.o: ../common/print-utils.c
$(COMPILE) $<
$(POSTCOMPILE)
@ -535,9 +531,6 @@ 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)
@ -583,9 +576,6 @@ 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

View File

@ -317,9 +317,6 @@
/* 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

View File

@ -694,7 +694,6 @@ enable_maintainer_mode
enable_largefile
enable_build_with_cxx
enable_libmcheck
with_included_regex
with_ust
with_ust_include
with_ust_lib
@ -1346,10 +1345,6 @@ 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
@ -5752,57 +5747,6 @@ $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 for UST
ustlibs=""

View File

@ -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-maps.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-ptrace.o linux-waitpid.o linux-personality.o linux-namespaces.o"
# Input is taken from the "${target}" variable.

View File

@ -22,7 +22,6 @@
#include "agent.h"
#include "tdesc.h"
#include "rsp-low.h"
#include "nat/linux-maps.h"
#include "nat/linux-nat.h"
#include "nat/linux-waitpid.h"
@ -44,11 +43,9 @@
#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,31 +182,6 @@ 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. */
@ -6038,38 +6010,15 @@ 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;
int num_phdr, i;
unsigned char *phdr_buf;
const ElfXX_Phdr *phdr;
const int phdr_size = ELFXX_SIZEOF (is_elf64, *phdr);
const int phdr_size = is_elf64 ? sizeof (Elf64_Phdr) : sizeof (Elf32_Phdr);
if (get_phdr_phnum_from_proc_auxv (pid, is_elf64, &phdr_memaddr, &num_phdr))
return 0;
@ -6083,10 +6032,22 @@ 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;
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);
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;
}
if (relocation == -1)
{
/* PT_PHDR is optional, but necessary for PIE in general. Fortunately
@ -6102,11 +6063,23 @@ get_dynamic (const int pid, const int is_elf64)
return 0;
}
phdr = find_phdr (is_elf64, phdr_buf, phdr_buf + num_phdr * phdr_size,
PT_DYNAMIC);
for (i = 0; i < num_phdr; i++)
{
if (is_elf64)
{
Elf64_Phdr *const p = (Elf64_Phdr *) (phdr_buf + i * phdr_size);
if (phdr != NULL)
return ELFXX_FLD (is_elf64, *phdr, p_vaddr) + relocation;
if (p->p_type == PT_DYNAMIC)
return p->p_vaddr + relocation;
}
else
{
Elf32_Phdr *const p = (Elf32_Phdr *) (phdr_buf + i * phdr_size);
if (p->p_type == PT_DYNAMIC)
return p->p_vaddr + relocation;
}
}
return 0;
}
@ -6246,278 +6219,6 @@ 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
@ -6530,15 +6231,6 @@ 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 so it is not expected it could have an ELF header. */
const enum filterflags filterflags = (COREFILTER_MAPPED_PRIVATE
| COREFILTER_MAPPED_SHARED
| COREFILTER_ELF_HEADERS
| COREFILTER_HUGETLB_PRIVATE
| COREFILTER_HUGETLB_SHARED);
static const struct link_map_offsets lmo_32bit_offsets =
{
@ -6581,14 +6273,6 @@ 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;
@ -6695,7 +6379,6 @@ 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)
{
@ -6704,11 +6387,7 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf,
header_done = 1;
}
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)))
while (allocated < p - document + len + 200)
{
/* Expand to guarantee sufficient storage. */
uintptr_t document_len = p - document;
@ -6720,13 +6399,9 @@ 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);
}
}
@ -6753,7 +6428,6 @@ 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;
}

View File

@ -20,8 +20,6 @@
#include "server.h"
#include "tracepoint.h"
#include "target/target-utils.h"
#include <fcntl.h>
struct target_ops *the_target;
@ -220,37 +218,3 @@ 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);
}

View File

@ -35,11 +35,56 @@
#include "observer.h"
#include "objfiles.h"
#include "infcall.h"
#include "nat/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. */
@ -350,6 +395,286 @@ 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
@ -773,6 +1098,191 @@ linux_core_info_proc (struct gdbarch *gdbarch, const char *args,
error (_("unable to handle request"));
}
typedef int linux_find_memory_region_ftype (ULONGEST vaddr, ULONGEST size,
ULONGEST offset, ULONGEST inode,
int read, int write,
int exec, int modified,
const char *filename,
void *data);
/* List memory regions in the inferior for a corefile. */
static int
linux_find_memory_regions_full (struct gdbarch *gdbarch,
linux_find_memory_region_ftype *func,
void *obfd)
{
char 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);
}
}
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;
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)
func (addr, endaddr - addr, offset, inode,
read, write, exec, 1, /* MODIFIED is true because we
want to dump the mapping. */
filename, obfd);
}
do_cleanups (cleanup);
return 0;
}
return 1;
}
/* A structure for passing information through
linux_find_memory_regions_full. */
@ -784,7 +1294,7 @@ struct linux_find_memory_regions_data
/* The original datum. */
void *data;
void *obfd;
};
/* A callback for linux_find_memory_regions that converts between the
@ -798,48 +1308,7 @@ 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->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);
return data->func (vaddr, size, read, write, exec, modified, data->obfd);
}
/* A variant of linux_find_memory_regions_full that is suitable as the
@ -847,15 +1316,16 @@ linux_find_memory_regions_gdb (struct gdbarch *gdbarch,
static int
linux_find_memory_regions (struct gdbarch *gdbarch,
find_memory_region_ftype func, void *func_data)
find_memory_region_ftype func, void *obfd)
{
struct linux_find_memory_regions_data data;
data.func = func;
data.data = func_data;
data.obfd = obfd;
return linux_find_memory_regions_gdb (gdbarch,
linux_find_memory_regions_thunk, &data);
return linux_find_memory_regions_full (gdbarch,
linux_find_memory_regions_thunk,
&data);
}
/* Determine which signal stopped execution. */
@ -1037,8 +1507,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_gdb (gdbarch, linux_make_mappings_callback,
&mapping_data);
linux_find_memory_regions_full (gdbarch, linux_make_mappings_callback,
&mapping_data);
if (mapping_data.file_count != 0)
{

View File

@ -1,493 +0,0 @@
/* 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"
#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;
}

View File

@ -1,64 +0,0 @@
/* 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 NAT_LINUX_MAPS_H
#define NAT_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 /* NAT_LINUX_MAPS_H */

View File

@ -634,5 +634,4 @@ _initialize_darwin_solib (void)
darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code;
darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol;
darwin_so_ops.bfd_open = darwin_bfd_open;
darwin_so_ops.validate = default_solib_validate;
}

View File

@ -1080,7 +1080,6 @@ _initialize_dsbt_solib (void)
dsbt_so_ops.open_symbol_file_object = open_symbol_file_object;
dsbt_so_ops.in_dynsym_resolve_code = dsbt_in_dynsym_resolve_code;
dsbt_so_ops.bfd_open = solib_bfd_open;
dsbt_so_ops.validate = default_solib_validate;
/* Debug this file's internals. */
add_setshow_zuinteger_cmd ("solib-dsbt", class_maintenance,

View File

@ -1183,7 +1183,6 @@ _initialize_frv_solib (void)
frv_so_ops.open_symbol_file_object = open_symbol_file_object;
frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code;
frv_so_ops.bfd_open = solib_bfd_open;
frv_so_ops.validate = default_solib_validate;
/* Debug this file's internals. */
add_setshow_zuinteger_cmd ("solib-frv", class_maintenance,

View File

@ -519,7 +519,6 @@ set_spu_solib_ops (struct gdbarch *gdbarch)
spu_so_ops.current_sos = spu_current_sos;
spu_so_ops.bfd_open = spu_bfd_open;
spu_so_ops.lookup_lib_global_symbol = spu_lookup_lib_symbol;
spu_so_ops.validate = default_solib_validate;
}
set_solib_ops (gdbarch, &spu_so_ops);

View File

@ -45,9 +45,6 @@
#include "auxv.h"
#include "gdb_bfd.h"
#include "probe.h"
#include "rsp-low.h"
#define NOTE_GNU_BUILD_ID_NAME ".note.gnu.build-id"
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
@ -973,64 +970,6 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
return (name_lm >= vaddr && name_lm < vaddr + size);
}
/* Validate SO by comparing build-id from the associated bfd and
corresponding build-id from target memory. Return NULL for success
or a string for error. Caller must call xfree for the error string. */
static char *
svr4_validate (const struct so_list *const so)
{
const bfd_byte *local_id;
size_t local_idsz;
gdb_assert (so != NULL);
/* Target doesn't support reporting the build ID or the remote shared library
does not have build ID. */
if (so->build_id == NULL)
return NULL;
/* Build ID may be present in the local file, just GDB is unable to retrieve
it. As it has been reported by gdbserver it is not FSF gdbserver. */
if (so->abfd == NULL
|| !bfd_check_format (so->abfd, bfd_object))
return NULL;
/* GDB has verified the local file really does not contain the build ID. */
if (so->abfd->build_id == NULL)
{
char *remote_hex;
remote_hex = alloca (so->build_idsz * 2 + 1);
bin2hex (so->build_id, remote_hex, so->build_idsz);
return xstrprintf (_("remote build ID is %s "
"but local file does not have build ID"),
remote_hex);
}
local_id = so->abfd->build_id->data;
local_idsz = so->abfd->build_id->size;
if (so->build_idsz != local_idsz
|| memcmp (so->build_id, local_id, so->build_idsz) != 0)
{
char *remote_hex, *local_hex;
remote_hex = alloca (so->build_idsz * 2 + 1);
bin2hex (so->build_id, remote_hex, so->build_idsz);
local_hex = alloca (local_idsz * 2 + 1);
bin2hex (local_id, local_hex, local_idsz);
return xstrprintf (_("remote build ID %s "
"does not match local build ID %s"),
remote_hex, local_hex);
}
/* Both build IDs are present and they match. */
return NULL;
}
/* Implement the "open_symbol_file_object" target_so_ops method.
If no open symbol file, attempt to locate and open the main symbol
@ -1169,12 +1108,6 @@ 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;
@ -1202,9 +1135,6 @@ 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);
@ -1216,37 +1146,6 @@ 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;
@ -1281,7 +1180,6 @@ 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 }
};
@ -3360,5 +3258,4 @@ _initialize_svr4_solib (void)
svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
svr4_so_ops.handle_event = svr4_handle_solib_event;
svr4_so_ops.validate = svr4_validate;
}

View File

@ -25,7 +25,6 @@
#include "target.h"
#include "vec.h"
#include "solib-target.h"
#include "solib.h"
/* Private data for each loaded library. */
struct lm_info
@ -507,7 +506,6 @@ _initialize_solib_target (void)
solib_target_so_ops.in_dynsym_resolve_code
= solib_target_in_dynsym_resolve_code;
solib_target_so_ops.bfd_open = solib_bfd_open;
solib_target_so_ops.validate = default_solib_validate;
/* Set current_target_so_ops to solib_target_so_ops if not already
set. */

View File

@ -518,20 +518,6 @@ solib_bfd_open (char *pathname)
return abfd;
}
/* Boolean for command 'set validate-build-id'. */
static 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);
}
/* Given a pointer to one of the shared objects in our list of mapped
objects, use the recorded name to open a bfd descriptor for the
object, build a section table, relocate all the section addresses
@ -548,7 +534,7 @@ static int
solib_map_sections (struct so_list *so)
{
const struct target_so_ops *ops = solib_ops (target_gdbarch ());
char *filename, *validate_error;
char *filename;
struct target_section *p;
struct cleanup *old_chain;
bfd *abfd;
@ -564,29 +550,6 @@ solib_map_sections (struct so_list *so)
/* Leave bfd open, core_xfer_memory and "info files" need it. */
so->abfd = abfd;
gdb_assert (ops->validate != NULL);
validate_error = ops->validate (so);
if (validate_error != NULL)
{
if (validate_build_id)
{
warning (_("Shared object \"%s\" could not be validated (%s) and "
"will be ignored; "
"or use 'set validate-build-id off'."),
so->so_name, validate_error);
xfree (validate_error);
gdb_bfd_unref (so->abfd);
so->abfd = NULL;
return 0;
}
warning (_("Shared object \"%s\" could not be validated (%s) "
"but it is being loaded due to "
"'set validate-build-id off'."),
so->so_name, validate_error);
xfree (validate_error);
}
/* Copy the full path name into so_name, allowing symbol_file_add
to find it later. This also affects the =library-loaded GDB/MI
event, and in particular the part of that notification providing
@ -663,9 +626,6 @@ clear_so (struct so_list *so)
of the symbol file. */
strcpy (so->so_name, so->so_original_name);
xfree (so->build_id);
so->build_id = NULL;
/* Do the same for target-specific data. */
if (ops->clear_so != NULL)
ops->clear_so (so);
@ -1697,14 +1657,6 @@ remove_user_added_objfile (struct objfile *objfile)
}
}
/* Default implementation does not perform any validation. */
char *
default_solib_validate (const struct so_list *const so)
{
return NULL; /* No validation. */
}
extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
void
@ -1762,18 +1714,4 @@ PATH and LD_LIBRARY_PATH."),
reload_shared_libraries,
show_solib_search_path,
&setlist, &showlist);
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);
}

View File

@ -98,8 +98,4 @@ extern void update_solib_breakpoints (void);
extern void handle_solib_event (void);
/* Default validation always returns 1. */
extern char *default_solib_validate (const struct so_list *so);
#endif /* SOLIB_H */

View File

@ -75,19 +75,6 @@ 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
@ -181,11 +168,6 @@ struct target_so_ops
NULL, in which case no specific preprocessing is necessary
for this target. */
void (*handle_event) (void);
/* Return NULL if SO does match target SO it is supposed to
represent. Otherwise return string describing why it does not match.
Caller has to free the string. */
char *(*validate) (const struct so_list *so);
};
/* Free the memory associated with a (so_list *). */

View File

@ -43,7 +43,6 @@
#include "agent.h"
#include "auxv.h"
#include "target-debug.h"
#include "target/target-utils.h"
static void target_info (char *, int);
@ -2974,17 +2973,6 @@ target_fileio_close_cleanup (void *opaque)
target_fileio_close (fd, &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
@ -2998,17 +2986,58 @@ 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;
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);
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;
/* 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 = target_fileio_pread (fd, &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)
xfree (buf);
else
*buf_p = buf;
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);
}
QUIT;
}
}
/* See target.h. */
@ -3020,14 +3049,40 @@ target_fileio_read_alloc (struct inferior *inf, const char *filename,
return target_fileio_read_alloc_1 (inf, filename, buf_p, 0);
}
/* See target/target.h. */
/* See target.h. */
char *
target_fileio_read_stralloc (struct inferior *inf, const char *filename)
{
return read_stralloc (inf, filename, target_fileio_read_alloc_1);
gdb_byte *buffer;
char *bufstr;
LONGEST i, transferred;
transferred = target_fileio_read_alloc_1 (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;
}
static int
default_region_ok_for_hw_watchpoint (struct target_ops *self,
CORE_ADDR addr, int len)

View File

@ -2033,6 +2033,16 @@ 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. */

View File

@ -1,100 +0,0 @@
/* 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"
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;
}

View File

@ -1,35 +0,0 @@
/* 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
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 */

View File

@ -70,15 +70,4 @@ 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 */

View File

@ -1,3 +1,8 @@
2015-07-15 Jan Kratochvil <jan.kratochvil@redhat.com>
Revert the previous commit:
Tests for validate symbol file using build-id.
2015-07-15 Aleksandar Ristovski <aristovski@qnx.com
Tests for validate symbol file using build-id.

View File

@ -1,30 +0,0 @@
/* 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;
}

View File

@ -1,30 +0,0 @@
/* 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();
}

View File

@ -1,56 +0,0 @@
/* 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;
}

View File

@ -1,156 +0,0 @@
# 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"
}

View File

@ -67,6 +67,7 @@
#include "gdb_usleep.h"
#include "interps.h"
#include "gdb_regex.h"
#if !HAVE_DECL_MALLOC
extern PTR malloc (); /* ARI: PTR */
@ -1113,6 +1114,60 @@ make_hex_string (const gdb_byte *data, size_t length)
/* 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);
}
/* 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