Patchwork [2/2] Trim trailing directory separators from new sysroots.

login
register
mail settings
Submitter John Baldwin
Date Jan. 23, 2019, 1:03 a.m.
Message ID <2c219947da76ada8ee0596dc61a4abef3ebdc256.1548205042.git.jhb@FreeBSD.org>
Download mbox | patch
Permalink /patch/31175/
State New
Headers show

Comments

John Baldwin - Jan. 23, 2019, 1:03 a.m.
The separate debugfile logic assumes that the sysroot does not include
a trailing separator (all of the sysroot logic in
find_separate_debug_file requires the next character after the sysroot
in a object file path to be a directory separator).  However, normal
filename completion will result in setting a sysroot with a trailing
directory separator.  If the directory portion of a new sysroot ends
with a directory separator and is not specifying the root directory,
trim the trailing separator.  This permits the sysroot logic to work
the same if a sysroot of "/myroot/" is specified instead of "/myroot".

Note that the sysroot displayed by 'show sysroot' will reflect the
trimmed sysroot.

gdb/ChangeLog:

	* solib.c (gdb_sysroot_changed): Trim trailing directory separator
	from new sysroot.
---
 gdb/ChangeLog | 5 +++++
 gdb/solib.c   | 8 ++++++++
 2 files changed, 13 insertions(+)
Simon Marchi - Jan. 26, 2019, 7:10 p.m.
On 2019-01-22 8:03 p.m., John Baldwin wrote:
> The separate debugfile logic assumes that the sysroot does not include
> a trailing separator (all of the sysroot logic in
> find_separate_debug_file requires the next character after the sysroot
> in a object file path to be a directory separator).  However, normal
> filename completion will result in setting a sysroot with a trailing
> directory separator.  If the directory portion of a new sysroot ends
> with a directory separator and is not specifying the root directory,
> trim the trailing separator.  This permits the sysroot logic to work
> the same if a sysroot of "/myroot/" is specified instead of "/myroot".
> 
> Note that the sysroot displayed by 'show sysroot' will reflect the
> trimmed sysroot.

I am not sure about this, it seems fragile to do this one off thing.  The
point where the path is stripped is quite far from the point where it has
an impact, so it's really not obvious why we do it (though this could be
fixed by saying why we do it in the comment).

I think it would be a step in a better direction to have an "is_child_path"
function that returns whether a path is a child of another one.  It would
be responsible for handling the case of the parent potentially having a
trailing directory separator.  The implementation of such function might
get hairy, but the  advantage is that it should be pretty easy to unit
test.

Finally, I think it would make this code more obvious:

      if (canon_dir != NULL
	  && filename_ncmp (canon_dir, gdb_sysroot,
			    strlen (gdb_sysroot)) == 0
	  && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)]))

vs

      if (canon_dir != NULL && is_child_patn (gdb_sysroot, canon_dir))

Simon
John Baldwin - Jan. 28, 2019, 8:40 p.m.
On 1/26/19 11:10 AM, Simon Marchi wrote:
> On 2019-01-22 8:03 p.m., John Baldwin wrote:
>> The separate debugfile logic assumes that the sysroot does not include
>> a trailing separator (all of the sysroot logic in
>> find_separate_debug_file requires the next character after the sysroot
>> in a object file path to be a directory separator).  However, normal
>> filename completion will result in setting a sysroot with a trailing
>> directory separator.  If the directory portion of a new sysroot ends
>> with a directory separator and is not specifying the root directory,
>> trim the trailing separator.  This permits the sysroot logic to work
>> the same if a sysroot of "/myroot/" is specified instead of "/myroot".
>>
>> Note that the sysroot displayed by 'show sysroot' will reflect the
>> trimmed sysroot.
> 
> I am not sure about this, it seems fragile to do this one off thing.  The
> point where the path is stripped is quite far from the point where it has
> an impact, so it's really not obvious why we do it (though this could be
> fixed by saying why we do it in the comment).
> 
> I think it would be a step in a better direction to have an "is_child_path"
> function that returns whether a path is a child of another one.  It would
> be responsible for handling the case of the parent potentially having a
> trailing directory separator.  The implementation of such function might
> get hairy, but the  advantage is that it should be pretty easy to unit
> test.
> 
> Finally, I think it would make this code more obvious:
> 
>       if (canon_dir != NULL
> 	  && filename_ncmp (canon_dir, gdb_sysroot,
> 			    strlen (gdb_sysroot)) == 0
> 	  && IS_DIR_SEPARATOR (canon_dir[strlen (gdb_sysroot)]))
> 
> vs
> 
>       if (canon_dir != NULL && is_child_patn (gdb_sysroot, canon_dir))

I have taken this approach, but it ended up being a bit more than just a
boolean check as I needed to reliably get the base path of the child
component as the existing 'canon_dir + strlen (gdb_sysroot)' assumed no
trailing separator in gdb_sysroot.  I'll post the updated version along
with another fix I encountered in some more testing today as a v2 in a
sec.

Patch

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a401cfc784..c9f2d049bc 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@ 
+2019-01-22  John Baldwin  <jhb@FreeBSD.org>
+
+	* solib.c (gdb_sysroot_changed): Trim trailing directory separator
+	from new sysroot.
+
 2019-01-22  John Baldwin  <jhb@FreeBSD.org>
 
 	* symfile.c (find_separate_debug_file): Look for separate debug
diff --git a/gdb/solib.c b/gdb/solib.c
index 3a6db5e12d..a837f27c73 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -1433,6 +1433,14 @@  gdb_sysroot_changed (const char *ignored, int from_tty,
 	}
     }
 
+  /* Trim trailing directory separator.  */
+  char *sysroot_dir = gdb_sysroot;
+  if (startswith (gdb_sysroot, TARGET_SYSROOT_PREFIX))
+    sysroot_dir += strlen (TARGET_SYSROOT_PREFIX);
+  size_t len = strlen (sysroot_dir);
+  if (len > 1 && IS_DIR_SEPARATOR (sysroot_dir[len - 1]))
+      sysroot_dir[len - 1] = '\0';
+
   reload_shared_libraries (ignored, from_tty, e);
 }