+ * 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.
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
}
}
-/* 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
}
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;
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>
--- /dev/null
+# 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}"
+ }
+}
}
}
+# 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.
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\
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,
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);
\f
/* GDB output, ui_file utilities. */