From 0f61a4620ce0fc33b012a8e12af6b17ad32f64fd Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 22 Jun 2018 14:44:01 +0300 Subject: [PATCH] db: introduce the cache_db The point of this is that say you want to record some information about a how a type is used in a file, instead of recording over and over you can record it in the cache_db. You'd put restrictions against duplicate rows or whatever. Then it's written after we finish parsing the file. Signed-off-by: Dan Carpenter --- smatch.h | 5 ++++ smatch_db.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/smatch.h b/smatch.h index d86f20ec..4c06fc5c 100644 --- a/smatch.h +++ b/smatch.h @@ -759,6 +759,7 @@ enum info_type { extern struct sqlite3 *smatch_db; extern struct sqlite3 *mem_db; +extern struct sqlite3 *cache_db; void debug_sql(struct sqlite3 *db, const char *sql); void db_ignore_states(int id); @@ -802,6 +803,8 @@ do { \ #define mem_sql(call_back, data, sql...) \ sql_helper(mem_db, call_back, data, sql) +#define cache_sql(call_back, data, sql...) \ + sql_helper(cache_db, call_back, data, sql) #define sql_insert_helper(table, db, ignore, late, values...) \ do { \ @@ -843,6 +846,8 @@ do { \ #define sql_insert(table, values...) sql_insert_helper(table, 0, 0, 0, values); #define sql_insert_or_ignore(table, values...) sql_insert_helper(table, 0, 1, 0, values); #define sql_insert_late(table, values...) sql_insert_helper(table, 0, 0, 1, values); +#define sql_insert_cache(table, values...) sql_insert_helper(table, cache_db, 1, 0, values); + char *get_static_filter(struct symbol *sym); void sql_insert_return_states(int return_id, const char *return_ranges, diff --git a/smatch_db.c b/smatch_db.c index 58117ff2..9172d965 100644 --- a/smatch_db.c +++ b/smatch_db.c @@ -25,6 +25,7 @@ struct sqlite3 *smatch_db; struct sqlite3 *mem_db; +struct sqlite3 *cache_db; static int return_id; @@ -1973,6 +1974,82 @@ static void init_memdb(void) } } +static void init_cachedb(void) +{ + char *err = NULL; + int rc; + const char *schema_files[] = { + "db/call_implies.schema", + "db/type_info.schema", + }; + static char buf[4096]; + int fd; + int ret; + int i; + + rc = sqlite3_open(":memory:", &cache_db); + if (rc != SQLITE_OK) { + printf("Error starting In-Memory database."); + return; + } + + for (i = 0; i < ARRAY_SIZE(schema_files); i++) { + fd = open_data_file(schema_files[i]); + if (fd < 0) { + printf("failed to open: %s\n", schema_files[i]); + continue; + } + ret = read(fd, buf, sizeof(buf)); + if (ret < 0) { + printf("failed to read: %s\n", schema_files[i]); + continue; + } + close(fd); + if (ret == sizeof(buf)) { + printf("Schema file too large: %s (limit %zd bytes)", + schema_files[i], sizeof(buf)); + continue; + } + buf[ret] = '\0'; + rc = sqlite3_exec(cache_db, buf, NULL, NULL, &err); + if (rc != SQLITE_OK) { + fprintf(stderr, "SQL error #2: %s\n", err); + fprintf(stderr, "%s\n", buf); + } + } +} + +static int save_cache_data(void *_table, int argc, char **argv, char **azColName) +{ + static char buf[4096]; + char *p = buf; + char *table = _table; + int i; + + + p += snprintf(p, 4096 - (p - buf), "insert or ignore into %s values (", table); + for (i = 0; i < argc; i++) { + if (i) + p += snprintf(p, 4096 - (p - buf), ", "); + p += snprintf(p, 4096 - (p - buf), "'%s'", argv[i]); + + } + p += snprintf(p, 4096 - (p - buf), ");"); + if (p - buf > 4096) + return 0; + + sm_msg("SQL: %s", buf); + return 0; +} + +static void dump_cache(struct symbol_list *sym_list) +{ + if (!option_info) + return; + cache_sql(&save_cache_data, (char *)"type_info", "select * from type_info;"); + cache_sql(&save_cache_data, (char *)"call_implies", "select * from call_implies;"); +} + void open_smatch_db(void) { int rc; @@ -1984,6 +2061,7 @@ void open_smatch_db(void) memset(use_states, 0xff, num_checks + 1); init_memdb(); + init_cachedb(); rc = sqlite3_open_v2("smatch_db.sqlite", &smatch_db, SQLITE_OPEN_READONLY, NULL); if (rc != SQLITE_OK) { @@ -2113,6 +2191,8 @@ void register_definition_db_callbacks(int id) register_common_funcs(); register_return_replacements(); + + add_hook(&dump_cache, END_FILE_HOOK); } void register_db_call_marker(int id) -- 2.11.4.GIT