]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ctf: handle srcdir-relative paths properly.
authorNick Alcock <nick.alcock@oracle.com>
Tue, 30 Sep 2014 14:02:46 +0000 (15:02 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 21 Jul 2015 14:29:42 +0000 (15:29 +0100)
The dwarf2ctf tool maintains various blacklists to get around things some
modules do which are incompatible with large-scale deduplication of types or
with having one type table per module. These blacklists are in the source tree,
and unfortunately we were looking for them using a relative path, which equates
to the objdir when O= or KBUILD_OUTPUT are in use: so we got assertion failures
from dwarf2ctf and a kernel build failure when it detected that something was
wrong with its duplicate-type detection.

Worse yet, one of these blacklists, member.blacklist, contains the names of
source files.  These paths relate to entities in the source tree, but they are
compared to source-file paths in object files generated by the compiler (which
are in theory objdir-relative, but which are in any case always absolute iff
KBUILD_OUTPUT is in use).  If these comparisons are to be successful, we must
absolutize the relative paths in the member.blacklist against the source tree,
not against the object tree.

We don't need to extend the realpath()-result-caching infrastructure to handle
this case, because we're only absolutizing *one path* this way, and at most
it'll be a few dozen.  The caching infrastructure exists to handle cases where
millions or billions of realpath()s are done.  We just need to chdir() to the
source tree, realpath(), and fchdir() back.  (We use the O_PATH open() flag to
do this if possible, but older glibcs such as that on OL6 do not provide O_PATH,
and it has an architecture-dependent so we cannot provide it ourselves: in that
case we fall back to O_RDONLY | O_DIRECTORY, which should always work since the
objdir really should always be readable by the current user.)

Orabug: 19712731

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Tested-by: Chuck Lever <chuck.lever@oracle.com>
Tested-by: Guangyu Sun <guangyu.sun@oracle.com>
Acked-by: Guru Anbalagane <Guru.Anbalagane@oracle.com>
scripts/Makefile.modpost
scripts/dwarf2ctf/dwarf2ctf.c

index 50943ab281e22572d989c5868d1dff038eba92d7..9039cd5fb4d0d3e457ca1f4f17ad4f65628edbd4 100644 (file)
@@ -160,7 +160,7 @@ ifdef CONFIG_CTF
 ifeq ($(KBUILD_EXTMOD),)
 ctf-dir := .ctf
 quiet_cmd_ctf = CTF
-      cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) objects.builtin modules.builtin scripts/dwarf2ctf/dedup.blacklist scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
+      cmd_ctf = scripts/dwarf2ctf/dwarf2ctf $(ctf-dir) $(srctree) objects.builtin modules.builtin $(srctree)/scripts/dwarf2ctf/dedup.blacklist $(srctree)/scripts/dwarf2ctf/member.blacklist $(ctf-filelist)
 builtins := $(shell cat objects.builtin 2>/dev/null)
 ctf-stamp := .ctf/ctf.stamp
 ctf-filelist := .ctf/ctf.filelist
index d43f5f97919958213a7299da29b94d65059f89e5..dd4511bfd51a177744ca85231a818606911e2bec 100644 (file)
@@ -18,6 +18,7 @@
 #include <stddef.h>
 #include <sys/stat.h>
 #include <sys/types.h>
+#include <fcntl.h>
 #include <limits.h>
 
 #include <libelf.h>
 #define PATH_MAX 1024
 #endif
 
+/*
+ * Work with older glibc: stub out O_PATH if not available.  (We can work
+ * without it.)
+ */
+#ifndef O_PATH
+# define O_PATH     0
+#endif
+
 #ifndef __GNUC__
 #define __attribute__((foo))
 #endif
@@ -174,7 +183,8 @@ static GHashTable *member_blacklist;
 /*
  * Populate the member blacklist from the member_blacklist file.
  */
-static void init_member_blacklist(const char *member_blacklist_file);
+static void init_member_blacklist(const char *member_blacklist_file,
+                                 const char *srcdir);
 
 /*
  * Return 1 if a given DWARF DIE, which must be a DW_TAG_member, appears in the
@@ -641,6 +651,12 @@ static char *fn_to_module(const char *file_name);
  */
 static const char *abs_file_name(const char *file_name);
 
+/*
+ * Determine absolute filenames relative to some other directory: do not cache
+ * them.  It is the caller's responsibility to free them.
+ */
+static char *rel_abs_file_name(const char *file_name, const char *relative_to);
+
 /*
  * Trivial wrapper, avoid an incompatible pointer type warning.
  */
@@ -654,11 +670,12 @@ int main(int argc, char *argv[])
 
        trace = getenv("DWARF2CTF_TRACE");
 
-       if ((argc != 4 && argc != 7) ||
+       if ((argc != 4 && argc != 8) ||
            (argc == 4 && strcmp(argv[2], "-e") != 0)) {
-               fprintf(stderr, "Syntax: dwarf2ctf outputdir objects.builtin modules.builtin dedup.blacklist\n");
+               fprintf(stderr, "Syntax: dwarf2ctf outputdir srcdir "
+                       "objects.builtin modules.builtin dedup.blacklist\n");
                fprintf(stderr, "                  member.blacklist filelist\n");
-               fprintf(stderr, "    or dwarf2ctf outputdir -e filelist"
+               fprintf(stderr, "    or dwarf2ctf outputdir -e filelist\n"
                        "for external module use\n");
                exit(1);
        }
@@ -681,20 +698,22 @@ int main(int argc, char *argv[])
         * independently invoked with every argument.
         */
        if (strcmp(argv[2], "-e") != 0) {
+               const char *srcdir;
                char *builtin_objects_file;
                char *builtin_module_file;
                char *dedup_blacklist_file;
                char *member_blacklist_file;
 
-               builtin_objects_file = argv[2];
-               builtin_module_file = argv[3];
-               dedup_blacklist_file = argv[4];
-               member_blacklist_file = argv[5];
+                srcdir = argv[2];
+               builtin_objects_file = argv[3];
+               builtin_module_file = argv[4];
+               dedup_blacklist_file = argv[5];
+               member_blacklist_file = argv[6];
 
                init_builtin(builtin_objects_file, builtin_module_file);
                init_dedup_blacklist(dedup_blacklist_file);
-               init_member_blacklist(member_blacklist_file);
-               init_object_names(argv[6]);
+               init_member_blacklist(member_blacklist_file, srcdir);
+               init_object_names(argv[7]);
 
                run(output_dir);
        } else {
@@ -1018,7 +1037,8 @@ static void init_dedup_blacklist(const char *dedup_blacklist_file)
 /*
  * Populate the member blacklist from the member_blacklist file.
  */
-static void init_member_blacklist(const char *member_blacklist_file)
+static void init_member_blacklist(const char *member_blacklist_file,
+                                 const char *srcdir)
 {
        FILE *f;
        char *line = NULL;
@@ -1058,7 +1078,7 @@ static void init_member_blacklist(const char *member_blacklist_file)
 
                *last_colon = '\0';
                last_colon++;
-               absolutized = xstrdup(abs_file_name(line));
+               absolutized = rel_abs_file_name(line, srcdir);
                absolutized = str_appendn(absolutized, ":", last_colon, NULL);
 
                g_hash_table_insert(member_blacklist, absolutized, NULL);
@@ -3663,6 +3683,50 @@ static const char *abs_file_name(const char *file_name)
        return abs_name;
 }
 
+/*
+ * Determine absolute filenames relative to some other directory.  This does not
+ * need to be fast.  The returned name is dynamically allocated, and must be
+ * freed by the caller.
+ */
+static char *rel_abs_file_name(const char *file_name, const char *relative_to)
+{
+       int dir = -1;
+       static int warned = 0;
+       char *abspath;
+       /*
+        * If we can't get this name relatively, we might as well *try* to do it
+        * absolutely: but print a warning.
+        */
+       if ((dir = open(".", O_RDONLY | O_DIRECTORY | O_PATH)) < 0) {
+               if (!warned) {
+                       fprintf(stderr, "Cannot open current directory: %s\n",
+                               strerror(errno));
+                       warned = 1;
+               }
+       } else {
+               if (chdir(relative_to) < 0)
+                       if (!warned) {
+                               fprintf(stderr, "Cannot change "
+                                       "directory to %s: %s\n",
+                                       relative_to, strerror(errno));
+                               warned = 1;
+                       }
+       }
+
+       abspath = realpath(file_name, NULL);
+       if (abspath == NULL)
+               abspath = strdup(file_name);
+
+       if ((dir > -1) && (fchdir(dir) < 0)) {
+               fprintf(stderr, "Cannot return to original directory "
+                       "after relative realpath(): %s\n",
+                       strerror(errno));
+               exit(1);
+       }
+
+       return abspath;
+}
+
 /*
  * Given a type encoding table, and a size, return the CTF encoding for that
  * type, or 0 if none.