Hello Roland and others,
I found an issue with dwarf_getsrc_file() and its ability to support a
combination of Windows and UNIX slashes ('\\' vs. '/'). The problem
occurs
when I load an ELF file that was built on Windows and has relative paths to
source files (i.e. "dir\\file.c"). The logic in dwarf_getsrc_file()
currently handles this as a basename path (is_basename is true). In this
case, it will compare "dir\\file.c" with basename("dir/file.c"), which
will
always fail. The fix for this is to check for the presence of either a '/'
or '\\' in the filename passed into the function.
Once this is fixed, there's still the issue of using a straight strcmp() to
compare the paths, which fails because the separator is different (I always
use '/' as my separator on Linux - I haven't found an easy way to determine
which separator to use for a given ELF file, but maybe someone has a
suggestion here and I could change my application code instead). But it
would be nice if libdw handled ELF files built on both Windows and Linux
seamlessly.
I propose the changes below to fix these issues (note that this diff is
against 0.142, but nothing has changed in this file since then). I'm
certain that this is not the most elegant way to solve the problem, so if
someone wants to improve on this and get it into the trunk, that would be
most excellent.
Please let me know if I can provide any additional information to help get
this fixed. Also, I will happily test out any fixes if that would be
helpful.
Thanks for your time!
--Mike
diff --git a/libdw/dwarf_getsrc_file.c b/libdw/dwarf_getsrc_file.c
index bc612f6..dcdda68 100644
--- a/libdw/dwarf_getsrc_file.c
+++ b/libdw/dwarf_getsrc_file.c
@@ -59,6 +59,23 @@
#include "libdwP.h"
+#include <stdio.h>
+
+int path_chr(char c)
+{
+ if(c == '\\')
+ return '/';
+ return c;
+}
+
+int path_strcmp (const char * p1, const char * p2)
+{
+ for(; path_chr(*p1) == path_chr(*p2); ++p1, ++p2)
+ if(*p1 == 0) {
+ return 0;
+ }
+ return *(unsigned char *)p1 < *(unsigned char *)p2 ? -1 : 1;
+}
int
dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column,
@@ -67,7 +84,8 @@ dwarf_getsrc_file (Dwarf *dbg, const char *fname, int
lineno, int column,
if (dbg == NULL)
return -1;
- bool is_basename = strchr (fname, '/') == NULL;
+ bool is_basename = (strchr (fname, '/') == NULL)
+ && (strchr(fname, '\\') == NULL);
size_t max_match = *nsrcs ?: ~0u;
size_t act_match = *nsrcs;
@@ -119,9 +137,9 @@ dwarf_getsrc_file (Dwarf *dbg, const char *fname, int
lineno, int column,
/* Match the name with the name the user provided. */
const char *fname2 = line->files->info[lastfile].name;
if (is_basename)
- lastmatch = strcmp (basename (fname2), fname) == 0;
+ lastmatch = path_strcmp (basename (fname2), fname) == 0;
else
- lastmatch = strcmp (fname2, fname) == 0;
+ lastmatch = path_strcmp (fname2, fname) == 0;
}
if (!lastmatch)
continue;
Show replies by date
Note that your mailer mangled your patch. It's not a problem since I could
still read it well enough to know I won't apply it. :-) But you should get
that in order (and punt the HTML mail!) if you ever submit any real patches
for inclusion into anything.
I wasn't aware that ELF objects were ever used on Windows.
My first reaction is that this seems like a general issue for using any
Unix tools on data containing Windows file names, not particular to
elfutils, to DWARF, or even to compiled objects per se. What other Unix
tools do you use on Windows file names, and what do you expect from them?
OTOH, the elfutils tools are meant in general to support cross-target uses
on ELF files from anywhere. So I'd like to contemplate what we might do
here. But, we won't uglify the tools much to handle this.
Can you pull out the comp_dir attributes from "eu-readelf --debug-dump=info"
and the directory and file name tables from "eu-readelf --debug-dump=line"
from some representative Windows ELF objects and show us what they look like?
I'm thinking it might be reasonable to look at the CU's comp_dir and/or
directory table to decide what model we think its directory and file names
use.
Thanks,
Roland