The Samba-Bugzilla – Attachment 10567 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]
Patch to support -gsplit-dwarf
split-dwarf.patch (text/plain), 39.90 KB, created by
ishikawa
on 2014-12-25 14:52:10 UTC
(
hide
)
Description:
Patch to support -gsplit-dwarf
Filename:
MIME Type:
Creator:
ishikawa
Created:
2014-12-25 14:52:10 UTC
Size:
39.90 KB
patch
obsolete
>diff --git a/ccache.c b/ccache.c >index c407760..434a3f9 100644 >--- a/ccache.c >+++ b/ccache.c >@@ -95,9 +95,15 @@ 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; >+ >+/* in conjunction with -gsplit-dwarf, try to reduce copying */ >+static int called_compiler = 0; >+ > /* > * Name (represented as a struct file_hash) of the file containing the cached > * object code. >@@ -129,6 +135,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 +188,24 @@ char *stats_file = NULL; > /* Whether the output is a precompiled header */ > static bool output_is_precompiled_header = false; > >+/* >+ * -gsplit-dwarf support: >+ * Also used for profile support (?) >+ * >+ * 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 +300,7 @@ failed(void) > fatal("execv of %s failed: %s", orig_args->argv[0], strerror(errno)); > } > >+ > static const char * > temp_dir() > { >@@ -735,19 +775,89 @@ static void > to_cache(struct args *args) > { > char *tmp_stdout, *tmp_stderr, *tmp_dia; >+ 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 .two file name >+ * >+ * What is the reliable way of creating the .two 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 here 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. >+ // >+ // Not sure what .dwo file path name which GCC produces in >+ // the following case. >+ // tmp_dwo concatenate ".dwo" to tmp_obj ; ??? >+ // tmp_obj = format("%s.tmp.%s", cached_obj, tmp_string()); >+ // >+ // Fact: gcc-4.8 produced the following .two file for >+ // the command below. >+ // t-test.o.tmp.gazonk >+ // 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. >+ // Strip anything after the final '.' and add "dwo" instead. >+ >+ cp = strrchr(tmp_obj, '.'); >+ assert(cp != NULL); >+ { >+ /* should be ATOMIC, but since we already created cp using >+ * x_strdup, and format, we should be relatively safe. >+ */ >+ *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); > > if (output_dia) { >- tmp_dia = x_strdup(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, tmp_dia); > } else { >@@ -777,6 +887,13 @@ to_cache(struct args *args) > stats_update(STATS_MISSING); > tmp_unlink(tmp_stdout); > tmp_unlink(tmp_stderr); >+ /* -gsplit-dwarf support */ >+ tmp_unlink(tmp_obj); >+ if (tmp_dia) { /* CI ??? TODO/FIXME: dont we need this? */ >+ tmp_unlink(tmp_dia); >+ } >+ if(tmp_dwo) >+ tmp_unlink(tmp_dwo); > failed(); > } > if (st.st_size != 0) { >@@ -784,14 +901,23 @@ to_cache(struct args *args) > stats_update(STATS_STDOUT); > tmp_unlink(tmp_stdout); > tmp_unlink(tmp_stderr); >+ tmp_unlink(tmp_obj); /* -gsplit-dwarf support */ > if (tmp_dia) { > tmp_unlink(tmp_dia); > } >+ if (tmp_dwo) { /* -gsplit-dwarf support */ >+ 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,12 +964,22 @@ to_cache(struct args *args) > > fd = open(tmp_stderr, O_RDONLY | O_BINARY); > if (fd != -1) { >- if (str_eq(output_obj, "/dev/null") || errno == ENOENT) { >+ /* TODO/FIXME: the order of OR clauses >+ * may have some issue. >+ */ >+ if ( str_eq(output_obj, "/dev/null") >+ || errno == ENOENT >+ ) { > /* we can use a quick method of getting the failed output */ > copy_fd(fd, 2); > 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. >+ */ >+ > if (output_dia) { > int ret; > x_unlink(output_dia); >@@ -867,30 +1003,63 @@ to_cache(struct args *args) > } > } > >+ >+ > exit(status); > } > } > >+ cc_log("verbose: (tmp_stderr) %s being removed", tmp_stderr); > tmp_unlink(tmp_stderr); >+ >+ 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(); > } >@@ -903,11 +1072,25 @@ 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); >+ /* >+ * TODO/FIXME: 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) { >@@ -918,16 +1101,69 @@ to_cache(struct args *args) > > if (tmp_dia) { > if (stat(tmp_dia, &st) != 0) { >- cc_log("Failed to stat %s: %s", tmp_dia, strerror(errno)); >+ 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(tmp_dia, cached_dia); >+ cc_log("(cached_dia) Stored in cache: %s", cached_dia); > } > } > >- put_file_in_cache(output_obj, cached_obj); >+ /* TODO/DONE : >+ 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 called AFTER the processing of >+ * .dwo file below. >+ */ >+ >+ /* TODO/FIXME: if we output to real object file first, then >+ tmp_obj *IS* the real object, and so we should not remove it! >+ and instead, 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); >+ >+ /* TODO/FIXME: if we output to real object file first, then >+ tmp_dwo *IS* the real .dwo file, and so we should not remove it! >+ and instead, we should not copy back the cached file to the final >+ destination .dwo. This is a waste of time. >+ Same can be said of .o file above: real and cached one. >+ Somehow dependency file was not copied this way. >+ */ >+ /* tmp_unlink(tmp_dwo); */ >+ } >+ > stats_update(STATS_TOCACHE); > > /* Make sure we have a CACHEDIR.TAG in the cache part of cache_dir. This can >@@ -953,9 +1189,12 @@ to_cache(struct args *args) > } > } > >+ free(tmp_obj); > free(tmp_stderr); > free(tmp_stdout); > free(tmp_dia); >+ if(tmp_dwo) >+ free(tmp_dwo); > } > > /* >@@ -977,7 +1216,7 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) > maximum filename length limits */ > input_base = basename(input_file); > tmp = strchr(input_base, '.'); >- if (tmp) { >+ if (tmp != NULL) { > *tmp = 0; > } > if (strlen(input_base) > 10) { >@@ -986,13 +1225,18 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) > > 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); > > if (direct_i_file) { >- /* We are compiling a .i or .ii file - that means we can skip the cpp stage >- * and directly form the correct i_tmpfile. */ >+ /* >+ * Fixed typo: form -> from >+ * we are compiling a .i or .ii file - that means we >+ * can skip the cpp stage and directly from the >+ * correct i_tmpfile >+ */ > path_stdout = input_file; > status = 0; > } else { >@@ -1016,8 +1260,12 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) > } > > if (conf->unify) { >- /* When we are doing the unifying tricks we need to include the input file >- * name in the hash to get the warnings right. */ >+ /* >+ * reindented: >+ * When we are doing the unifying tricks we need to >+ * include the input file name in the hash to get the >+ * warnings right. >+ */ > hash_delimiter(hash, "unifyfilename"); > hash_string(hash, input_file); > >@@ -1077,6 +1325,28 @@ update_cached_result_globals(struct file_hash *hash) > 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: 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! >+ */ >+ 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); > } >@@ -1193,7 +1463,6 @@ calculate_common_hash(struct args *args, struct mdfour *hash) > } > free(p); > } >- > /* Possibly hash GCC_COLORS (for color diagnostics). */ > if (compiler_is_gcc(args)) { > const char *gcc_colors = getenv("GCC_COLORS"); >@@ -1328,6 +1597,10 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) > 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 >@@ -1348,6 +1621,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) > * artifacts will be produced in the wrong place. > */ > if (profile_generate) { >+ output_to_real_object_first = true; > if (!profile_dir) { > profile_dir = get_cwd(); > } >@@ -1355,10 +1629,18 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) > 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. >+ * >+ * DONE: check the reference to profile_use and mimic its >+ * processing. >+ */ > 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(); >@@ -1383,7 +1665,7 @@ calculate_object_hash(struct args *args, struct mdfour *hash, int direct_mode) > "OBJCPLUS_INCLUDE_PATH", /* clang */ > NULL > }; >- for (p = envvars; *p; ++p) { >+ for (p = envvars; *p != NULL; ++p) { > char *v = getenv(*p); > if (v) { > hash_delimiter(hash, *p); >@@ -1440,6 +1722,7 @@ static void > from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > { > int fd_stderr; >+ int ret; > struct stat st; > bool produce_dep_file; > >@@ -1448,28 +1731,61 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > 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.) >@@ -1482,20 +1798,133 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > return; > } > >- if (!str_eq(output_obj, "/dev/null")) { >+ /* TODO/DONE: In the else clause, do a similar processing for >+ split dwarf file. cached_dwo. in case -gsplit-dwarf is specified. */ >+ >+ if (str_eq(output_obj, "/dev/null")) { >+ ret = 0; >+ } else { /* not /dev/null */ >+ /* when generating object in direct mode */ >+ if( output_to_real_object_first && called_compiler) { >+ assert(mode == FROMCACHE_COMPILED_MODE); >+ /* we don't need to 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 { >+ 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 0 >+ if( strcmp (output_obj, tmp_obj) != 0) >+ cc_log("PROBLEM: ooutput_obj=%s != tmp_obj=%s", output_obj, tmp_obj); >+#endif >+ } >+ >+ /* >+ * if something failed internal to get_file_from_cache >+ * we may want to remove these files: >+ * 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 compiler in this run of ccache since >+ // the output_dwo would have been created by the compiler. >+ if (!called_compiler) { >+ assert(mode == FROMCACHE_CPP_MODE || mode == FROMCACHE_DIRECT_MODE); >+ get_file_from_cache(cached_dwo, output_dwo); >+ >+ } else { >+ 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); >+ } >+ /* TODO/FIXME: >+ * if something failed internal to get_file_from_cache >+ * we may want to remove files. >+ * >+ * maybe failed() called when error exit is taken does this? >+ * 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); >+ * x_unlink(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); >+ /* >+ * if something failed internal to get_file_from_cache >+ * we may want to remove these files: >+ * if(output_dwo) x_unlink(output_dwo); >+ * if(cached_dwo) x_unlink(cached_dwo); >+ * >+ * x_unlink(output_obj); >+ * x_unlink(output_dep); >+ * x_unlink(cached_stderr); >+ * x_unlink(cached_obj); >+ * x_unlink(cached_dep); >+ * x_unlink(cached_dia); >+ */ > } >+ > 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); >+ >+ /* >+ * if something failed internal to get_file_from_cache >+ * we may want to remove these files: >+ * if(output_dwo) x_unlink(output_dwo); >+ * if(cached_dwo) x_unlink(cached_dwo); >+ * x_unlink(output_obj); >+ * x_unlink(output_dep); >+ * x_unlink(output_dia); >+ * x_unlink(cached_stderr); >+ * x_unlink(cached_obj); >+ * x_unlink(cached_dep); >+ * x_unlink(cached_dia); >+ */ > } > >+ >+ /* 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); > update_mtime(cached_stderr); >+ > if (produce_dep_file) { > update_mtime(cached_dep); > } >@@ -1507,13 +1936,24 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > 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); > } > >+ /* TODO/FIXME: not sure if we should put .dwo file hash in manifest.. >+ * Is it possible that the content of manifest is used to clear/remove >+ * files when "ccache -C" is issued? If so, then we need to put >+ * .dwo file entry in manifest. >+ */ >+ > /* Create or update the manifest file. */ > if (conf->direct_mode > && put_object_in_manifest >@@ -1528,8 +1968,17 @@ from_cache(enum fromcache_call_mode mode, bool put_object_in_manifest) > 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); >+ >+ /* >+ * TODO/FIXME: 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); > } >@@ -1641,6 +2090,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > bool result = true; > bool found_color_diagnostics = false; > >+ > expanded_args = args_copy(args); > stripped_args = args_init(0, NULL); > dep_args = args_init(0, NULL); >@@ -1679,6 +2129,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > if (argpath[-1] == '-') { > ++argpath; > } >+ > file_args = args_init_from_gcc_atfile(argpath); > if (!file_args) { > cc_log("Couldn't read arg file %s", argpath); >@@ -1775,6 +2226,12 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > 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; > } >@@ -1785,6 +2242,20 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > 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 > */ >@@ -2174,6 +2645,19 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > > /* 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) { >@@ -2212,7 +2696,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > } > > output_is_precompiled_header = >- actual_language && strstr(actual_language, "-header"); >+ (actual_language && strstr(actual_language, "-header") != NULL); > > if (output_is_precompiled_header > && !(conf->sloppiness & SLOPPY_PCH_DEFINES)) { >@@ -2235,6 +2719,8 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > } else { > stats_update(STATS_LINK); > } >+ // git dev does not have the following line. Oct 10, 2014 >+ // stats_update(STATS_CANTUSEPCH); > result = false; > goto out; > } >@@ -2261,6 +2747,9 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > conf->cpp_extension = x_strdup(extension_for_language(p_language) + 1); > } > >+ /* TODO/FIXME: Is there an angle in which split_dwarf_p processing >+ has anything to do with "-" output ? */ >+ > /* don't try to second guess the compilers heuristics for stdout handling */ > if (output_obj && str_eq(output_obj, "-")) { > stats_update(STATS_OUTSTDOUT); >@@ -2269,6 +2758,54 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > goto out; > } > >+ /* -gsplit-dwarf support. >+ * we have probably already seen and check for >+ * -gsplit-dwarf by the time we reach here. (Do 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? >+ */ >+ >+ /* >+ * Question: 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 condition needs to be handled. >+ * My modification 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. >+ */ >+ >+ /* I think it is OK here, but just comment it here. We 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); >@@ -2287,6 +2824,27 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > } > } > >+ /* --gsplit-dwarf: 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); >+ } >+ >+ >+ /* TODO/DONE: Do we need to cope with strange >+ output_obj file name in case split_dwarf_p ? */ >+ > /* cope with -o /dev/null */ > if (!str_eq(output_obj,"/dev/null") > && stat(output_obj, &st) == 0 >@@ -2315,6 +2873,7 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > 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. >@@ -2337,6 +2896,18 @@ cc_process_args(struct args *args, struct args **preprocessor_args, > } > } > >+ /* -gsplit-dwarf support >+ * >+ * -gsplit-dwarf processing should not affect dependency generation. >+ * BUT, given the command line below, >+ * dependency file is generated first and then >+ * ccache.o is generated. >+ * Note 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. > */ >@@ -2469,10 +3040,12 @@ initialize(void) > if (str_eq(conf->cache_dir, "")) { > fatal("configuration setting \"cache_dir\" must not be the empty string"); > } >+ > if ((p = getenv("CCACHE_DIR"))) { > free(conf->cache_dir); > conf->cache_dir = strdup(p); > } >+ > if (str_eq(conf->cache_dir, "")) { > fatal("CCACHE_DIR must not be the empty string"); > } >@@ -2509,6 +3082,7 @@ initialize(void) > if (conf->umask != UINT_MAX) { > umask(conf->umask); > } >+ > } > > /* Reset the global state. Used by the test suite. */ >@@ -2524,10 +3098,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; >@@ -2544,6 +3120,12 @@ cc_reset(void) > output_is_precompiled_header = false; > > conf = conf_create(); >+ split_dwarf_p = false; >+ >+#if 0 >+ /* Not any more, Dec 14 ?*/ >+ initialize(); >+#endif > } > > /* Make a copy of stderr that will not be cached, so things like >@@ -2604,6 +3186,8 @@ ccache(int argc, char *argv[]) > signal(SIGINT, signal_handler); > signal(SIGTERM, signal_handler); > >+ >+ /* this one added Oct 2014 */ > if (str_eq(conf->temporary_dir, "")) { > clean_up_internal_tempdir(); > } >@@ -2639,7 +3223,33 @@ ccache(int argc, char *argv[]) > if (output_dia) { > cc_log("Diagnostic file: %s", output_dia); > } >- cc_log("Object file: %s", output_obj); >+ >+ /* TODO/DONE: cc_process_args ought to have generated >+ * output_dwo. But we may not want to do so yet before >+ * generating_dependencies ? >+ */ >+ if (split_dwarf_p ) { >+#if 0 >+ if(output_obj) >+ cc_log("output_obj = %s", output_obj); >+ if(output_dep) >+ cc_log("output_dep = %s", output_dep); >+#endif >+ 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); >@@ -2713,6 +3323,8 @@ ccache(int argc, char *argv[]) > put_object_in_manifest = true; > } > >+ called_compiler = 0; >+ > /* if we can return from cache at this point then do */ > from_cache(FROMCACHE_CPP_MODE, put_object_in_manifest); > >@@ -2726,6 +3338,8 @@ ccache(int argc, char *argv[]) > /* run real compiler, sending output to cache */ > to_cache(compiler_args); > >+ called_compiler = 1; >+ > /* return from cache */ > from_cache(FROMCACHE_COMPILED_MODE, put_object_in_manifest); > >diff --git a/cleanup.c b/cleanup.c >index ee872cc..d810685 100644 >--- a/cleanup.c >+++ b/cleanup.c >@@ -72,7 +72,7 @@ traverse_fn(const char *fname, struct stat *st) > goto out; > } > >- if (strstr(p, ".tmp.")) { >+ if (strstr(p, ".tmp.") != NULL) { > /* delete any tmp files older than 1 hour */ > if (st->st_mtime + 3600 < time(NULL)) { > x_unlink(fname); >diff --git a/compopt.c b/compopt.c >index 1996fdf..c1802e0 100644 >--- a/compopt.c >+++ b/compopt.c >@@ -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}, >diff --git a/hash.c b/hash.c >index 80beed2..5994a9d 100644 >--- a/hash.c >+++ b/hash.c >@@ -128,6 +128,7 @@ hash_file(struct mdfour *md, const char *fname) > > fd = open(fname, O_RDONLY|O_BINARY); > if (fd == -1) { >+ perror(fname); /* to catch strange errors. */ > return false; > } > >diff --git a/language.c b/language.c >index 110066a..0714b5d 100644 >--- a/language.c >+++ b/language.c >@@ -1,5 +1,5 @@ > /* >- * Copyright (C) 2010, 2013 Joel Rosdahl >+ * Copyright (C) 2010-2014 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 *language) > bool > language_is_supported(const char *language) > { >- return p_language_for_language(language); >+ return p_language_for_language(language) != NULL; > } > > bool >diff --git a/manifest.c b/manifest.c >index 6eb53fd..de78c03 100644 >--- a/manifest.c >+++ b/manifest.c >@@ -70,6 +70,7 @@ static const uint32_t MAGIC = 0x63436d46U; > static const uint32_t MAX_MANIFEST_ENTRIES = 100; > static const uint32_t MAX_MANIFEST_FILE_INFO_ENTRIES = 10000; > >+ > #define ccache_static_assert(e) \ > do { enum { ccache_static_assert__ = 1/(e) }; } while (false) > >@@ -598,11 +599,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 > } > > /* >diff --git a/mdfour.c b/mdfour.c >index 06bc17f..7659f3f 100644 >--- a/mdfour.c >+++ b/mdfour.c >@@ -163,7 +163,7 @@ mdfour_update(struct mdfour *md, const unsigned char *in, size_t n) > > m = md; > >- if (!in) { >+ if (in == NULL) { > if (!md->finalized) { > mdfour_tail(md->tail, md->tail_len); > md->finalized = 1; >diff --git a/system.h b/system.h >index 0692dcd..d9ca63c 100644 >--- a/system.h >+++ b/system.h >@@ -38,6 +38,7 @@ > #include <fcntl.h> > #include <inttypes.h> > #include <limits.h> >+/* strange: without signal.h, the compilation succeeded ? */ > #include <signal.h> > #include <stdarg.h> > #include <stddef.h> >diff --git a/util.c b/util.c >index 80eb58b..01955a9 100644 >--- a/util.c >+++ b/util.c >@@ -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 **argv) > log_prefix(true); > fputs(prefix, logfile); > print_command(logfile, argv); >- fflush(logfile); >+ rc = fflush(logfile); >+ if(rc) >+ warn_log_fail(); > } > > /* something went badly wrong! */ >@@ -245,7 +261,7 @@ get_umask(void) > int > copy_file(const char *src, const char *dest, int compress_level) > { >- int fd_in, fd_out; >+ int fd_in = -1, fd_out = -1; > gzFile gz_in = NULL, gz_out = NULL; > char buf[10240]; > int n, written; >@@ -1073,7 +1089,6 @@ create_tmp_fd(char **fname) > if (fd == -1) { > fatal("Failed to create file %s: %s", template, strerror(errno)); > } >- > #ifndef _WIN32 > fchmod(fd, 0666 & ~get_umask()); > #endif >@@ -1318,8 +1333,14 @@ x_rename(const char *oldpath, const char *newpath) > 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; > } > > /* >@@ -1335,7 +1356,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; >@@ -1348,6 +1369,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; > } >
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