GHashTable *structs_seen;
GList *named_structs;
GHashTable *vars_seen;
- const char *dwfl_file_name;
+ char *dwfl_file_name;
Dwarf *dwarf;
Dwfl *dwfl;
int repeat_detection;
/*
* Filter a GList, calling a predicate on it and removing all elements for which
- * the predicate returns true.
+ * the predicate returns true, calling the free_func on them if set.
*/
typedef int (*filter_pred_fun) (void *element, void *data);
-static GList *list_filter(GList *list, filter_pred_fun fun, void *data);
+static GList *list_filter(GList *list, filter_pred_fun fun, GDestroyNotify free_func,
+ void *data);
/*
* Figure out the (pathless, suffixless) module name for a given module file (.o
object_names[object_names_cnt-1] = xstrdup(line);
}
+ free(line);
if (ferror(f)) {
fprintf(stderr, "Error reading from %s: %s\n",
g_hash_table_insert(dedup_blacklist, xstrdup(line), NULL);
}
+ free(line);
if (ferror(f)) {
fprintf(stderr, "Error reading from %s: %s\n",
g_hash_table_insert(member_blacklist, absolutized, NULL);
}
+ free(line);
if (ferror(f)) {
fprintf(stderr, "Error reading from %s: %s\n",
dw_ctf_trace("Duplicate detection: primary pass.\n");
+ /*
+ * This is merely flushed between TUs, not recreated: we create it here.
+ */
+ state.vars_seen = g_hash_table_new_full(g_str_hash,
+ g_str_equal,
+ free, NULL);
+
for (i = 0; i < object_names_cnt; i++)
process_file(object_names[i], detect_duplicates,
detect_duplicates_tu_init,
state.repeat_detection = 0;
state.named_structs = list_filter(state.named_structs,
detect_duplicates_alias_fixup,
+ free_duplicates_id_file,
&state);
} while (state.repeat_detection);
out:
struct detect_duplicates_state *state = data;
state->structs_seen = g_hash_table_new_full(g_str_hash, g_str_equal,
- free, free);
- if (state->module_name == NULL ||
- (strcmp(state->module_name, module_name) != 0)) {
- if (state->module_name != NULL)
- g_hash_table_remove_all(state->vars_seen);
- else
- state->vars_seen = g_hash_table_new_full(g_str_hash,
- g_str_equal,
- free, NULL);
- }
+ free, NULL);
+ g_hash_table_remove_all(state->vars_seen);
state->module_name = module_name;
}
{
struct detect_duplicates_state *state = data;
+ /*
+ * We have to annul module_name because it is freed between object files
+ * by process_file(). Since we use that to track whether vars_seen
+ * needs reconstructing, that means we have to destroy that as well.
+ */
g_hash_table_destroy(state->structs_seen);
state->structs_seen = NULL;
+ state->module_name = NULL;
}
/*
simple_dwfl_free(state->dwfl);
state->dwfl = NULL;
state->dwarf = NULL;
+ free(state->dwfl_file_name);
state->dwfl_file_name = NULL;
if (state->structs_seen)
g_hash_table_destroy(state->structs_seen);
* structure, its opaque alias is easy to compute, but the converse is not
* true.)
*
- * As a list_filter() filter function, returns 0 if this structure will not need
- * to be checked again (because both its opaque and transparent variants are
- * shared).
+ * As a list_filter() filter function, returns nonzero if this structure will
+ * not need to be checked again (because both its opaque and transparent
+ * variants are shared).
*/
static int detect_duplicates_alias_fixup(void *id_file_data, void *data)
{
if (state->dwfl_file_name == NULL) {
state->dwfl = simple_dwfl_new(id_file->file_name, &mod);
state->dwarf = dwfl_module_getdwarf(mod, &dummy);
- state->dwfl_file_name = id_file->file_name;
+ state->dwfl_file_name = xstrdup(id_file->file_name);
+ if (state->structs_seen)
+ g_hash_table_destroy(state->structs_seen);
state->structs_seen = g_hash_table_new_full(g_str_hash,
g_str_equal,
- free, free);
+ free, NULL);
}
if (!dwarf_offdie(state->dwarf, id_file->dieoff,
&die)) {
/*
* Filter a GList, calling a predicate on it and removing all elements for which
- * the predicate returns true.
+ * the predicate returns true, calling the free_func on them if set.
*/
-static GList *list_filter(GList *list, filter_pred_fun fun, void *data)
+static GList *list_filter(GList *list, filter_pred_fun fun,
+ GDestroyNotify free_func, void *data)
{
GList *cur = list;
while (cur) {
GList *next = cur->next;
- if (fun(cur->data, data))
+ if (fun(cur->data, data)) {
+ if (free_func)
+ free_func(cur->data);
list = g_list_delete_link(list, cur);
+ }
cur = next;
}
ctf_close(per_mod->ctf_file);
g_hash_table_destroy(per_mod->member_counts);
+ free(per_module);
}
/*