From: Nick Alcock Date: Tue, 30 Sep 2014 14:02:46 +0000 (+0100) Subject: ctf: handle srcdir-relative paths properly. X-Git-Tag: v4.1.12-92~313^2~34 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=ddcd0eab148f21c136ca1b98b7bb278d38ec592d;p=users%2Fjedix%2Flinux-maple.git ctf: handle srcdir-relative paths properly. 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 Tested-by: Chuck Lever Tested-by: Guangyu Sun Acked-by: Guru Anbalagane --- diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 50943ab281e2..9039cd5fb4d0 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -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 diff --git a/scripts/dwarf2ctf/dwarf2ctf.c b/scripts/dwarf2ctf/dwarf2ctf.c index d43f5f979199..dd4511bfd51a 100644 --- a/scripts/dwarf2ctf/dwarf2ctf.c +++ b/scripts/dwarf2ctf/dwarf2ctf.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -34,6 +35,14 @@ #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.