The Samba-Bugzilla – Attachment 10815 Details for
Bug 10005
Doesn't support -gsplit-dwarf
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
Patch to support -gsplit-dwarf (rev02)
split-dwarf-rev02.patch (text/plain), 39.19 KB, created by
ishikawa
on 2015-03-04 14:34:17 UTC
(
hide
)
Description:
Patch to support -gsplit-dwarf (rev02)
Filename:
MIME Type:
Creator:
ishikawa
Created:
2015-03-04 14:34:17 UTC
Size:
39.19 KB
patch
obsolete
>Binary files ccache/ccache and ccache-gsplit-dwarf-support/ccache differ >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/ccache.c ccache-gsplit-dwarf-support/ccache.c >--- ccache/ccache.c 2015-03-04 23:01:48.149927458 +0900 >+++ ccache-gsplit-dwarf-support/ccache.c 2015-03-04 23:07:21.441798623 +0900 >@@ -1,3 +1,4 @@ >+/* -*- mode: C; fill-column:78 -*- */ > /* > * ccache -- a fast C/C++ compiler cache > * >@@ -95,9 +96,12 @@ static char *output_obj; > /* The path to the dependency file (implicit or specified with -MF). */ > static char *output_dep; > >-/* Diagnostic generation information (clang). */ >+/* Diagnostic generation information (clang). Contains pathname if not NULL. */ > static char *output_dia = NULL; > >+/* -gsplit-dwarf support: Split dwarf information (GCC 4.8 and up). Contains pathname if not NULL. */ >+static char *output_dwo = NULL; >+ > /* > * Name (represented as a struct file_hash) of the file containing the cached > * object code. >@@ -129,6 +133,21 @@ static char *cached_dep; > static char *cached_dia; > > /* >+ * -gsplit-dwarf support: >+ * Full path to the file containing the split dwarf (for GCC 4.8 and above) >+ * (cachedir/a/b/cdef[...]-size.dwo). >+ * >+ * contains NULL if -gsplit-dwarf is not given. >+ */ >+static char *cached_dwo; >+ >+/* >+ * -gsplit-dwarf support: >+ * split_dwarf_p is true if "-gsplit-dwarf" is given to the compiler (GCC 4.8 and up). >+ */ >+bool split_dwarf_p = false; >+ >+/* > * Full path to the file containing the manifest > * (cachedir/a/b/cdef[...]-size.manifest). > */ >@@ -167,6 +186,25 @@ char *stats_file = NULL; > /* Whether the output is a precompiled header */ > static bool output_is_precompiled_header = false; > >+/* >+ * -gsplit-dwarf support: >+ * Also used during profile support [profile creates more than one file and >+ * we need a similar handling of files.] >+ * >+ * Whether we should output to the real object first before saving >+ * into cache. >+ * This direct output to the real object first >+ * becomes necessary when a produced object file needs >+ * to contain a valid source pathname (or part of it) such as in the >+ * case of .o file containing the pathname of .dwo file when >+ * -gsplit-dwarf is specified. >+ * Unless output_to_real_object_first is set to true, the recorded .dwo >+ * filepath in .o file ends up as that of a temporary file which is >+ * removed after compilation. >+ */ >+ >+static bool output_to_real_object_first = false; >+ > /* Profile generation / usage information */ > static char *profile_dir = NULL; > static bool profile_use = false; >@@ -261,6 +299,7 @@ failed(void) > fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno)); > } > >+ > static const char * > temp_dir() > { >@@ -735,20 +774,99 @@ static void > to_cache(struct args *args) > { > char *tmp_stdout, *tmp_stderr; >+ char *tmp_dia; /* for supporting output_to_real_object_first */ >+ char *tmp_obj; /* for supporting -gsplit-dwarf */ >+ char *tmp_dwo; /* for supporting -gsplit-dwarf */ >+ char *cp; /* for supporting -gsplit-dwarf */ > struct stat st; > int status, tmp_stdout_fd, tmp_stderr_fd; > >+ /* Here cached_obj contains a file name for object */ >+ > tmp_stdout = format("%s.tmp.stdout", cached_obj); > tmp_stdout_fd = create_tmp_fd(&tmp_stdout); > tmp_stderr = format("%s.tmp.stderr", cached_obj); > tmp_stderr_fd = create_tmp_fd(&tmp_stderr); > >+ /* -gsplit-dwarf support: >+ * we ought to create tmp_dwo path name, too >+ * if -gsplit-dwarf is used. >+ * tmp_obj will contain a file path name. >+ */ >+ if (output_to_real_object_first) { >+ tmp_obj = x_strdup(output_obj); >+ cc_log("(tmp_obj) Outputting to final destination: %s", tmp_obj); >+ } else { >+ tmp_obj = format("%s.tmp.%s", cached_obj, tmp_string()); >+ cc_log("(tmp_obj) Outputting to temporary destination: %s", tmp_obj); >+ } >+ >+ /* -gsplit-dwarf support: creating .dwo file name >+ * >+ * What is the reliable way of creating the .dwo file name in the case >+ * of using |-o tmp_obj| to the compiler ? >+ * Heuristics based on one run of GCC 4.8 is placed below, and it >+ * works with gcc 4.9 as well. >+ * >+ * No matter whether -gsplit-warning is placed on the command line, or >+ * if so, whether it has been seen or not, we need to set tmp_dwo in >+ * this part of the code to reflect the value of the current tmp_obj >+ * above to tmp_dwo. >+ * If -gsplit-dwarf is specified on the command line, this tmp_dwo >+ * will be used. >+ */ >+ >+ // In the extreme simple case, >+ // if (output_to_real_object_first) { >+ // tmp_obj = x_strdup(output_obj); >+ // cc_log("Outputting to final destination: %s", tmp_obj); >+ // Try replacing .o with .dwo. >+ // >+ // Fact: gcc-4.8 produced the following .dwo file for the command >+ // below: >+ // t-test.o.tmp.dwo >+ // >+ // /usr/bin/gcc-4.8 -gsplit-dwarf -c t-test.c -o t-test.o.tmp.gazonk >+ // >+ // So here is the huristics (works with gcc 4.9 also). >+ // Strip anything after the final '.' and add "dwo" instead. >+ >+ cp = strrchr(tmp_obj, '.'); >+ assert(cp); >+ { >+ /* >+ * String is modified in place. Since we already created the >+ * string by x_strdup, and format, we should be relatively >+ * safe and not cause unintended change even if ccache becomes >+ * multi-threaded. >+ */ >+ *cp = '\0'; >+ tmp_dwo = format("%s.dwo", tmp_obj); >+ *cp = '.'; >+ } >+ cc_log("Setting tmp_dwo to %s", tmp_dwo); >+ > args_add(args, "-o"); >- args_add(args, output_obj); > >+ /* change mandated by -gsplit-dwarf support above: >+ * Let's make the compiler output to |tmp_obj| instead of |output_obj| >+ */ >+ args_add(args, tmp_obj); >+ >+ /* >+ * We need to use different paths for diagnostic output depending on >+ * whether output to real object is done first. >+ * Use tmp_dia instead of output_dia after we set tmp_dia appropriately. >+ */ > if (output_dia) { >+ tmp_dia = output_to_real_object_first ? >+ x_strdup(output_dia) : >+ format("%s.tmp.dia.%s", cached_obj, tmp_string()); >+ cc_log("(tmp_dia) Outputting to final destination: %s", tmp_dia); > args_add(args, "--serialize-diagnostics"); >- args_add(args, output_dia); >+ args_add(args, tmp_dia); >+ } else { >+ tmp_dia = NULL; > } > > /* Turn off DEPENDENCIES_OUTPUT when running cc1, because >@@ -774,6 +892,13 @@ to_cache(struct args *args) > stats_update(STATS_MISSING); > tmp_unlink(tmp_stdout); > tmp_unlink(tmp_stderr); >+ /* -gsplit-dwarf support requires the removal of a few more files.*/ >+ tmp_unlink(tmp_obj); >+ if (tmp_dia) { /* Note: tmp_dia is the path name for diagnostics. */ >+ tmp_unlink(tmp_dia); /* I think we need this. */ >+ } >+ if (tmp_dwo) >+ tmp_unlink(tmp_dwo); > failed(); > } > if (st.st_size != 0) { >@@ -781,11 +906,24 @@ to_cache(struct args *args) > stats_update(STATS_STDOUT); > tmp_unlink(tmp_stdout); > tmp_unlink(tmp_stderr); >+ /* -gsplit-dwarf support requires the removal of a few more files. */ >+ tmp_unlink(tmp_obj); >+ if (tmp_dia) { >+ tmp_unlink(tmp_dia); >+ } >+ if (tmp_dwo) { >+ tmp_unlink(tmp_dwo); >+ } > failed(); > } > tmp_unlink(tmp_stdout); > > /* >+ * OBSERVATION: processing stderr does not have to be changed in the >+ * presence of "-gsplit-dwarf". >+ */ >+ >+ /* > * Merge stderr from the preprocessor (if any) and stderr from the real > * compiler into tmp_stderr. > */ >@@ -838,26 +976,88 @@ to_cache(struct args *args) > close(fd); > tmp_unlink(tmp_stderr); > >+ /* Copying of _dia file should be done here since when >+ * an error occurs, we may want to know the >+ * diagnostics, don't we? >+ */ >+ >+ if (output_dia) { >+ int ret; >+ x_unlink(output_dia); >+ /* only make a hardlink if the cache file is uncompressed */ >+ ret = move_file(tmp_dia, output_dia, 0); >+ >+ if (ret == -1) { >+ if (errno == ENOENT) { >+ /* Someone removed the file just before we began copying? */ >+ cc_log("Diagnostic file %s just disappeared", output_dia); >+ stats_update(STATS_MISSING); >+ } else { >+ cc_log("Failed to move %s to %s: %s", >+ tmp_dia, output_dia, strerror(errno)); >+ stats_update(STATS_ERROR); >+ failed(); >+ } >+ x_unlink(tmp_dia); >+ } else { >+ cc_log("Created %s from %s", output_dia, tmp_dia); >+ } >+ } > exit(status); > } > >+ cc_log("verbose: (tmp_stderr) %s being removed", tmp_stderr); > tmp_unlink(tmp_stderr); >+ >+ /* gsplit-support modification */ >+ cc_log("verbose: (tmp_obj) %s being removed", tmp_obj); >+ tmp_unlink(tmp_obj); >+ >+ if (tmp_dia) { >+ tmp_unlink(tmp_dia); >+ } >+ if (tmp_dwo) { >+ tmp_unlink(tmp_dwo); >+ } > failed(); > } > >- if (stat(output_obj, &st) != 0) { >- cc_log("Compiler didn't produce an object file"); >+ if (stat(tmp_obj, &st) != 0) { >+ cc_log("(tmp_obj) Compiler didn't produce an object file"); > stats_update(STATS_NOOUTPUT); > failed(); > } > if (st.st_size == 0) { >- cc_log("Compiler produced an empty object file"); >+ cc_log("(tmp_obj) Compiler produced an empty object file"); > stats_update(STATS_EMPTYOUTPUT); > failed(); > } > >+ >+ /* -gsplit-dwarf support: >+ * We should also repeat the check for .dwo file in addition to >+ * tmp_obj when "-gsplit-dwarf is given. >+ * Because of the way tmp_dwo is produced when command line is >+ * scanned, we can have non-null tmp_dwo even when split_swarf_p is >+ * false. Check only when split_dwarf_p is true. >+ */ >+ >+ if (tmp_dwo && split_dwarf_p) { >+ /* cc_log("tmp_dwo = %s", tmp_dwo); */ >+ if (stat(tmp_dwo, &st) != 0) { >+ cc_log("(tmp_dwo) Compiler didn't produce a split dwarf file"); >+ stats_update(STATS_NOOUTPUT); >+ failed(); >+ } >+ if (st.st_size == 0) { >+ cc_log("(tmp_dwo) Compiler produced an empty split dwarf file"); >+ stats_update(STATS_EMPTYOUTPUT); >+ failed(); >+ } >+ } >+ > if (stat(tmp_stderr, &st) != 0) { >- cc_log("Failed to stat %s: %s", tmp_stderr, strerror(errno)); >+ cc_log("(tmp_stderr) Failed to stat %s: %s", tmp_stderr, strerror(errno)); > stats_update(STATS_ERROR); > failed(); > } >@@ -870,11 +1070,24 @@ to_cache(struct args *args) > stats_update(STATS_ERROR); > failed(); > } >- cc_log("Stored in cache: %s", cached_stderr); >+ cc_log("(cached_stderr) Stored in cache: %s", cached_stderr); >+ /* >+ * Do not forget to check return value of stat() and act accordingly. >+ */ > if (conf->compression) { >- stat(cached_stderr, &st); >+ /* >+ * The file was compressed, so obtain the compressed >+ * size again. >+ */ >+ if ( stat(cached_stderr, &st) == 0) { >+ stats_update_size(file_size(&st), 1); >+ } else { >+ cc_log("stat on cached_stderr=%s failed (%s)", cached_stderr, strerror(errno)); > } >+ } else { > stats_update_size(file_size(&st), 1); >+ } >+ > } else { > tmp_unlink(tmp_stderr); > if (conf->recache) { >@@ -883,18 +1096,71 @@ to_cache(struct args *args) > } > } > >- if (output_dia) { >- if (stat(output_dia, &st) != 0) { >- cc_log("Failed to stat %s: %s", output_dia, strerror(errno)); >+ if (tmp_dia) { >+ if (stat(tmp_dia, &st) != 0) { >+ cc_log("(tmp_dia) Failed to stat %s: %s", tmp_dia, strerror(errno)); > stats_update(STATS_ERROR); > failed(); > } > if (st.st_size > 0) { >- put_file_in_cache(output_dia, cached_dia); >+ put_file_in_cache(tmp_dia, cached_dia); >+ cc_log("(cached_dia) Stored in cache: %s", cached_dia); > } > } > >- put_file_in_cache(output_obj, cached_obj); >+ /* Description of processing below.: >+ * if (output_to_real_object_first) { >+ * Perform the extra copy of .dwo file if --gsplit-dwarf is used. >+ * } else if (move_uncompressed_file(...) != 0) { >+ * The above line of move_uncompressed_file() >+ * ought to be repeated for .dwo file if --gsplit-dwarf is used. >+ * } >+ */ >+ >+ /* use tmp_obj instead of output_obj */ >+ put_file_in_cache(tmp_obj, cached_obj); >+ >+ cc_log("(cached_obj) Stored in cache: %s", cached_obj); >+ >+ /* stats_update(STATS_TOCACHE) is now called AFTER the processing of >+ * .dwo file below. >+ */ >+ >+ /* >+ * Caution: if we output to real object file first, then >+ * tmp_obj *IS* the real object, and so we should not remove it! >+ * >+ * Also, in this case, we should NOT copy back the cached file to the >+ * final destination object. This is a waste of time. >+ * >+ * Same can be said of .dwo file: real and cached one below. >+ * Somehow dependency file was not copied this way. >+ */ >+ if (!output_to_real_object_first) >+ tmp_unlink(tmp_obj); >+ >+ /* -gsplit-dwarf support: >+ * if -gsplit-dwarf is given on the compiler command line, >+ * .dwo file ought to be put into cache as well. >+ */ >+ if (split_dwarf_p) >+ { >+ assert(tmp_dwo); >+ assert(cached_dwo); >+ put_file_in_cache(tmp_dwo, cached_dwo); >+ cc_log("(cached_dwo) Stored in cache: %s", cached_dwo); >+ >+ /* internal sanity check */ >+ if (!generating_dependencies) >+ assert(tmp_dwo && cached_dwo); >+ >+ /* Caution: if we output to real object file first, then >+ * tmp_dwo *IS* the real .dwo file, and so we should not remove it! >+ * The original code is left as a comment line to stress this point. >+ */ >+ /* tmp_unlink(tmp_dwo); */ >+ } >+ > stats_update(STATS_TOCACHE); > > /* Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can >@@ -915,13 +1181,18 @@ to_cache(struct args *args) > * previous ccache versions. */ > if (getpid() % 1000 == 0) { > char *path = format("%s/CACHEDIR.TAG", conf->cache_dir); >- unlink(path); >+ x_unlink(path); > free(path); > } > } > >+ free(tmp_obj); > free(tmp_stderr); > free(tmp_stdout); >+ if (tmp_dia) >+ free(tmp_dia); >+ if (tmp_dwo) >+ free(tmp_dwo); > } > > /* >@@ -952,6 +1223,7 @@ get_object_name_from_cpp(struct args *ar > > path_stderr = format("%s/tmp.cpp_stderr", temp_dir()); > path_stderr_fd = create_tmp_fd(&path_stderr); >+ > add_pending_tmp_file(path_stderr); > > time_of_compilation = time(NULL); >@@ -1045,6 +1317,29 @@ update_cached_result_globals(struct file > cached_stderr = get_path_in_cache(object_name, ".stderr"); > cached_dep = get_path_in_cache(object_name, ".d"); > cached_dia = get_path_in_cache(object_name, ".dia"); >+ >+ /* >+ * --gsplit-dwarf support. >+ * We set cached_dwo to NULL to signify --gsplit-dwarf is not used. >+ */ >+ if (split_dwarf_p) >+ cached_dwo = get_path_in_cache(object_name, ".dwo"); >+ else >+ cached_dwo = NULL; >+ >+ /* TODO/NOTE: if split_dwarf_p is not true and we get non-null >+ * get_path_in_cache(object_name, ".dwo"), we probably should purge >+ * that file! But this is not so critical. We will purge the file eventually >+ * by LRU algorithm. >+ */ >+ if (!split_dwarf_p) { >+ char *cp; >+ cp = get_path_in_cache(object_name, ".dwo"); >+ if (!cp) { >+ cc_log("We are not using split dwarf but, we have .dwo. Maybe we should purge it.:%s", cp); >+ } >+ } >+ > stats_file = format("%s/%c/stats", conf->cache_dir, object_name[0]); > free(object_name); > } >@@ -1308,6 +1603,10 @@ calculate_object_hash(struct args *args, > hash_string(hash, args->argv[i]); > } > >+ if (split_dwarf_p) { >+ cc_log("Setting output_to_real_object_first to true since split_dwarf_p is true."); >+ output_to_real_object_first = true; >+ } > /* > * For profile generation (-fprofile-arcs, -fprofile-generate): > * - hash profile directory >@@ -1328,6 +1627,7 @@ calculate_object_hash(struct args *args, > * artifacts will be produced in the wrong place. > */ > if (profile_generate) { >+ output_to_real_object_first = true; > if (!profile_dir) { > profile_dir = get_cwd(); > } >@@ -1335,10 +1635,17 @@ calculate_object_hash(struct args *args, > hash_delimiter(hash, "-fprofile-dir"); > hash_string(hash, profile_dir); > } >+ /* OBSERVATION: processing for profile_use is a good example >+ * which we can mimic to implement the support for >+ * --gsplit-dwarf. >+ * So the support for -gsplit-dwarf was modeled after the >+ * processing to support profile. >+ */ > if (profile_use) { > /* Calculate gcda name */ > char *gcda_name; > char *base_name; >+ output_to_real_object_first = true; > base_name = remove_extension(output_obj); > if (!profile_dir) { > profile_dir = get_cwd(); >@@ -1420,6 +1727,7 @@ static void > from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > { > int fd_stderr; >+ int ret; /* to keep track of error value. */ > struct stat st; > bool produce_dep_file; > >@@ -1428,28 +1736,59 @@ from_cache(enum fromcache_call_mode mode > return; > } > >- /* Check if the object file is there. */ >+ /* >+ * Check if the object file is there. >+ * For -gsplit-dwarf support, check for .dwo as well. See below. >+ * cached_obj contains the path for cached object file. >+ */ >+ > if (stat(cached_obj, &st) != 0) { >- cc_log("Object file %s not in cache", cached_obj); >+ cc_log("(cached_obj) Object file %s not in cache", cached_obj); > return; > } > >- /* Check if the diagnostic file is there. */ >+ /* Check if the diagnostic file is there. >+ * Notice the logic. We only check when output_dia is not NULL. >+ */ > if (output_dia && stat(cached_dia, &st) != 0) { >- cc_log("Diagnostic file %s not in cache", cached_dia); >+ cc_log("(cached_dia) Diagnostic file %s not in cache", cached_dia); > return; > } > > /* > * Occasionally, e.g. on hard reset, our cache ends up as just filesystem >- * meta-data with no content catch an easy case of this. >+ * meta-data with no content. Catch an easy case of this. > */ > if (st.st_size == 0) { >- cc_log("Invalid (empty) object file %s in cache", cached_obj); >+ cc_log(" (cached_obj) Invalid (empty) object file %s in cache", cached_obj); > x_unlink(cached_obj); > return; > } > >+ /* -gsplit-dwarf support >+ * We should repeat the above check for cached_dwo >+ */ >+ if (split_dwarf_p && !generating_dependencies) >+ assert(output_dwo); >+ >+ if (output_dwo) >+ assert(cached_dwo); >+ >+ if (output_dwo) { >+ >+ if (stat(cached_dwo, &st) != 0) { >+ cc_log("(cached_dwo) Split dwarf file %s not in cache", cached_dwo); >+ return; >+ } >+ >+ if (st.st_size == 0) { >+ cc_log(" (cached_dwo) Invalid (empty) dwo file %s in cache", cached_dwo); >+ x_unlink(cached_dwo); >+ x_unlink(cached_obj); /* to really invalidate */ >+ return; >+ } >+ } >+ > /* > * (If mode != FROMCACHE_DIRECT_MODE, the dependency file is created by > * gcc.) >@@ -1462,16 +1801,117 @@ from_cache(enum fromcache_call_mode mode > return; > } > >- if (!str_eq(output_obj, "/dev/null")) { >+ /* >+ * Note: The if-expr is reverted. In the else clause, do a similar >+ * processing for FissionDwarf file, cached_dwo in case -gsplit-dwarf >+ * is specified. >+ */ >+ >+ if (str_eq(output_obj, "/dev/null")) { >+ ret = 0; >+ } else { /* not /dev/null */ >+ /* we get file(s) from cache unless we generate object in direct mode */ >+ if (output_to_real_object_first >+ && mode == FROMCACHE_COMPILED_MODE /* called compier */) { >+ /* we don't need to copy from cache since we have >+ called the compiler and left the object in the >+ final destination.*/ >+ cc_log("[direct object generation]: skipped copy: (output_obj) %s from (cached_obj) %s", >+ output_obj, cached_obj); >+ >+ } else { >+ /* internal sanity check */ >+ assert( (output_to_real_object_first >+ && (mode == FROMCACHE_CPP_MODE >+ || mode == FROMCACHE_DIRECT_MODE)) >+ || (!output_to_real_object_first) ); > get_file_from_cache(cached_obj, output_obj); >+ cc_log("Created (output_obj) %s from (cached_obj) %s", >+ output_obj, cached_obj); > } >+ >+ /* >+ * if something failed internal to get_file_from_cache we may >+ * want to remove some files: the following x_unlink calls >+ * were in the original code circa 2014 summer. >+ * >+ * Similar comments are repeated in code below. >+ * >+ * Does failed(), which is called when error exit is taken, >+ * handle this now? If so, this comment is superflous. >+ * >+ * if (output_dwo) x_unlink(output_dwo); >+ * if (cached_dwo) x_unlink(cached_dwo); >+ * x_unlink(output_obj); >+ * x_unlink(cached_stderr); >+ * x_unlink(cached_obj); >+ * x_unlink(cached_dep); >+ *x_unlink(cached_dia); >+ */ >+ ret = 0; >+ } >+ >+ assert(ret == 0); >+ if (split_dwarf_p) { >+ assert(output_dwo); >+ assert(output_to_real_object_first); >+ /* >+ * we don't need to get file from cache when we called tge >+ * compiler in this run of ccache since the output_dwo would >+ * have been created by the compiler. >+ */ >+ if (mode == FROMCACHE_CPP_MODE || mode == FROMCACHE_DIRECT_MODE ) { >+ /* did not call compiler */ >+ get_file_from_cache(cached_dwo, output_dwo); >+ /* >+ * Note: if something failed internal to get_file_from_cache >+ * we may want to remove a flurry of files. >+ * There were calls to x_unlinks in the original code circa 2014 summer. >+ */ >+ } else { >+ /* sanity check */ >+ assert(mode == FROMCACHE_COMPILED_MODE); >+ cc_log("[direct object generation]: skipped the copy from cached_dwo=%s to output_dwo=%s", >+ cached_dwo, output_dwo); >+ } >+ } >+ >+ /* NOTE: The error processing above assumed we only do a copy/hardlink >+ * for cached_obj. We may need to repeat the copy and error >+ * processing for cached_dwo in a similar manner instead of doing the >+ * copy/link only. >+ * >+ * But do note that the unlinking of related files >+ * MUST BE REPEATED in the both cases of the failures of copy/link >+ * of cached_obj -> output_obj >+ * and cached_dwo -> output_dwo if (split_dwarf_p). >+ */ >+ > if (produce_dep_file) { > get_file_from_cache(cached_dep, output_dep); >+ cc_log("Created (output_dep) %s from (cached_dep) %s", output_dep, cached_dep); >+ /* >+ * Note: if something failed internal to get_file_from_cache >+ * we may want to remove a flurry of files. >+ * There were calls to x_unlinks in the original code circa 2014 summer. >+ */ > } >+ > if (output_dia) { > get_file_from_cache(cached_dia, output_dia); >+ cc_log("Created (output_dia) %s from (cached_dia) %s", output_dia, cached_dia); >+ >+ /* >+ * Note: if something failed internal to get_file_from_cache >+ * we may want to remove a flurry of files. >+ * There were calls to x_unlinks in the original code circa 2014 summer. >+ */ > } > >+ /* OBSERVATION: The above seems to be the best place where we >+ * can copy object file and dwo file safely. >+ */ >+ > /* Update modification timestamps to save files from LRU cleanup. > Also gives files a sensible mtime when hard-linking. */ > update_mtime(cached_obj); >@@ -1487,13 +1927,20 @@ from_cache(enum fromcache_call_mode mode > put_file_in_cache(output_dep, cached_dep); > } > >+ /* -gsplit-dwarf support */ >+ if (cached_dwo) >+ update_mtime(cached_dwo); >+ > /* Send the stderr, if any. */ > fd_stderr = open(cached_stderr, O_RDONLY | O_BINARY); > if (fd_stderr != -1) { >+ cc_log("Using stderr cache (cached_stderr): %s\n", cached_stderr); > copy_fd(fd_stderr, 2); > close(fd_stderr); > } > >+ /* Note: we do not need to put .dwo file in MANIFEST file. */ >+ > /* Create or update the manifest file. */ > if (conf->direct_mode > && put_object_in_manifest >@@ -1508,8 +1955,16 @@ from_cache(enum fromcache_call_mode mode > if (manifest_put(manifest_path, cached_obj_hash, included_files)) { > cc_log("Added object file hash to %s", manifest_path); > update_mtime(manifest_path); >- stat(manifest_path, &st); >- stats_update_size(file_size(&st) - old_size, old_size == 0 ? 1 : 0); >+ /* >+ * Don't forget to check the return value of stat and act accordingly. >+ */ >+ if (stat(manifest_path, &st) == 0) { >+ stats_update_size((file_size(&st) - old_size), >+ old_size == 0 ? 1 : 0); >+ } else { >+ cc_log("stat on manifest (manifest_path) %s failed (%s), so size statistics is incorrect.", >+ manifest_path, strerror(errno)); >+ } > } else { > cc_log("Failed to add object file hash to %s", manifest_path); > } >@@ -1659,6 +2114,7 @@ cc_process_args(struct args *args, struc > if (argpath[-1] == '-') { > ++argpath; > } >+ > file_args = args_init_from_gcc_atfile(argpath); > if (!file_args) { > cc_log("Couldn't read arg file %s", argpath); >@@ -1755,6 +2211,12 @@ cc_process_args(struct args *args, struc > goto out; > } > output_obj = make_relative_path(x_strdup(argv[i+1])); >+ >+ /* OBSERVATION: We need to create output_dwo if >+ -gsplit-dwarf is given. But we should not do here >+ YET since --gsplit-dwarf may be given later on the >+ command line !*/ >+ > i++; > continue; > } >@@ -1765,6 +2227,20 @@ cc_process_args(struct args *args, struc > continue; > } > >+ /* -gsplit-dwarf support >+ * This place is chosen as the place to handle -gsplit-dwarf. >+ */ >+ >+ if (str_eq(argv[i], "-gsplit-dwarf")) { >+ cc_log("split_dwarf_p is set to true due to -gsplit-dwarf."); >+ split_dwarf_p = true; >+ output_to_real_object_first = true; >+ /* we should add this option to the compiler option >+ when the real compiler is invoked. */ >+ args_add(stripped_args, argv[i]); >+ continue; >+ } >+ > /* debugging is handled specially, so that we know if we > can strip line number info > */ >@@ -2154,6 +2630,18 @@ cc_process_args(struct args *args, struc > > /* Rewrite to relative to increase hit rate. */ > input_file = make_relative_path(x_strdup(argv[i])); >+ } /* for */ >+ >+ /* found_S_opt needs to be handled with caution with split_dwarf_p */ >+ >+ if (found_S_opt /* || generating_dependencies*/ ) { >+ /* even if -gsplit-dwarf is given, .dwo file is not generated. >+ * So split_dwarf_p is set to false. >+ */ >+ split_dwarf_p = false; >+ output_to_real_object_first = false; >+ cc_log("split_dwarf_p is reset to false due to found_S_opt"); >+ cc_log("output_to_real_object_first is set to false, too"); > } > > if (!input_file) { >@@ -2241,6 +2729,15 @@ cc_process_args(struct args *args, struc > conf->cpp_extension = x_strdup(extension_for_language(p_language) + 1); > } > >+ /* Question: Is there an angle in which split_dwarf_p processing has >+ * anything to do with "-" output that is handled specialy below? >+ * >+ * For example, what do we want to do with .dwo file (produce it >+ * somewhere, but what path name to use)? >+ * >+ * We may find the answer in the long run. >+ */ >+ > /* don't try to second guess the compilers heuristics for stdout handling */ > if (output_obj && str_eq(output_obj, "-")) { > stats_update(STATS_OUTSTDOUT); >@@ -2249,6 +2746,55 @@ cc_process_args(struct args *args, struc > goto out; > } > >+ /* -gsplit-dwarf support: >+ * We have probably already seen and check for >+ * -gsplit-dwarf by the time we reach here. (We did it somewhere above.) >+ * Here is the chance to create output_dwo based on the value of output_obj. >+ * The basic outline would be >+ * output_obj = basename(input_file) >+ * add ".dwo" to it with minor tweaks to handle special cases. >+ */ >+ >+ /* >+ * Special case 1: What do we do if we need to output .s file >+ * for output and -gsplit-dwarf is specified? >+ * What file(s) does GCC 4.8 produce exactly? >+ * Answer: >+ * /usr/bin/gcc-4.8 -gsplit-dwarf -c t-test.c -S >+ * generated >+ * t-test.s >+ * that contains assembler directives to generate data (dwarf data). >+ * This means that if we are only producing assembler source >+ * we do not need to handle ".dwo" file at all. >+ * >+ * /usr/bin/gcc-4.8 -gsplit-dwarf -c t-test.c -S -o t-test.s.gazonk >+ * produced >+ * t-test.s.gazonk >+ * >+ * DONE: >+ * The above special cases need to be handled. >+ * The modification below more or less assumed that .dwo file is produced >+ * always (together with the paired .o file) unless "-S" is specified. >+ * >+ * File-scope global variable |found_S_opt| is set to true >+ * when "-S" is specified. >+ * >+ * /usr/bin/gcc-4.8 -gsplit-dwarf -c t-test.s >+ * produced >+ * t-test.o >+ * t-test.o.dwo. >+ * >+ * So let us disable split_dwarf_p to false if >+ * found_S_opt is true. >+ * This is done at the end of a loop in argument processing. >+ */ >+ >+ /* >+ * This clarifies the change for -gsplit-dwarf. We always use >+ * output_obj instead of tmp_obj even in the case of "-gsplit-dwarf" >+ * in the code below. >+ */ >+ > if (!output_obj) { > if (output_is_precompiled_header) { > output_obj = format("%s.gch", input_file); >@@ -2267,6 +2813,31 @@ cc_process_args(struct args *args, struc > } > } > >+ /* -gsplit-dwarf support: create output_dwo */ >+ if (split_dwarf_p && !found_S_opt) { >+ char *p; >+ p = strrchr(output_obj, '.'); >+ if (!p || !p[1]) { >+ cc_log("Badly formed object filename"); >+ stats_update(STATS_ARGS); >+ result = false; >+ goto out; >+ } >+ *p = '\0'; >+ output_dwo = format("%s.dwo", output_obj); >+ *p = '.'; >+ >+ cc_log("setting output_dwo to %s", output_dwo); >+ } >+ >+ >+ /* Long-term question: Do we need to cope with strange output_obj file >+ * name in case split_dwarf_p? >+ * "-gsplit-dwarf" support may encounter corner cases when strange >+ * file names are given. >+ * We may find the answer in the long run. >+ */ >+ > /* cope with -o /dev/null */ > if (!str_eq(output_obj,"/dev/null") > && stat(output_obj, &st) == 0 >@@ -2295,6 +2866,7 @@ cc_process_args(struct args *args, struc > args_add(cpp_args, explicit_language); > } > >+ > /* > * Since output is redirected, compilers will not color their output by > * default, so force it explicitly if it would be otherwise done. >@@ -2317,6 +2889,20 @@ cc_process_args(struct args *args, struc > } > } > >+ /* -gsplit-dwarf support: Ordering of dependency generation. >+ * >+ * -gsplit-dwarf processing should not affect dependency generation. >+ * >+ * Note, given the command line below, dependency file is generated >+ * first and then ccache.o is generated. >+ * Observing the ordering and take care of that. >+ * >+ * ccache /usr/bin/gcc-4.8 -gsplit-dwarf -DHAVE_CONFIG_H \ >+ * -DSYSCONFDIR=/usr/local/etc -I. -I. -MD -MP -MF .deps/ccache.c.d \ >+ * -g -O2 -Wall -W -Werror -c -o ccache.o ccache.c >+ * >+ */ >+ > /* > * Add flags for dependency generation only to the preprocessor command line. > */ >@@ -2489,6 +3075,7 @@ initialize(void) > if (conf->umask != UINT_MAX) { > umask(conf->umask); > } >+ > } > > /* Reset the global state. Used by the test suite. */ >@@ -2504,10 +3091,12 @@ cc_reset(void) > args_free(orig_args); orig_args = NULL; > free(input_file); input_file = NULL; > free(output_obj); output_obj = NULL; >+ if (output_dwo) free(output_dwo); output_dwo = NULL; > free(output_dep); output_dep = NULL; > free(output_dia); output_dia = NULL; > free(cached_obj_hash); cached_obj_hash = NULL; > free(cached_obj); cached_obj = NULL; >+ if (cached_dwo) free(cached_dwo); cached_dwo = NULL; > free(cached_stderr); cached_stderr = NULL; > free(cached_dep); cached_dep = NULL; > free(cached_dia); cached_dia = NULL; >@@ -2524,6 +3113,7 @@ cc_reset(void) > output_is_precompiled_header = false; > > conf = conf_create(); >+ split_dwarf_p = false; > } > > /* Make a copy of stderr that will not be cached, so things like >@@ -2619,7 +3209,33 @@ ccache(int argc, char *argv[]) > if (output_dia) { > cc_log("Diagnostic file: %s", output_dia); > } >- cc_log("Object file: %s", output_obj); >+ >+ /* >+ * Note: cc_process_args ought to have generated output_dwo. But we >+ * may not want to do so before generating dependencies because it has >+ * been the implicit ordering that the dependency is generated first >+ * and then object file is generated. >+ * See a block comment that starts with >+ * "-gsplit-dwarf support: Ordering of dependency generation." >+ * in the earlier part of this file. >+ */ >+ >+ if (split_dwarf_p ) { >+ if (output_dia) >+ cc_log("output_dia = %s", output_dia); >+ if (output_dwo) >+ cc_log("output_dwo = %s", output_dwo); >+ fflush(stdout); >+ if (!generating_dependencies) >+ assert (output_dwo); >+ } else { >+ assert (!output_dwo); >+ } >+ >+ if (!generating_dependencies && output_dwo) { >+ cc_log("Split dwarf file: %s", output_dwo); >+ } >+ cc_log("(output_obj) Object file: %s", output_obj); > > hash_start(&common_hash); > calculate_common_hash(preprocessor_args, &common_hash); >Only in ccache-gsplit-dwarf-support: ccache.c.saved >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/compopt.c ccache-gsplit-dwarf-support/compopt.c >--- ccache/compopt.c 2014-12-26 00:16:41.857924683 +0900 >+++ ccache-gsplit-dwarf-support/compopt.c 2014-10-31 01:23:27.861419530 +0900 >@@ -60,7 +60,6 @@ static const struct compopt compopts[] = > {"-frepo", TOO_HARD}, > {"-ftest-coverage", TOO_HARD}, /* generates a .gcno file at the same time */ > {"-fworking-directory", AFFECTS_CPP}, >- {"-gsplit-dwarf", TOO_HARD}, /* generates a .dwo file at the same time */ > {"-idirafter", AFFECTS_CPP | TAKES_ARG | TAKES_PATH}, > {"-iframework", AFFECTS_CPP | TAKES_ARG | TAKES_CONCAT_ARG | TAKES_PATH}, > {"-imacros", AFFECTS_CPP | TAKES_ARG | TAKES_PATH}, >Only in ccache-gsplit-dwarf-support: do-diff.sh >Only in ccache-gsplit-dwarf-support: do-test.sh >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/execute.c ccache-gsplit-dwarf-support/execute.c >--- ccache/execute.c 2015-03-04 23:01:48.149927458 +0900 >+++ ccache-gsplit-dwarf-support/execute.c 2015-03-04 22:59:49.424081775 +0900 >@@ -1,6 +1,6 @@ > /* > * Copyright (C) Andrew Tridgell 2002 >- * Copyright (C) Joel Rosdahl 2011 >+ * Copyright (C) Joel Rosdahl 2011-2015 > * > * This program is free software; you can redistribute it and/or modify it > * under the terms of the GNU General Public License as published by the Free >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/hash.c ccache-gsplit-dwarf-support/hash.c >--- ccache/hash.c 2014-12-26 00:16:41.857924683 +0900 >+++ ccache-gsplit-dwarf-support/hash.c 2015-03-04 03:36:51.011393317 +0900 >@@ -128,6 +128,7 @@ hash_file(struct mdfour *md, const char > > fd = open(fname, O_RDONLY|O_BINARY); > if (fd == -1) { >+ cc_log("hash file creation (%s) failed\n", fname); /* to catch strange errors */ > return false; > } > >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/language.c ccache-gsplit-dwarf-support/language.c >--- ccache/language.c 2014-12-26 00:16:41.857924683 +0900 >+++ ccache-gsplit-dwarf-support/language.c 2015-03-04 22:59:49.424081775 +0900 >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2010, 2013 Joel Rosdahl >+ * Copyright (C) 2010-2015 Joel Rosdahl > * > * This program is free software; you can redistribute it and/or modify it > * under the terms of the GNU General Public License as published by the Free >@@ -147,7 +147,7 @@ extension_for_language(const char *langu > bool > language_is_supported(const char *language) > { >- return p_language_for_language(language); >+ return p_language_for_language(language) != NULL; > } > > bool >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/manifest.c ccache-gsplit-dwarf-support/manifest.c >--- ccache/manifest.c 2014-12-26 00:16:41.857924683 +0900 >+++ ccache-gsplit-dwarf-support/manifest.c 2015-03-04 22:59:49.424081775 +0900 >@@ -598,11 +598,31 @@ add_object_entry(struct manifest *mf, > obj = &mf->objects[n]; > > n = hashtable_count(included_files); >+#if defined(CI_DEBUG) >+ { >+ char tmpbuf[128]; >+ snprintf(tmpbuf, 128, "add_object_entry: hashtable_count = %d", n); >+ cc_log(tmpbuf); >+ } >+#endif >+ > obj->n_file_info_indexes = n; > obj->file_info_indexes = x_malloc(n * sizeof(*obj->file_info_indexes)); > add_file_info_indexes(obj->file_info_indexes, n, mf, included_files); > memcpy(obj->hash.hash, object_hash->hash, mf->hash_size); > obj->hash.size = object_hash->size; >+#if defined(CI_DEBUG) >+ { >+ int i; >+ static char tmpbuf[1024]; >+ unsigned char *cp = (unsigned char *) obj->hash.hash ; >+ n = snprintf(tmpbuf, 1024,"add_object_entry: "); >+ for(i = 0; i < mf->hash_size; i++) >+ snprintf(&tmpbuf[n+i*2], 1024 - n - i * 2, "%02x", cp[i]); >+ snprintf(&tmpbuf[1024 - n - i * 2 + 2], 1024, "\n"); >+ cc_log(tmpbuf); >+ } >+#endif > } > > /* >Binary files ccache/test/main and ccache-gsplit-dwarf-support/test/main differ >Only in ccache: testdir.18714 >Only in ccache: testdir.19069 >Only in ccache: testdir.20915 >Only in ccache: testdir.2264 >Only in ccache-gsplit-dwarf-support: testdir.3089 >Only in ccache-gsplit-dwarf-support: testdir.865 >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/util.c ccache-gsplit-dwarf-support/util.c >--- ccache/util.c 2015-03-04 23:01:48.153927399 +0900 >+++ ccache-gsplit-dwarf-support/util.c 2015-03-04 23:09:57.217004306 +0900 >@@ -108,15 +108,28 @@ path_max(const char *path) > } > > static void >+warn_log_fail() { >+ fprintf(stderr, >+ "Writing to logfile failed.\n" >+ "Check the permission and make sure there is enough room for writing to the filesystem.\n"); >+ /* maybe we should exit here? */ >+} >+ >+static void > vlog(const char *format, va_list ap, bool log_updated_time) > { >+ int rc1, rc2; > if (!init_log()) { > return; > } > > log_prefix(log_updated_time); >- vfprintf(logfile, format, ap); >- fprintf(logfile, "\n"); >+ rc1 = vfprintf(logfile, format, ap); >+ rc2 = fprintf(logfile, "\n"); >+ if (rc1 < 0 || rc2 < 0) { >+ warn_log_fail(); >+ } >+ > } > > /* >@@ -153,6 +166,7 @@ cc_bulklog(const char *format, ...) > void > cc_log_argv(const char *prefix, char **argv) > { >+ int rc; > if (!init_log()) { > return; > } >@@ -160,7 +174,9 @@ cc_log_argv(const char *prefix, char **a > log_prefix(true); > fputs(prefix, logfile); > print_command(logfile, argv); >- fflush(logfile); >+ rc = fflush(logfile); >+ if (rc) >+ warn_log_fail(); > } > > /* something went badly wrong! */ >@@ -560,7 +576,6 @@ get_hostname(void) > } > WSACleanup(); > #endif >- > hostname[sizeof(hostname) - 1] = 0; > return hostname; > } >@@ -827,7 +842,7 @@ traverse(const char *dir, void (*fn)(con > fname = format("%s/%s", dir, de->d_name); > if (lstat(fname, &st)) { > if (errno != ENOENT) { >- perror(fname); >+ cc_log("lstat on file %s failed.", fname); > } > free(fname); > continue; >@@ -1413,8 +1428,14 @@ x_rename(const char *oldpath, const char > int > tmp_unlink(const char *path) > { >- cc_log("Unlink %s", path); >- return unlink(path); >+ /* verbose for debugging -gsplit-dwarf */ >+ int rc; >+ cc_log("tmp_unlink:Unlink %s", path); >+ rc = unlink(path); >+ if (rc) { >+ cc_log("tmp_unlink:Unlink failed: rc = %d", rc); >+ } >+ return rc; > } > > /* >@@ -1430,7 +1451,7 @@ x_unlink(const char *path) > */ > char *tmp_name = format("%s.rm.%s", path, tmp_string()); > int result = 0; >- cc_log("Unlink %s via %s", path, tmp_name); >+ cc_log("x_unlink: Unlink %s via %s", path, tmp_name); > if (x_rename(path, tmp_name) == -1) { > result = -1; > goto out; >@@ -1443,6 +1464,10 @@ x_unlink(const char *path) > } > out: > free(tmp_name); >+ if (result) { >+ /* verbose for debugging -gsplit-dwarf */ >+ cc_log("x_unlink: failed result = %d", result); >+ } > return result; > } > >diff '--exclude=test.sh' '--exclude=*.log' '--exclude=*.o' '--exclude=.gitignore' '--exclude=config.status' '--exclude=autom4te.cache' '--exclude=.deps' '--exclude=.git' '--exclude=*.txt' '--exclude=*.in' '--exclude=Makefile*' -p -uibwr ccache/version.c ccache-gsplit-dwarf-support/version.c >--- ccache/version.c 2014-12-26 00:10:38.346977900 +0900 >+++ ccache-gsplit-dwarf-support/version.c 2015-03-04 23:25:29.047632064 +0900 >@@ -1 +1 @@ >-const char CCACHE_VERSION[] = "3.2.1+1_g090af0a"; >+const char CCACHE_VERSION[] = "3.1.9+354_g50a749f";
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 10005
:
10567
|
10813
|
10815
|
10819
|
10843
|
10844
|
10845
|
10846
|
10847
|
10848
|
10849
|
10850
|
10996
|
11014
|
11197