[PATCH 1/5] Introduce build_debug_file_name

Gary Benson
2015-06-16T09:42:56Z

This commit introduces a new function build_debug_file_name which
concatenates a series of filename components into a filename.
find_separate_debug_file is updated to use build_debug_file_name.
A later commit in this series will extend build_debug_file_name
to correctly handle "target:" prefixes, so it is convenient to
have filename building pulled out into one function. For now the
only functional change here is that the original code sometimes
generated filenames with repeated directory separators while the
new code does not.

gdb/ChangeLog:

* gdb/symfile.c (build_debug_file_name): New function.
(find_separate_debug_file): Use the above to build filenames.
---
gdb/ChangeLog | 5 ++
gdb/symfile.c | 117 +++++++++++++++++++++++++++++++++++++++++---------------
2 files changed, 90 insertions(+), 32 deletions(-)

diff --git a/gdb/symfile.c b/gdb/symfile.c
index 0c35ffa..799133a 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -1431,6 +1431,79 @@ separate_debug_file_exists (const char *name, unsigned long crc,
return 1;
}

+/* Build the filename of a separate debug file from an arbitrary
+ number of components. Returns an xmalloc'd string that must
+ be be freed by the caller. The final argument of this function
+ must be NULL to mark the end the argument list. */
+
+static char *
+build_debug_file_name (const char *first, ...)
+{
+ va_list ap;
+ const char *arg, *last;
+ VEC (char_ptr) *args = NULL;
+ struct cleanup *back_to = make_cleanup_free_char_ptr_vec (args);
+ int bufsiz = 0;
+ char *buf, *tmp;
+ int i;
+
+ va_start (ap, first);
+ for (arg = first; arg; arg = va_arg (ap, const char *))
+ last = arg;
+ va_end (ap);
+
+ va_start (ap, first);
+ for (arg = first; arg; arg = va_arg (ap, const char *))
+ {
+ if (arg == last)
+ tmp = xstrdup (arg);
+ else
+ {
+ int len;
+
+ /* Strip leading separators from subdirectories. */
+ if (arg != first)
+ {
+ while (*arg != '\0' && IS_DIR_SEPARATOR (*arg))
+ arg++;
+ }
+
+ /* Strip trailing separators. */
+ len = strlen (arg);
+
+ while (len > 0 && IS_DIR_SEPARATOR (arg[len - 1]))
+ len--;
+
+ if (len > 0)
+ {
+ tmp = xmalloc (len + strlen (SLASH_STRING) + 1);
+ memcpy (tmp, arg, len);
+ strcpy (tmp + len, SLASH_STRING);
+ }
+ else
+ tmp = NULL;
+ }
+
+ if (tmp != NULL)
+ {
+ VEC_safe_push (char_ptr, args, tmp);
+ bufsiz += strlen (tmp);
+ }
+ }
+ va_end (ap);
+
+ bufsiz += 1; /* Terminator. */
+
+ buf = xmalloc (bufsiz);
+ buf[0] = '\0';
+ for (i = 0; VEC_iterate (char_ptr, args, i, tmp); i++)
+ strcat (buf, tmp);
+ gdb_assert (bufsiz == strlen (buf) + 1);
+
+ do_cleanups (back_to);
+ return buf;
+}
+
char *debug_file_directory = NULL;
static void
show_debug_file_directory (struct ui_file *file, int from_tty,
@@ -1461,38 +1534,22 @@ find_separate_debug_file (const char *dir,
{
char *debugdir;
char *debugfile;
- int i;
VEC (char_ptr) *debugdir_vec;
struct cleanup *back_to;
int ix;

- /* Set I to max (strlen (canon_dir), strlen (dir)). */
- i = strlen (dir);
- if (canon_dir != NULL && strlen (canon_dir) > i)
- i = strlen (canon_dir);
-
- debugfile = xmalloc (strlen (debug_file_directory) + 1
- + i
- + strlen (DEBUG_SUBDIRECTORY)
- + strlen ("/")
- + strlen (debuglink)
- + 1);
-
/* First try in the same directory as the original file. */
- strcpy (debugfile, dir);
- strcat (debugfile, debuglink);
-
+ debugfile = build_debug_file_name (dir, debuglink, NULL);
if (separate_debug_file_exists (debugfile, crc32, objfile))
return debugfile;
+ xfree (debugfile);

/* Then try in the subdirectory named DEBUG_SUBDIRECTORY. */
- strcpy (debugfile, dir);
- strcat (debugfile, DEBUG_SUBDIRECTORY);
- strcat (debugfile, "/");
- strcat (debugfile, debuglink);
-
+ debugfile = build_debug_file_name (dir, DEBUG_SUBDIRECTORY,
+ debuglink, NULL);
if (separate_debug_file_exists (debugfile, crc32, objfile))
return debugfile;
+ xfree (debugfile);

/* Then try in the global debugfile directories.

@@ -1504,16 +1561,14 @@ find_separate_debug_file (const char *dir,

for (ix = 0; VEC_iterate (char_ptr, debugdir_vec, ix, debugdir); ++ix)
{
- strcpy (debugfile, debugdir);
- strcat (debugfile, "/");
- strcat (debugfile, dir);
- strcat (debugfile, debuglink);
-
+ debugfile = build_debug_file_name (debugdir, dir, debuglink,
+ NULL);
if (separate_debug_file_exists (debugfile, crc32, objfile))
{
do_cleanups (back_to);
return debugfile;
}
+ xfree (debugfile);

/* If the file is in the sysroot, try using its base path in the
global debugfile directory. */
@@ -1522,21 +1577,19 @@ find_separate_debug_file (const char *dir,
strlen (gdb_sysroot)) == 0
&& IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)]))
{
- strcpy (debugfile, debugdir);
- strcat (debugfile, canon_dir + strlen (gdb_sysroot));
- strcat (debugfile, "/");
- strcat (debugfile, debuglink);
-
+ debugfile = build_debug_file_name (debugdir, canon_dir
+ + strlen (gdb_sysroot),
+ debuglink, NULL);
if (separate_debug_file_exists (debugfile, crc32, objfile))
{
do_cleanups (back_to);
return debugfile;
}
+ xfree (debugfile);
}
}

do_cleanups (back_to);
- xfree (debugfile);
return NULL;
}

--
1.7.1