summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDoug Evans <dje@google.com>2015-12-10 12:00:33 -0800
committerDoug Evans <dje@google.com>2015-12-10 12:00:33 -0800
commit99f46b49a70e508b1ef801e0cf85304ffc5bfb43 (patch)
tree3fe57b4ef2960021ca5825cec0216008141ac713
parent6dc3050775f42a9e9877d967aa81cf9af161da85 (diff)
downloadbinutils-gdb-99f46b49a70e508b1ef801e0cf85304ffc5bfb43.tar.gz
patch ../102438704.patch
-rw-r--r--README.google20
-rw-r--r--gdb/completer.c11
-rw-r--r--gdb/main.c121
-rw-r--r--gdb/testsuite/ChangeLog4
-rw-r--r--gdb/testsuite/gdb.base/relocatable.exp161
-rw-r--r--gdb/testsuite/lib/gdb.exp66
-rw-r--r--gdb/top.c3
-rw-r--r--gdb/utils.c22
-rw-r--r--gdb/utils.h8
9 files changed, 364 insertions, 52 deletions
diff --git a/README.google b/README.google
index 6bd979ae4e6..6967900a33e 100644
--- a/README.google
+++ b/README.google
@@ -409,3 +409,23 @@ they are an ongoing maintenance burden.
+ * gdb.python/py-post-init.c: New file.
+ * gdb.python/py-post-init.exp: New file.
+ * gdb.python/py-post-init.py: New file.
+--- README.google 2015-09-06 00:43:48.000000000 -0700
++++ README.google 2015-09-06 00:49:09.000000000 -0700
++
++2015-09-05 Doug Evans <dje@google.com>
++
++ * completer.c (gdb_path_isdir): Move to ...
++ * utils.c (gdb_path_isdir): ... here.
++ (gdb_path_isfile): New function.
++ * utils.h (gdb_path_isdir): Declare.
++ (gdb_path_isfile): Declare.
++ * main.c (relocate_gdb_file): Renamed from relocate_path.
++ Try both make_relative_prefix and make_relative_prefix_ignore_symlinks.
++ All callers updated.
++ (maybe_lrealpath): New function.
++ (relocate_gdb_directory: Try both make_relative_prefix and
++ make_relative_prefix_ignore_symlinks.
++ * top.c (print_gdb_configuration): Print BINDIR.
++
++ testsuite/
++ * gdb.base/relocatable.exp: New file.
diff --git a/gdb/completer.c b/gdb/completer.c
index d55853cedb5..c506aecebf3 100644
--- a/gdb/completer.c
+++ b/gdb/completer.c
@@ -1285,17 +1285,6 @@ gdb_display_match_list_pager (int lines,
return 0;
}
-/* Return non-zero if FILENAME is a directory.
- Based on readline/complete.c:path_isdir. */
-
-static int
-gdb_path_isdir (const char *filename)
-{
- struct stat finfo;
-
- return (stat (filename, &finfo) == 0 && S_ISDIR (finfo.st_mode));
-}
-
/* Return the portion of PATHNAME that should be output when listing
possible completions. If we are hacking filename completion, we
are only interested in the basename, the portion following the
diff --git a/gdb/main.c b/gdb/main.c
index a87a09b8819..76a6f8836ae 100644
--- a/gdb/main.c
+++ b/gdb/main.c
@@ -138,58 +138,97 @@ set_gdb_data_directory (const char *new_datadir)
}
}
-/* Relocate a file or directory. PROGNAME is the name by which gdb
- was invoked (i.e., argv[0]). INITIAL is the default value for the
- file or directory. FLAG is true if the value is relocatable, false
- otherwise. Returns a newly allocated string; this may return NULL
- under the same conditions as make_relative_prefix. */
+/* Relocate a file.
+ INITIAL is the default value of the file.
+ FLAG is true if the value is relocatable, false otherwise.
+ Returns a newly allocated string; this may return NULL
+ under the same conditions as gdb_make_relative_prefix. */
static char *
-relocate_path (const char *progname, const char *initial, int flag)
+relocate_gdb_file (const char *initial, int flag)
{
- if (flag)
- return make_relative_prefix (progname, BINDIR, initial);
+ char *path;
+
+ /* Early exit if there's nothing we can do. */
+ if (!flag)
+ return xstrdup (initial);
+
+ /* We have to try both make_relative_prefix and
+ make_relative_prefix_ignore_links. The first handles a symlink to
+ gdb where it is installed. The second handles the case where the
+ installation tree is itself a collection of symlinks to random places.
+ Alas we can't distinguish a NULL return from make_relative_prefix*
+ due to lack of memory or due to failure to find a common prefix.
+ make_relative_prefix is tried first for backward compatibility. Ugh. */
+
+ path = make_relative_prefix (gdb_program_name, BINDIR, initial);
+ if (path != NULL && gdb_path_isfile (path))
+ return path;
+ xfree (path);
+ path = make_relative_prefix_ignore_links (gdb_program_name, BINDIR, initial);
+ if (path != NULL && gdb_path_isfile (path))
+ return path;
+ xfree (path);
return xstrdup (initial);
}
-/* Like relocate_path, but specifically checks for a directory.
- INITIAL is relocated according to the rules of relocate_path. If
- the result is a directory, it is used; otherwise, INITIAL is used.
- The chosen directory is then canonicalized using lrealpath. This
- function always returns a newly-allocated string. */
+/* Return the lrealpath form of PATH.
+ Space for PATH must have been malloc'd.
+ PATH is freed if the lrealpath'd form is different. */
-char *
-relocate_gdb_directory (const char *initial, int flag)
+static char *
+maybe_lrealpath (char *path)
{
- char *dir;
+ char *canon;
- dir = relocate_path (gdb_program_name, initial, flag);
- if (dir)
- {
- struct stat s;
+ if (*path == '\0')
+ return path;
- if (*dir == '\0' || stat (dir, &s) != 0 || !S_ISDIR (s.st_mode))
- {
- xfree (dir);
- dir = NULL;
- }
+ canon = lrealpath (path);
+ if (canon != NULL)
+ {
+ xfree (path);
+ path = canon;
}
- if (!dir)
- dir = xstrdup (initial);
- /* Canonicalize the directory. */
- if (*dir)
- {
- char *canon_sysroot = lrealpath (dir);
+ return path;
+}
- if (canon_sysroot)
- {
- xfree (dir);
- dir = canon_sysroot;
- }
- }
+/* Relocate a directory.
+ INITIAL is the default value of the directory.
+ FLAG is true if the value is relocatable, false otherwise.
+ If the result is a directory, it is used; otherwise, INITIAL is used.
+ The chosen directory is then canonicalized using lrealpath. This
+ function always returns a newly-allocated string. */
+
+char *
+relocate_gdb_directory (const char *initial, int flag)
+{
+ char *dir;
- return dir;
+ /* Early exit if there's nothing we can do. */
+ if (initial[0] == '\0')
+ return xstrdup ("");
+ if (!flag)
+ return maybe_lrealpath (xstrdup (initial));
+
+ /* We have to try both make_relative_prefix and
+ make_relative_prefix_ignore_links. The first handles a symlink to
+ gdb where it is installed. The second handles the case where the
+ installation tree is itself a collection of symlinks to random places.
+ Alas we can't distinguish a NULL return from make_relative_prefix*
+ due to lack of memory or due to failure to find a common prefix. Ugh.
+ make_relative_prefix is tried first for backward compatibility. */
+
+ dir = make_relative_prefix (gdb_program_name, BINDIR, initial);
+ if (dir != NULL && gdb_path_isdir (dir))
+ return maybe_lrealpath (dir);
+ xfree (dir);
+ dir = make_relative_prefix_ignore_links (gdb_program_name, BINDIR, initial);
+ if (gdb_path_isdir (dir))
+ return maybe_lrealpath (dir);
+ xfree (dir);
+ return maybe_lrealpath (xstrdup (initial));
}
/* Compute the locations of init files that GDB should source and
@@ -238,9 +277,9 @@ get_init_files (const char **system_gdbinit,
}
else
{
- relocated_sysgdbinit = relocate_path (gdb_program_name,
- SYSTEM_GDBINIT,
- SYSTEM_GDBINIT_RELOCATABLE);
+ relocated_sysgdbinit
+ = relocate_gdb_file (SYSTEM_GDBINIT,
+ SYSTEM_GDBINIT_RELOCATABLE);
}
if (relocated_sysgdbinit && stat (relocated_sysgdbinit, &s) == 0)
sysgdbinit = relocated_sysgdbinit;
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index dd253e3b06c..6312d4c551c 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -21,6 +21,10 @@
gdb.base/dso2dso-dso1.c, gdb.base/dso2dso-dso1.h, gdb.base/dso2dso.c,
gdb.base/dso2dso.exp: New files.
+2015-08-12 Patrick Palka <patrick@parcs.ath.cx>
+
+ * lib/gdb.exp (save_vars): New proc.
+
2015-08-10 Doug Evans <dje@google.com>
Keith Seitz <keiths@redhat.com>
diff --git a/gdb/testsuite/gdb.base/relocatable.exp b/gdb/testsuite/gdb.base/relocatable.exp
new file mode 100644
index 00000000000..263215c7b67
--- /dev/null
+++ b/gdb/testsuite/gdb.base/relocatable.exp
@@ -0,0 +1,161 @@
+# 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/>.
+
+# Test gdb's handling of relocatability.
+# This only works if gdb was configured to be relocatable.
+# We can't rebuild gdb just for this test, but we can check whether
+# the built gdb is relocatable and if so then run the tests.
+
+# It's not clear what systems this test will work on.
+# For now pick the ones we know will work.
+if {![istarget *-*-linux*]
+ || [is_remote host]} {
+ return 0
+}
+
+gdb_exit
+gdb_start
+set config [capture_command_output "show config" ""]
+
+regsub "^.*(--bindir=\[\^\r\n\]+).*$" $config "\\1" bindir_text
+regsub "^.*(--with-gdb-datadir=\[\^\r\n\]+).*$" $config "\\1" datadir_text
+
+verbose -log "bindir_text: $bindir_text"
+verbose -log "datadir_text: $datadir_text"
+
+if { [string first " (relocatable)" $datadir_text] < 0 } {
+ unsupported "gdb not relocatable"
+ return 0
+}
+
+regsub "^--bindir=" $bindir_text "" bindir
+regsub "^--with-gdb-datadir=" $datadir_text "" datadir
+regsub " \\(relocatable\\)" $datadir "" datadir
+
+verbose -log "bindir: $bindir"
+verbose -log "datadir: $datadir"
+
+set env_program "env" ;# TODO: gdb_find_env
+set make_program "make" ;# TODO: gdb_find_make
+
+# Run "make install" to install gdb in INSTALL_DIR.
+# The result is zero for success, non-zero for failure.
+
+proc make_install { install_dir } {
+ global env_program
+ global make_program
+
+ file delete -force -- $install_dir
+
+ # If invoked from make check-parallel, several env vars are set up which
+ # will confuse this make, so unset them.
+ set env_options "-u MAKELEVEL -u MAKEFLAGS -u MFLAGS -u MAKEOVERRIDES"
+
+ # We don't need to install the docs or gdbserver, just gdb.
+ # And we don't want to cause a rebuild of gdb, so use install-only.
+ set make_options "-C .. install-only SUBDIRS=data-directory DESTDIR=$install_dir"
+
+ set cmd "$env_program $env_options $make_program $make_options"
+ verbose -log "Executing: $cmd"
+ set result [catch "exec $cmd" output]
+
+ verbose -log "result is $result"
+ verbose -log "output is $output"
+
+ set test "make install"
+ if { $result != 0 } {
+ fail $test
+ } else {
+ pass $test
+ }
+ return $result
+}
+
+proc start_and_check_data_dir { gdb_path expected_data_dir } {
+ global GDB INTERNAL_GDBFLAGS
+ save_vars { GDB INTERNAL_GDBFLAGS } {
+ set GDB $gdb_path
+ # We want this gdb to find its installed data-directory, so don't
+ # pass it one.
+ regsub -- "-data-directory \[^ \]+" $INTERNAL_GDBFLAGS "" INTERNAL_GDBFLAGS
+ gdb_exit
+ gdb_start
+ set datadir_in_gdb [capture_command_output "show data-dir" ""]
+ regsub "^GDB's data directory is \"" $datadir_in_gdb "" datadir_in_gdb
+ regsub "\".\[\r\n\]+$" $datadir_in_gdb "" datadir_in_gdb
+ set test "data-dir updated correctly"
+ if { $datadir_in_gdb == $expected_data_dir } {
+ pass $test
+ } else {
+ fail $test
+ }
+ }
+}
+
+# Move all files (and directories) from from_dir to to_dir and leave behind
+# symlinks pointing to the new location.
+
+proc move_and_leave_symlinks { from_dir to_dir } {
+ file delete -force -- $to_dir
+ file mkdir $to_dir
+ set files [glob -tails -directory $from_dir *]
+ foreach f $files {
+ file copy -- "${from_dir}/$f" "${to_dir}"
+ file delete -force -- "${from_dir}/$f"
+ file link -symbolic "${from_dir}/$f" "${to_dir}/$f"
+ }
+}
+
+# First test the case where gdb is a symlink to its installed copy.
+# This exercises make_relative_prefix (where we need to call lrealname
+# on gdb's argv[0] in order to establish our location).
+
+with_test_prefix "realpath_symlinks" {
+ set install_dir [standard_output_file make_relative_prefix]
+
+ if { [make_install $install_dir] == 0 } {
+ set linked_gdb [standard_output_file ${install_dir}/gdb]
+ file delete -force -- "${linked_gdb}"
+ file link -symbolic "${linked_gdb}" ".${bindir}/gdb"
+
+ start_and_check_data_dir $linked_gdb "${install_dir}${datadir}"
+ }
+}
+
+# Second test is having the install tree being a set of symlinks pointing
+# to (essentially) random places
+# This exercises make_relative_prefix_ignore_links (where calling lrealname on
+# gdb's argv[0] is the wrong thing to do).
+
+with_test_prefix "ignore_symlinks" {
+ set install_dir [standard_output_file make_relative_prefix_ignore_links]
+
+ if { [make_install $install_dir] == 0 } {
+ # Now that we've created an install tree, move bindir and datadir to
+ # "random" places and create symlinks in their place.
+
+ set install_bindir "${install_dir}${bindir}"
+ set install_datadir "${install_dir}${datadir}"
+
+ set random_bindir "${install_dir}/random1/bindir"
+ set random_datadir "${install_dir}/random2/datadir"
+
+ move_and_leave_symlinks $install_bindir $random_bindir
+ move_and_leave_symlinks $install_datadir $random_datadir
+
+ start_and_check_data_dir ${install_bindir}/gdb \
+ "${install_dir}${datadir}"
+ }
+}
diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp
index f74d1220201..730f878281f 100644
--- a/gdb/testsuite/lib/gdb.exp
+++ b/gdb/testsuite/lib/gdb.exp
@@ -1835,6 +1835,72 @@ proc with_test_prefix { prefix body } {
}
}
+# Run BODY in the context of the caller. After BODY is run, the variables
+# listed in VARS will be reset to the values they had before BODY was run.
+#
+# This is useful for providing a scope in which it is safe to temporarily
+# modify global variables, e.g.
+#
+# global INTERNAL_GDBFLAGS
+# global env
+#
+# set foo GDBHISTSIZE
+#
+# save_vars { INTERNAL_GDBFLAGS env($foo) env(HOME) } {
+# append INTERNAL_GDBFLAGS " -nx"
+# unset -nocomplain env(GDBHISTSIZE)
+# gdb_start
+# gdb_test ...
+# }
+#
+# Here, although INTERNAL_GDBFLAGS, env(GDBHISTSIZE) and env(HOME) may be
+# modified inside BODY, this proc guarantees that the modifications will be
+# undone after BODY finishes executing.
+
+proc save_vars { vars body } {
+ array set saved_scalars { }
+ array set saved_arrays { }
+ set unset_vars { }
+
+ foreach var $vars {
+ # First evaluate VAR in the context of the caller in case the variable
+ # name may be a not-yet-interpolated string like env($foo)
+ set var [uplevel 1 list $var]
+
+ if [uplevel 1 [list info exists $var]] {
+ if [uplevel 1 [list array exists $var]] {
+ set saved_arrays($var) [uplevel 1 [list array get $var]]
+ } else {
+ set saved_scalars($var) [uplevel 1 [list set $var]]
+ }
+ } else {
+ lappend unset_vars $var
+ }
+ }
+
+ set code [catch {uplevel 1 $body} result]
+
+ foreach {var value} [array get saved_scalars] {
+ uplevel 1 [list set $var $value]
+ }
+
+ foreach {var value} [array get saved_arrays] {
+ uplevel 1 [list unset $var]
+ uplevel 1 [list array set $var $value]
+ }
+
+ foreach var $unset_vars {
+ uplevel 1 [list unset -nocomplain $var]
+ }
+
+ if {$code == 1} {
+ global errorInfo errorCode
+ return -code $code -errorinfo $errorInfo -errorcode $errorCode $result
+ } else {
+ return -code $code $result
+ }
+}
+
# Run tests in BODY with GDB prompt and variable $gdb_prompt set to
# PROMPT. When BODY is finished, restore GDB prompt and variable
# $gdb_prompt.
diff --git a/gdb/top.c b/gdb/top.c
index 01fddd2c95f..988dd3b665f 100644
--- a/gdb/top.c
+++ b/gdb/top.c
@@ -1284,6 +1284,9 @@ This GDB was configured as follows:\n\
configure --host=%s --target=%s\n\
"), host_name, target_name);
fprintf_filtered (stream, _("\
+ --bindir=%s\n\
+"), BINDIR);
+ fprintf_filtered (stream, _("\
--with-auto-load-dir=%s\n\
--with-auto-load-safe-path=%s\n\
"), AUTO_LOAD_DIR, AUTO_LOAD_SAFE_PATH);
diff --git a/gdb/utils.c b/gdb/utils.c
index b25216cecf3..80b009c5935 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3057,6 +3057,28 @@ ldirname (const char *filename)
return dirname;
}
+/* See utils.h.
+ Based on readline/complete.c:path_isdir. */
+
+int
+gdb_path_isdir (const char *path)
+{
+ struct stat s;
+
+ return stat (path, &s) == 0 && S_ISDIR (s.st_mode);
+}
+
+/* See utils.h.
+ Based on readline/complete.c:path_isdir. */
+
+int
+gdb_path_isfile (const char *path)
+{
+ struct stat s;
+
+ return stat (path, &s) == 0 && S_ISREG (s.st_mode);
+}
+
/* Call libiberty's buildargv, and return the result.
If buildargv fails due to out-of-memory, call nomem.
Therefore, the returned value is guaranteed to be non-NULL,
diff --git a/gdb/utils.h b/gdb/utils.h
index 995a1cfb8ef..0adb097464b 100644
--- a/gdb/utils.h
+++ b/gdb/utils.h
@@ -135,6 +135,14 @@ extern void substitute_path_component (char **stringp, const char *from,
const char *to);
char *ldirname (const char *filename);
+
+/* Return non-zero if PATH is a directory. */
+
+extern int gdb_path_isdir (const char *path);
+
+/* Return non-zero if PATH is a plain file. */
+
+extern int gdb_path_isfile (const char *path);
/* GDB output, ui_file utilities. */