diff options
Diffstat (limited to 'gdb/common')
-rw-r--r-- | gdb/common/common-defs.h | 3 | ||||
-rw-r--r-- | gdb/common/gdb_tilde_expand.c | 13 | ||||
-rw-r--r-- | gdb/common/gdb_tilde_expand.h | 4 | ||||
-rw-r--r-- | gdb/common/pathstuff.c | 142 | ||||
-rw-r--r-- | gdb/common/pathstuff.h | 49 |
5 files changed, 211 insertions, 0 deletions
diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h index acbc32c..881a4ea 100644 --- a/gdb/common/common-defs.h +++ b/gdb/common/common-defs.h @@ -91,4 +91,7 @@ /* Pull in gdb::unique_xmalloc_ptr. */ #include "common/gdb_unique_ptr.h" +/* String containing the current directory (what getwd would return). */ +extern char *current_directory; + #endif /* COMMON_DEFS_H */ diff --git a/gdb/common/gdb_tilde_expand.c b/gdb/common/gdb_tilde_expand.c index b4f3714..fcb9796 100644 --- a/gdb/common/gdb_tilde_expand.c +++ b/gdb/common/gdb_tilde_expand.c @@ -80,3 +80,16 @@ gdb_tilde_expand (const char *dir) return expanded_dir; } + +/* See common/gdb_tilde_expand.h. */ + +gdb::unique_xmalloc_ptr<char> +gdb_tilde_expand_up (const char *dir) +{ + gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL); + + gdb_assert (glob.pathc () > 0); + /* "glob" may return more than one match to the path provided by the + user, but we are only interested in the first match. */ + return gdb::unique_xmalloc_ptr<char> (xstrdup (glob.pathv ()[0])); +} diff --git a/gdb/common/gdb_tilde_expand.h b/gdb/common/gdb_tilde_expand.h index d0dfb37..22860d3 100644 --- a/gdb/common/gdb_tilde_expand.h +++ b/gdb/common/gdb_tilde_expand.h @@ -24,4 +24,8 @@ the full path. */ extern std::string gdb_tilde_expand (const char *dir); +/* Same as GDB_TILDE_EXPAND, but return the full path as a + gdb::unique_xmalloc_ptr<char>. */ +extern gdb::unique_xmalloc_ptr<char> gdb_tilde_expand_up (const char *dir); + #endif /* ! GDB_TILDE_EXPAND_H */ diff --git a/gdb/common/pathstuff.c b/gdb/common/pathstuff.c new file mode 100644 index 0000000..02f6e44 --- /dev/null +++ b/gdb/common/pathstuff.c @@ -0,0 +1,142 @@ +/* Path manipulation routines for GDB and gdbserver. + + Copyright (C) 1986-2018 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 "pathstuff.h" +#include "host-defs.h" +#include "filenames.h" +#include "gdb_tilde_expand.h" + +/* See common/pathstuff.h. */ + +gdb::unique_xmalloc_ptr<char> +gdb_realpath (const char *filename) +{ +/* On most hosts, we rely on canonicalize_file_name to compute + the FILENAME's realpath. + + But the situation is slightly more complex on Windows, due to some + versions of GCC which were reported to generate paths where + backlashes (the directory separator) were doubled. For instance: + c:\\some\\double\\slashes\\dir + ... instead of ... + c:\some\double\slashes\dir + Those double-slashes were getting in the way when comparing paths, + for instance when trying to insert a breakpoint as follow: + (gdb) b c:/some/double/slashes/dir/foo.c:4 + No source file named c:/some/double/slashes/dir/foo.c:4. + (gdb) b c:\some\double\slashes\dir\foo.c:4 + No source file named c:\some\double\slashes\dir\foo.c:4. + To prevent this from happening, we need this function to always + strip those extra backslashes. While canonicalize_file_name does + perform this simplification, it only works when the path is valid. + Since the simplification would be useful even if the path is not + valid (one can always set a breakpoint on a file, even if the file + does not exist locally), we rely instead on GetFullPathName to + perform the canonicalization. */ + +#if defined (_WIN32) + { + char buf[MAX_PATH]; + DWORD len = GetFullPathName (filename, MAX_PATH, buf, NULL); + + /* The file system is case-insensitive but case-preserving. + So it is important we do not lowercase the path. Otherwise, + we might not be able to display the original casing in a given + path. */ + if (len > 0 && len < MAX_PATH) + return gdb::unique_xmalloc_ptr<char> (xstrdup (buf)); + } +#else + { + char *rp = canonicalize_file_name (filename); + + if (rp != NULL) + return gdb::unique_xmalloc_ptr<char> (rp); + } +#endif + + /* This system is a lost cause, just dup the buffer. */ + return gdb::unique_xmalloc_ptr<char> (xstrdup (filename)); +} + +/* See common/pathstuff.h. */ + +gdb::unique_xmalloc_ptr<char> +gdb_realpath_keepfile (const char *filename) +{ + const char *base_name = lbasename (filename); + char *dir_name; + char *result; + + /* Extract the basename of filename, and return immediately + a copy of filename if it does not contain any directory prefix. */ + if (base_name == filename) + return gdb::unique_xmalloc_ptr<char> (xstrdup (filename)); + + dir_name = (char *) alloca ((size_t) (base_name - filename + 2)); + /* Allocate enough space to store the dir_name + plus one extra + character sometimes needed under Windows (see below), and + then the closing \000 character. */ + strncpy (dir_name, filename, base_name - filename); + dir_name[base_name - filename] = '\000'; + +#ifdef HAVE_DOS_BASED_FILE_SYSTEM + /* We need to be careful when filename is of the form 'd:foo', which + is equivalent of d:./foo, which is totally different from d:/foo. */ + if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':') + { + dir_name[2] = '.'; + dir_name[3] = '\000'; + } +#endif + + /* Canonicalize the directory prefix, and build the resulting + filename. If the dirname realpath already contains an ending + directory separator, avoid doubling it. */ + gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name); + const char *real_path = path_storage.get (); + if (IS_DIR_SEPARATOR (real_path[strlen (real_path) - 1])) + result = concat (real_path, base_name, (char *) NULL); + else + result = concat (real_path, SLASH_STRING, base_name, (char *) NULL); + + return gdb::unique_xmalloc_ptr<char> (result); +} + +/* See common/pathstuff.h. */ + +gdb::unique_xmalloc_ptr<char> +gdb_abspath (const char *path) +{ + gdb_assert (path != NULL && path[0] != '\0'); + + if (path[0] == '~') + return gdb_tilde_expand_up (path); + + if (IS_ABSOLUTE_PATH (path)) + return gdb::unique_xmalloc_ptr<char> (xstrdup (path)); + + /* Beware the // my son, the Emacs barfs, the botch that catch... */ + return gdb::unique_xmalloc_ptr<char> + (concat (current_directory, + IS_DIR_SEPARATOR (current_directory[strlen (current_directory) - 1]) + ? "" : SLASH_STRING, + path, (char *) NULL)); +} diff --git a/gdb/common/pathstuff.h b/gdb/common/pathstuff.h new file mode 100644 index 0000000..3cb02c8 --- /dev/null +++ b/gdb/common/pathstuff.h @@ -0,0 +1,49 @@ +/* Path manipulation routines for GDB and gdbserver. + + Copyright (C) 1986-2018 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 PATHSTUFF_H +#define PATHSTUFF_H + +/* Path utilities. */ + +/* Return the real path of FILENAME, expanding all the symbolic links. + + Contrary to "gdb_abspath", this function does not use + CURRENT_DIRECTORY for path expansion. Instead, it relies on the + current working directory (CWD) of GDB or gdbserver. */ + +extern gdb::unique_xmalloc_ptr<char> gdb_realpath (const char *filename); + +/* Return a copy of FILENAME, with its directory prefix canonicalized + by gdb_realpath. */ + +extern gdb::unique_xmalloc_ptr<char> + gdb_realpath_keepfile (const char *filename); + +/* Return PATH in absolute form, performing tilde-expansion if necessary. + PATH cannot be NULL or the empty string. + This does not resolve symlinks however, use gdb_realpath for that. + + Contrary to "gdb_realpath", this function uses CURRENT_DIRECTORY + for the path expansion. This may lead to scenarios the current + working directory (CWD) is different than CURRENT_DIRECTORY. */ + +extern gdb::unique_xmalloc_ptr<char> gdb_abspath (const char *path); + +#endif /* PATHSTUFF_H */ |