dwarves: Add destructors

So that at program exit we can verify, using tools, that no memory was
leaked.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2009-03-11 12:31:17 -03:00
parent f62770c4a2
commit 8cc4949b00
10 changed files with 225 additions and 81 deletions

View File

@ -679,6 +679,21 @@ static int cu_show_diffs_iterator(struct cu *cu, void *cookie)
return 0;
}
static int cu_delete_priv(struct cu *cu, void *cookie __unused)
{
struct class *c;
struct function *f;
uint32_t id;
cu__for_each_struct(cu, id, c)
free(c->priv);
cu__for_each_function(cu, id, f)
free(f->priv);
return 0;
}
static void print_total_function_diff(const char *filename)
{
printf("\n%s:\n", filename);
@ -750,17 +765,12 @@ static struct argp codiff__argp = {
int main(int argc, char *argv[])
{
int remaining, err;
int remaining, err, rc = EXIT_FAILURE;
struct cus *old_cus, *new_cus;
char *old_filename, *new_filename;
char *filenames[2];
struct stat st;
if (dwarves__init(0)) {
fputs("codiff: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
if (argp_parse(&codiff__argp, argc, argv, 0, &remaining, NULL) ||
remaining < argc) {
switch (argc - remaining) {
@ -772,6 +782,11 @@ int main(int argc, char *argv[])
} else {
failure:
argp_help(&codiff__argp, stderr, ARGP_HELP_SEE, argv[0]);
goto out;
}
if (dwarves__init(0)) {
fputs("codiff: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
@ -829,5 +844,13 @@ failure:
print_total_function_diff(new_filename);
}
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__for_each_cu(old_cus, cu_delete_priv, NULL, NULL);
cus__for_each_cu(new_cus, cu_delete_priv, NULL, NULL);
cus__delete(old_cus);
cus__delete(new_cus);
strlist__delete(structs_printed);
dwarves__exit();
return rc;
}

View File

@ -875,10 +875,11 @@ int main(int argc, char *argv[])
char classes_filename[PATH_MAX];
struct structure *pos;
FILE *fp_functions;
int rc = EXIT_FAILURE;
if (dwarves__init(0)) {
fputs("ctracer: insufficient memory\n", stderr);
return EXIT_FAILURE;
goto out;
}
if (argp_parse(&ctracer__argp, argc, argv, 0, &remaining, NULL) ||
@ -892,7 +893,7 @@ int main(int argc, char *argv[])
} else {
failure:
argp_help(&ctracer__argp, stderr, ARGP_HELP_SEE, argv[0]);
return EXIT_FAILURE;
goto out;
}
type_emissions__init(&emissions);
@ -906,7 +907,7 @@ failure:
methods_cus = cus__new();
if (methods_cus == NULL) {
fputs("ctracer: insufficient memory\n", stderr);
return EXIT_FAILURE;
goto out;
}
/*
@ -920,7 +921,7 @@ failure:
fprintf(stderr, "ctracer: couldn't load DWARF info "
"from %s dir with glob %s\n",
dirname, glob);
return EXIT_FAILURE;
goto out;
}
/*
@ -930,7 +931,7 @@ failure:
err = cus__load(methods_cus, filename);
if (err != 0) {
cus__print_error_msg("ctracer", methods_cus, filename, err);
return EXIT_FAILURE;
goto out;
}
}
@ -940,7 +941,7 @@ failure:
class = cus__find_struct_by_name(methods_cus, &cu, class_name, 0, NULL);
if (class == NULL) {
fprintf(stderr, "ctracer: struct %s not found!\n", class_name);
return EXIT_FAILURE;
goto out;
}
snprintf(functions_filename, sizeof(functions_filename),
@ -949,7 +950,7 @@ failure:
if (fp_functions == NULL) {
fprintf(stderr, "ctracer: couldn't create %s\n",
functions_filename);
exit(EXIT_FAILURE);
goto out;
}
snprintf(methods_filename, sizeof(methods_filename),
@ -958,7 +959,7 @@ failure:
if (fp_methods == NULL) {
fprintf(stderr, "ctracer: couldn't create %s\n",
methods_filename);
exit(EXIT_FAILURE);
goto out;
}
snprintf(collector_filename, sizeof(collector_filename),
@ -967,7 +968,7 @@ failure:
if (fp_collector == NULL) {
fprintf(stderr, "ctracer: couldn't create %s\n",
collector_filename);
exit(EXIT_FAILURE);
goto out;
}
snprintf(classes_filename, sizeof(classes_filename),
@ -976,7 +977,7 @@ failure:
if (fp_classes == NULL) {
fprintf(stderr, "ctracer: couldn't create %s\n",
classes_filename);
exit(EXIT_FAILURE);
goto out;
}
fputs("%{\n"
@ -1037,5 +1038,9 @@ failure:
fclose(fp_classes);
strlist__delete(cu_blacklist);
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(methods_cus);
dwarves__exit();
return rc;
}

View File

@ -41,19 +41,23 @@ static void cus__dump_class_tag_names(struct cus *self)
int main(int argc __unused, char *argv[])
{
int err;
int err, rc = EXIT_FAILURE;
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("dtagnames: insufficient memory\n", stderr);
return EXIT_FAILURE;
goto out;
}
err = cus__loadfl(cus, NULL, argv + 1);
if (err != 0)
return EXIT_FAILURE;
goto out;
cus__dump_class_tag_names(cus);
print_malloc_stats();
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(cus);
dwarves__exit();
return rc;
}

View File

@ -1530,11 +1530,18 @@ static unsigned long long dwarf_tag__orig_type(const struct tag *self,
return cu->extra_dbg_info ? dtag->type : 0;
}
static void dwarf_tag__free_orig_info(struct tag *self, struct cu *cu __unused)
{
free(self->priv);
self->priv = NULL;
}
static struct cu_orig_info dwarf_orig_info_ops = {
.tag__decl_file = dwarf_tag__decl_file,
.tag__decl_line = dwarf_tag__decl_line,
.tag__orig_id = dwarf_tag__orig_id,
.tag__orig_type = dwarf_tag__orig_type,
.tag__free_orig_info = dwarf_tag__free_orig_info,
};
static int tag__delete_priv(struct tag *self, struct cu *cu __unused,

View File

@ -563,20 +563,31 @@ out_free:
goto out;
}
static void array_type__delete(struct tag *self)
{
free(tag__array_type(self)->nr_entries);
free(self);
}
static int cu__delete_tag(struct tag *self, struct cu *cu __unused,
void *cookie __unused)
{
tag__free_orig_info(self, cu);
switch (self->tag) {
case DW_TAG_array_type:
array_type__delete(self); break;
default:
free(self); break;
}
return 0;
}
void cu__delete(struct cu *self)
{
struct tag *pos, *n;
list_for_each_entry_safe(pos, n, &self->tags, node) {
list_del_init(&pos->node);
/* Look for nested namespaces */
if (tag__has_namespace(pos))
namespace__delete(tag__namespace(pos));
}
cu__for_all_tags(self, cu__delete_tag, NULL);
ptr_table__exit(&self->tags_table);
ptr_table__exit(&self->types_table);
free(self->name);
free(self);
}
@ -2474,9 +2485,9 @@ static int list__for_all_tags(struct list_head *self, struct cu *cu,
struct cu *cu, void *cookie),
void *cookie)
{
struct tag *pos;
struct tag *pos, *n;
list_for_each_entry(pos, self, node) {
list_for_each_entry_safe(pos, n, self, node) {
if (tag__has_namespace(pos)) {
if (list__for_all_tags(&tag__namespace(pos)->tags,
cu, iterator, cookie))
@ -2486,18 +2497,23 @@ static int list__for_all_tags(struct list_head *self, struct cu *cu,
cu, iterator, cookie))
return 1;
}
} if (tag__is_function(pos)) {
} else if (tag__is_function(pos)) {
if (list__for_all_tags(&tag__ftype(pos)->parms,
cu, iterator, cookie))
return 1;
if (list__for_all_tags(&tag__function(pos)->lexblock.tags,
cu, iterator, cookie))
return 1;
} if (pos->tag == DW_TAG_subroutine_type) {
} else if (pos->tag == DW_TAG_subroutine_type) {
if (list__for_all_tags(&tag__ftype(pos)->parms,
cu, iterator, cookie))
return 1;
} else if (pos->tag == DW_TAG_lexical_block) {
if (list__for_all_tags(&tag__lexblock(pos)->tags,
cu, iterator, cookie))
return 1;
}
if (iterator(pos, cu, cookie))
return 1;
}
@ -2626,6 +2642,21 @@ struct cus *cus__new(void)
return self;
}
void cus__delete(struct cus *self)
{
struct cu *pos, *n;
if (self == NULL)
return;
list_for_each_entry_safe(pos, n, &self->cus, node) {
list_del_init(&pos->node);
cu__delete(pos);
}
free(self);
}
int dwarves__init(uint16_t user_cacheline_size)
{
strings = strings__new();
@ -2646,6 +2677,12 @@ int dwarves__init(uint16_t user_cacheline_size)
return 0;
}
void dwarves__exit(void)
{
strings__delete(strings);
strings = NULL;
}
struct argp_state;
void dwarves_print_version(FILE *fp, struct argp_state *state __unused)

View File

@ -34,6 +34,7 @@ struct cus {
};
struct cus *cus__new(void);
void cus__delete(struct cus *self);
struct ptr_table {
void **entries;
@ -100,6 +101,8 @@ struct cu_orig_info {
const struct cu *cu);
unsigned long long (*tag__orig_type)(const struct tag *self,
const struct cu *cu);
void (*tag__free_orig_info)(struct tag *self,
struct cu *cu);
};
struct cu {
@ -226,7 +229,12 @@ static inline unsigned long long tag__orig_type(const struct tag *self,
{
return cu->orig_info ? cu->orig_info->tag__orig_type(self, cu) : 0;
}
static inline void tag__free_orig_info(struct tag *self, struct cu *cu)
{
return cu->orig_info ? cu->orig_info->tag__free_orig_info(self, cu) : 0;
}
struct ptr_to_member_type {
struct tag tag;
Dwarf_Off containing_type;
@ -641,6 +649,7 @@ struct conf_fprintf {
};
int dwarves__init(uint16_t user_cacheline_size);
void dwarves__exit(void);
extern void class__find_holes(struct class *self, const struct cu *cu);
extern int class__has_hole_ge(const struct class *self, const uint16_t size);

View File

@ -84,6 +84,11 @@ static struct structure *structure__new(struct class *class, uint16_t id,
return self;
}
static void structure__delete(struct structure *self)
{
free(self);
}
static void *structures__tree;
static LIST_HEAD(structures__anonymous_list);
static LIST_HEAD(structures__named_list);
@ -178,6 +183,23 @@ static struct structure *structures__find(strings_t name)
return s;
}
void void_structure__delete(void *structure)
{
structure__delete(structure);
}
void structures__delete(void)
{
struct structure *pos, *n;
list_for_each_entry_safe(pos, n, &structures__anonymous_list, node) {
list_del_init(&pos->node);
structure__delete(pos);
}
tdestroy(structures__tree, void_structure__delete);
}
static void nr_definitions_formatter(struct structure *self)
{
printf("%s%c%u\n", class__name(self->class), separator,
@ -1052,24 +1074,25 @@ static struct argp pahole__argp = {
int main(int argc, char *argv[])
{
int err, remaining;
struct cus *cus = cus__new();
if (dwarves__init(cacheline_size) || cus == NULL) {
fputs("pahole: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
int err, remaining, rc = EXIT_FAILURE;
struct cus *cus;
if (argp_parse(&pahole__argp, argc, argv, 0, &remaining, NULL) ||
remaining == argc) {
argp_help(&pahole__argp, stderr, ARGP_HELP_SEE, argv[0]);
return EXIT_FAILURE;
goto out;
}
cus = cus__new();
if (dwarves__init(cacheline_size) || cus == NULL) {
fputs("pahole: insufficient memory\n", stderr);
goto out;
}
err = cus__loadfl(cus, &conf_load, argv + remaining);
if (err != 0) {
fputs("pahole: No debugging information found\n", stderr);
return EXIT_FAILURE;
goto out;
}
if (word_size != 0) {
@ -1080,7 +1103,7 @@ int main(int argc, char *argv[])
if (long_int_str_t == 0 || long_unsigned_int_str_t == 0) {
fputs("pahole: couldn't find one of \"long int\" or "
"\"long unsigned int\" types", stderr);
return EXIT_FAILURE;
goto out;
}
cus__for_each_cu(cus, cu_fixup_word_size_iterator, NULL, NULL);
@ -1098,7 +1121,8 @@ int main(int argc, char *argv[])
tag__fprintf(tag, cu, &conf, stdout);
putchar('\n');
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
goto out;
}
cus__for_each_cu(cus, cu_unique_iterator, NULL, cu__filter);
@ -1106,8 +1130,10 @@ int main(int argc, char *argv[])
* Done on cu_unique_iterator, we just want to print the CUs
* that have class_name defined
*/
if (defined_in)
return EXIT_SUCCESS;
if (defined_in) {
rc = EXIT_SUCCESS;
goto out;
}
if (formatter == nr_methods_formatter)
cus__for_each_cu(cus, cu_nr_methods_iterator, NULL, cu__filter);
@ -1119,13 +1145,13 @@ int main(int argc, char *argv[])
if (!stname) {
fprintf(stderr, "struct %s not found!\n", class_name);
return EXIT_FAILURE;
goto out;
}
s = structures__find(stname);
if (s == NULL) {
fprintf(stderr, "struct %s not found!\n", class_name);
return EXIT_FAILURE;
goto out;
}
if (reorganize) {
@ -1135,7 +1161,7 @@ int main(int argc, char *argv[])
struct class *clone = class__clone(s->class, NULL);
if (clone == NULL) {
fprintf(stderr, "pahole: out of memory!\n");
return EXIT_FAILURE;
goto out;
}
class__reorganize(clone, s->cu, reorg_verbose, stdout);
savings = class__size(s->class) - class__size(clone);
@ -1171,6 +1197,10 @@ int main(int argc, char *argv[])
}
} else
print_classes(formatter);
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(cus);
structures__delete();
dwarves__exit();
return rc;
}

View File

@ -98,24 +98,28 @@ static struct argp pdwtags__argp = {
int main(int argc, char *argv[])
{
int err, remaining;
int err, remaining, rc = EXIT_FAILURE;
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("pwdtags: insufficient memory\n", stderr);
return EXIT_FAILURE;
goto out;
}
if (argp_parse(&pdwtags__argp, argc, argv, 0, &remaining, NULL) ||
remaining == argc) {
argp_help(&pdwtags__argp, stderr, ARGP_HELP_SEE, argv[0]);
return EXIT_FAILURE;
goto out;
}
err = cus__loadfl(cus, NULL, argv + remaining);
if (err != 0)
return EXIT_FAILURE;
goto out;
cus__emit_tags(cus);
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(cus);
dwarves__exit();
return rc;
}

View File

@ -57,6 +57,11 @@ static struct fn_stats *fn_stats__new(struct tag *tag, const struct cu *cu)
return self;
}
static void fn_stats__delete(struct fn_stats *self)
{
free(self);
}
static LIST_HEAD(fn_stats__list);
static struct fn_stats *fn_stats__find(const char *name)
@ -70,6 +75,16 @@ static struct fn_stats *fn_stats__find(const char *name)
return NULL;
}
static void fn_stats__delete_list(void)
{
struct fn_stats *pos, *n;
list_for_each_entry_safe(pos, n, &fn_stats__list, node) {
list_del_init(&pos->node);
fn_stats__delete(pos);
}
}
static void fn_stats__add(struct tag *tag, const struct cu *cu)
{
struct fn_stats *fns = fn_stats__new(tag, cu);
@ -504,23 +519,24 @@ static struct argp pfunct__argp = {
int main(int argc, char *argv[])
{
int err, remaining;
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("pfunct: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
int err, remaining, rc = EXIT_FAILURE;
struct cus *cus;
if (argp_parse(&pfunct__argp, argc, argv, 0, &remaining, NULL) ||
remaining == argc) {
argp_help(&pfunct__argp, stderr, ARGP_HELP_SEE, argv[0]);
return EXIT_FAILURE;
goto out;
}
cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("pfunct: insufficient memory\n", stderr);
goto out;
}
err = cus__loadfl(cus, &conf_load, argv + remaining);
if (err != 0)
return EXIT_FAILURE;
goto out;
cus__for_each_cu(cus, cu_unique_iterator, NULL, NULL);
@ -534,5 +550,10 @@ int main(int argc, char *argv[])
else
print_fn_stats(formatter);
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(cus);
fn_stats__delete_list();
dwarves__exit();
return rc;
}

View File

@ -316,23 +316,24 @@ static struct argp pglobal__argp = {
int main(int argc, char *argv[])
{
int err, remaining;
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("pglobal: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
int err, remaining, rc = EXIT_FAILURE;
if (argp_parse(&pglobal__argp, argc, argv, 0, &remaining, NULL) ||
remaining == argc) {
argp_help(&pglobal__argp, stderr, ARGP_HELP_SEE, argv[0]);
return EXIT_FAILURE;
goto out;
}
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("pglobal: insufficient memory\n", stderr);
goto out;
}
err = cus__loadfl(cus, NULL, argv + remaining);
if (err != 0)
return EXIT_FAILURE;
goto out;
if (walk_var) {
cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL);
@ -343,6 +344,9 @@ int main(int argc, char *argv[])
}
tdestroy(tree, free_node);
return EXIT_SUCCESS;
rc = EXIT_SUCCESS;
out:
cus__delete(cus);
dwarves__exit();
return rc;
}