1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
|
/*
Copyright (C) 2006 Mandriva Conectiva S.A.
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
#include <assert.h>
#include <dwarf.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dwarves.h"
#include "dutil.h"
static void refcnt_tag(struct tag *tag, const struct cu *cu);
static void refcnt_member(struct class_member *member, const struct cu *cu)
{
if (member->visited)
return;
member->visited = 1;
if (member->tag.type != 0) { /* if not void */
struct tag *type = cu__type(cu, member->tag.type);
if (type != NULL)
refcnt_tag(type, cu);
}
}
static void refcnt_parameter(const struct parameter *parameter,
const struct cu *cu)
{
if (parameter->tag.type != 0) { /* if not void */
struct tag *type = cu__type(cu, parameter->tag.type);
if (type != NULL)
refcnt_tag(type, cu);
}
}
static void refcnt_variable(const struct variable *variable,
const struct cu *cu)
{
if (variable->ip.tag.type != 0) { /* if not void */
struct tag *type = cu__type(cu, variable->ip.tag.type);
if (type != NULL)
refcnt_tag(type, cu);
}
}
static void refcnt_inline_expansion(const struct inline_expansion *exp,
const struct cu *cu)
{
if (exp->ip.tag.type != 0) { /* if not void */
struct tag *type = cu__function(cu, exp->ip.tag.type);
if (type != NULL)
refcnt_tag(type, cu);
}
}
static void refcnt_tag(struct tag *tag, const struct cu *cu)
{
struct class_member *member;
tag->visited = 1;
if (tag__is_struct(tag) || tag__is_union(tag))
type__for_each_member(tag__type(tag), member)
refcnt_member(member, cu);
}
static void refcnt_lexblock(const struct lexblock *lexblock, const struct cu *cu)
{
struct tag *pos;
list_for_each_entry(pos, &lexblock->tags, node)
switch (pos->tag) {
case DW_TAG_variable:
refcnt_variable(tag__variable(pos), cu);
break;
case DW_TAG_inlined_subroutine:
refcnt_inline_expansion(tag__inline_expansion(pos), cu);
break;
case DW_TAG_lexical_block:
refcnt_lexblock(tag__lexblock(pos), cu);
break;
}
}
static void refcnt_function(struct function *function, const struct cu *cu)
{
struct parameter *parameter;
function->proto.tag.visited = 1;
if (function->proto.tag.type != 0) /* if not void */ {
struct tag *type = cu__type(cu, function->proto.tag.type);
if (type != NULL)
refcnt_tag(type, cu);
}
list_for_each_entry(parameter, &function->proto.parms, tag.node)
refcnt_parameter(parameter, cu);
refcnt_lexblock(&function->lexblock, cu);
}
static int cu_refcnt_iterator(struct cu *cu, void *cookie __unused)
{
struct function *pos;
uint32_t id;
cu__for_each_function(cu, id, pos)
refcnt_function(pos, cu);
return 0;
}
static int lost_iterator(struct tag *tag, struct cu *cu,
void *cookie __unused)
{
if (!tag->visited && tag__decl_file(tag, cu)) {
tag__fprintf(tag, cu, NULL, stdout);
puts(";\n");
}
return 0;
}
static int cu_lost_iterator(struct cu *cu, void *cookie)
{
return cu__for_all_tags(cu, lost_iterator, cookie);
}
int main(int argc __unused, char *argv[])
{
int err;
struct cus *cus = cus__new();
if (dwarves__init(0) || cus == NULL) {
fputs("prefcnt: insufficient memory\n", stderr);
return EXIT_FAILURE;
}
err = cus__load_files(cus, NULL, argv + 1);
if (err != 0) {
cus__fprintf_load_files_err(cus, "prefcnt", argv + 1, err, stderr);
return EXIT_FAILURE;
}
cus__for_each_cu(cus, cu_refcnt_iterator, NULL, NULL);
cus__for_each_cu(cus, cu_lost_iterator, NULL, NULL);
return EXIT_SUCCESS;
}
|