mirror of
https://github.com/reactos/ccache.git
synced 2025-02-21 11:30:29 +00:00
Disable direct mode if __{DATE,FILE,TIME}__ is used
This commit is contained in:
parent
6faf3267d2
commit
149d4912dc
47
ccache.c
47
ccache.c
@ -288,7 +288,12 @@ static char *get_path_in_cache(const char *name, const char *suffix)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Takes over ownership of path. */
|
||||
/*
|
||||
* This function hashes an include file and stores the path and hash in the
|
||||
* global included_files variable. It also checks if the include file contains
|
||||
* __DATE__/__FILE__/__TIME__ macros, in which case the file is not stored and
|
||||
* direct mode is disabled. Takes over ownership of path.
|
||||
*/
|
||||
static void remember_include_file(char *path, size_t path_len)
|
||||
{
|
||||
struct file_hash *h;
|
||||
@ -296,6 +301,7 @@ static void remember_include_file(char *path, size_t path_len)
|
||||
struct stat st;
|
||||
int fd = -1;
|
||||
char *data = (char *)-1;
|
||||
enum hash_source_code_result result;
|
||||
|
||||
if (!included_files) {
|
||||
goto ignore;
|
||||
@ -342,7 +348,16 @@ static void remember_include_file(char *path, size_t path_len)
|
||||
}
|
||||
|
||||
hash_start(&fhash);
|
||||
hash_include_file_string(&fhash, data, st.st_size);
|
||||
result = hash_source_code_string(&fhash, data, st.st_size, 1);
|
||||
switch (result) {
|
||||
case HASH_SOURCE_CODE_OK:
|
||||
break;
|
||||
case HASH_SOURCE_CODE_FOUND_VOLATILE_MACRO:
|
||||
cc_log("Found __DATE__/__FILE__/__TIME__ macro in %s", path);
|
||||
/* Fall through. */
|
||||
case HASH_SOURCE_CODE_ERROR:
|
||||
goto failure;
|
||||
}
|
||||
|
||||
h = x_malloc(sizeof(*h));
|
||||
hash_result_as_bytes(&fhash, h->hash);
|
||||
@ -354,8 +369,6 @@ static void remember_include_file(char *path, size_t path_len)
|
||||
failure:
|
||||
cc_log("Disabling direct mode");
|
||||
enable_direct = 0;
|
||||
hashtable_destroy(included_files, 1);
|
||||
included_files = NULL;
|
||||
/* Fall through. */
|
||||
ignore:
|
||||
free(path);
|
||||
@ -386,10 +399,12 @@ static char *make_relative_path(char *path)
|
||||
|
||||
/*
|
||||
* This function reads and hashes a file. While doing this, it also does these
|
||||
* things with preprocessor lines starting with a hash:
|
||||
* things:
|
||||
*
|
||||
* - Makes include file paths whose prefix is CCACHE_BASEDIR relative.
|
||||
* - Stores the paths of included files in the global variable included_files.
|
||||
* - Makes include file paths whose prefix is CCACHE_BASEDIR relative when
|
||||
* computing the hash sum.
|
||||
* - Stores the paths and hashes of included files in the global variable
|
||||
* included_files.
|
||||
*/
|
||||
static int process_preprocessed_file(struct mdfour *hash, const char *path)
|
||||
{
|
||||
@ -746,6 +761,7 @@ static int find_hash(ARGS *args, enum findhash_call_mode mode)
|
||||
char *object_name;
|
||||
char *manifest_name;
|
||||
const char *compilercheck;
|
||||
enum hash_source_code_result result;
|
||||
|
||||
switch (mode) {
|
||||
case FINDHASH_DIRECT_MODE:
|
||||
@ -860,9 +876,19 @@ static int find_hash(ARGS *args, enum findhash_call_mode mode)
|
||||
|
||||
switch (mode) {
|
||||
case FINDHASH_DIRECT_MODE:
|
||||
if (!hash_include_file(&hash, input_file)) {
|
||||
cc_log("Failed to hash %s", input_file);
|
||||
result = hash_source_code_file(&hash, input_file, 1);
|
||||
switch (result) {
|
||||
case HASH_SOURCE_CODE_OK:
|
||||
break;
|
||||
case HASH_SOURCE_CODE_ERROR:
|
||||
failed();
|
||||
break;
|
||||
case HASH_SOURCE_CODE_FOUND_VOLATILE_MACRO:
|
||||
cc_log("Found __DATE__/__FILE__/__TIME__ macro in %s",
|
||||
input_file);
|
||||
cc_log("Disabling direct mode");
|
||||
enable_direct = 0;
|
||||
break;
|
||||
}
|
||||
manifest_name = hash_result(&hash);
|
||||
manifest_path = get_path_in_cache(manifest_name, ".manifest");
|
||||
@ -1046,7 +1072,8 @@ static void from_cache(enum fromcache_call_mode mode, int put_object_in_manifest
|
||||
}
|
||||
|
||||
/* Create or update the manifest file. */
|
||||
if (put_object_in_manifest
|
||||
if (enable_direct
|
||||
&& put_object_in_manifest
|
||||
&& included_files
|
||||
&& !getenv("CCACHE_READONLY")) {
|
||||
if (manifest_put(manifest_path, object_hash, included_files)) {
|
||||
|
@ -381,13 +381,14 @@ disabled), ccache falls back to the preprocessor mode.
|
||||
|
||||
The direct mode will be disabled if any of the following holds:
|
||||
|
||||
* the environment variable CCACHE_NODIRECT is set
|
||||
* the environment variable *CCACHE_NODIRECT* is set
|
||||
* a modification time of one of the include files is too new (needed to avoid a
|
||||
race condition)
|
||||
* the unifier is enabled (the environment variable *CCACHE_UNIFY* is set)
|
||||
* a compiler option unsupported by the direct mode is used
|
||||
** Currently, *-Wp,_X_* options are not supported, except if _X_ is
|
||||
*-MD,_path_* or *-MMD,_path_*.
|
||||
* a *-Wp,_X_* compiler option other than *-Wp,-MD,_path_* and *-Wp,-MMD,_path_*
|
||||
is used
|
||||
* a *\_\_DATE\_\_*, *\_\_FILE\_\_* or *\_\_TIME__* macro is used in the source
|
||||
code
|
||||
|
||||
|
||||
THE PREPROCESSOR MODE
|
||||
|
54
hashutil.c
54
hashutil.c
@ -50,8 +50,15 @@ int file_hashes_equal(struct file_hash *fh1, struct file_hash *fh2)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void hash_include_file_string(
|
||||
struct mdfour *hash, const char *str, size_t len)
|
||||
/*
|
||||
* Hash a string ignoring comments. If check_volatile_macros is true, also
|
||||
* check for volatile preprocessor macros (__{DATE,FILE,TIME}__) and, if found,
|
||||
* stop hashing.
|
||||
*/
|
||||
enum hash_source_code_result
|
||||
hash_source_code_string(
|
||||
struct mdfour *hash, const char *str, size_t len,
|
||||
int check_volatile_macros)
|
||||
{
|
||||
const char *p;
|
||||
const char *end;
|
||||
@ -115,6 +122,20 @@ void hash_include_file_string(
|
||||
}
|
||||
break;
|
||||
|
||||
/* Potential start of volatile macro. */
|
||||
case '_':
|
||||
if (check_volatile_macros
|
||||
&& p + 7 < end
|
||||
&& p[1] == '_'
|
||||
&& p[6] == '_'
|
||||
&& p[7] == '_'
|
||||
&& (strncmp(p + 2, "DATE", 4) == 0
|
||||
|| strncmp(p + 2, "FILE", 4) == 0
|
||||
|| strncmp(p + 2, "TIME", 4) == 0)) {
|
||||
return HASH_SOURCE_CODE_FOUND_VOLATILE_MACRO;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -125,38 +146,45 @@ void hash_include_file_string(
|
||||
|
||||
end:
|
||||
hash_buffer(hash, hashbuf, hashbuflen);
|
||||
return HASH_SOURCE_CODE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add contents of a file to a hash, but don't hash comments. Returns 1 on
|
||||
* success, otherwise 0.
|
||||
* Add contents of a source code file to a hash, but don't hash comments.
|
||||
*/
|
||||
int hash_include_file(struct mdfour *hash, const char *path)
|
||||
enum hash_source_code_result
|
||||
hash_source_code_file(
|
||||
struct mdfour *hash, const char *path,
|
||||
int check_volatile_macros)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *data;
|
||||
enum hash_source_code_result result;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
fd = open(path, O_RDONLY|O_BINARY);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
cc_log("Failed to open %s", path);
|
||||
return HASH_SOURCE_CODE_ERROR;
|
||||
}
|
||||
if (fstat(fd, &st) == -1) {
|
||||
cc_log("Failed to fstat %s", path);
|
||||
close(fd);
|
||||
return 0;
|
||||
return HASH_SOURCE_CODE_ERROR;
|
||||
}
|
||||
if (st.st_size == 0) {
|
||||
close(fd);
|
||||
return 1;
|
||||
return HASH_SOURCE_CODE_OK;
|
||||
}
|
||||
data = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
close(fd);
|
||||
if (data == (void *)-1) {
|
||||
return 0;
|
||||
cc_log("Failed to mmap %s", path);
|
||||
return HASH_SOURCE_CODE_ERROR;
|
||||
}
|
||||
|
||||
hash_include_file_string(hash, data, st.st_size);
|
||||
|
||||
result = hash_source_code_string(
|
||||
hash, data, st.st_size, check_volatile_macros);
|
||||
munmap(data, st.st_size);
|
||||
return 1;
|
||||
return result;
|
||||
}
|
||||
|
17
hashutil.h
17
hashutil.h
@ -14,8 +14,19 @@ unsigned int hash_from_string(void *str);
|
||||
int strings_equal(void *str1, void *str2);
|
||||
int file_hashes_equal(struct file_hash *fh1, struct file_hash *fh2);
|
||||
|
||||
void hash_include_file_string(
|
||||
struct mdfour *hash, const char *str, size_t len);
|
||||
int hash_include_file(struct mdfour *hash, const char *path);
|
||||
enum hash_source_code_result {
|
||||
HASH_SOURCE_CODE_OK,
|
||||
HASH_SOURCE_CODE_ERROR,
|
||||
HASH_SOURCE_CODE_FOUND_VOLATILE_MACRO
|
||||
};
|
||||
|
||||
enum hash_source_code_result
|
||||
hash_source_code_string(
|
||||
struct mdfour *hash, const char *str, size_t len,
|
||||
int check_volatile_macros);
|
||||
enum hash_source_code_result
|
||||
hash_source_code_file(
|
||||
struct mdfour *hash, const char *path,
|
||||
int check_volatile_macros);
|
||||
|
||||
#endif
|
||||
|
@ -370,7 +370,9 @@ static int verify_object(struct manifest *mf, struct object *obj,
|
||||
if (!actual) {
|
||||
actual = x_malloc(sizeof(*actual));
|
||||
hash_start(&hash);
|
||||
if (!hash_include_file(&hash, mf->files[fi->index])) {
|
||||
if (hash_source_code_file(&hash, mf->files[fi->index],
|
||||
0)
|
||||
!= HASH_SOURCE_CODE_OK) {
|
||||
cc_log("Failed hashing %s",
|
||||
mf->files[fi->index]);
|
||||
free(actual);
|
||||
|
35
test.sh
35
test.sh
@ -506,6 +506,7 @@ EOF
|
||||
test_failed "$dep_file missing"
|
||||
fi
|
||||
done
|
||||
rm -rf test.dir
|
||||
|
||||
##################################################################
|
||||
# Check that -Wp,-MD,file.d works.
|
||||
@ -774,6 +775,40 @@ EOF
|
||||
checkstat 'cache hit (preprocessed)' 0
|
||||
checkstat 'cache miss' 1
|
||||
|
||||
##################################################################
|
||||
# Check that direct mode is disabled if __DATE__, __FILE__ or __TIME__
|
||||
# macros are used.
|
||||
for x in date file time; do
|
||||
X=`echo $x | tr 'a-z' 'A-Z'`
|
||||
testname="__${X}__ in source file"
|
||||
$CCACHE -Cz >/dev/null
|
||||
cat <<EOF >$x.c
|
||||
char $x[] = __${X}__;
|
||||
EOF
|
||||
$CCACHE $COMPILER -c $x.c
|
||||
checkstat 'cache hit (direct)' 0
|
||||
checkstat 'cache hit (preprocessed)' 0
|
||||
checkstat 'cache miss' 1
|
||||
$CCACHE $COMPILER -c $x.c
|
||||
checkstat 'cache hit (direct)' 0
|
||||
|
||||
testname="__${X}__ in include file"
|
||||
$CCACHE -Cz >/dev/null
|
||||
cat <<EOF >$x.h
|
||||
char $x[] = __${X}__;
|
||||
EOF
|
||||
backdate $x.h
|
||||
cat <<EOF >${x}_h.c
|
||||
#include "$x.h"
|
||||
EOF
|
||||
$CCACHE $COMPILER -c ${x}_h.c
|
||||
checkstat 'cache hit (direct)' 0
|
||||
checkstat 'cache hit (preprocessed)' 0
|
||||
checkstat 'cache miss' 1
|
||||
$CCACHE $COMPILER -c ${x}_h.c
|
||||
checkstat 'cache hit (direct)' 0
|
||||
done
|
||||
|
||||
##################################################################
|
||||
# Reset things.
|
||||
CCACHE_NODIRECT=1
|
||||
|
Loading…
x
Reference in New Issue
Block a user