[CLASSES]: Become struct tag centric

So far struct class was being used as the main data structure, switch to struct
tag, that already was the top of the tag hierarchy, being a struct class
ancestor, so reflect that and stop using struct class as the catch all class,
as a started DW_TAG_array_type tags are now represented by a new class, struct
array_type, reducing the size of struct class and reducing DW__TAG_array_type
instance memory usage.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2006-12-29 15:28:58 -02:00
parent 3e177d577a
commit bbf3f8d95e
7 changed files with 346 additions and 325 deletions

463
classes.c
View File

@ -185,7 +185,6 @@ static size_t enumeration__snprintf(const struct class *self,
static void enumeration__print(const struct class *self, const char *suffix,
uint8_t ntabs)
{
struct enumerator *pos;
char bf[4096];
if (ntabs >= sizeof(tabs))
@ -310,10 +309,9 @@ static struct cu *cu__new(uint32_t cu, const char *name)
return self;
}
static void cu__add_class(struct cu *self, struct class *class)
static void cu__add_tag(struct cu *self, struct tag *tag)
{
class->cu = self;
list_add_tail(&class->tag.node, &self->classes);
list_add_tail(&tag->node, &self->classes);
}
static void cu__add_function(struct cu *self, struct function *function)
@ -328,7 +326,7 @@ static void cu__add_variable(struct cu *self, struct variable *variable)
list_add_tail(&variable->cu_node, &self->variables);
}
static const char *tag_name(const struct cu *cu, const uint32_t tag)
static const char *tag__prefix(const struct cu *cu, const uint32_t tag)
{
switch (tag) {
case DW_TAG_enumeration_type: return "enum ";
@ -342,48 +340,37 @@ static const char *tag_name(const struct cu *cu, const uint32_t tag)
return "";
}
int tag__fwd_decl(const struct cu *cu, const struct tag *tag)
struct tag *cu__find_tag_by_id(const struct cu *self, const Dwarf_Off id)
{
struct class *type = cu__find_class_by_id(cu, tag->type);
struct tag *pos;
/* void ? */
if (type == NULL)
return 0;
if (id == 0)
return NULL;
if (type->tag.tag != DW_TAG_pointer_type)
return 0;
list_for_each_entry(pos, &self->classes, node)
if (pos->id == id)
return pos;
next_indirection:
type = cu__find_class_by_id(cu, type->tag.type);
if (type != NULL && type->tag.tag == DW_TAG_pointer_type)
goto next_indirection;
if (type == NULL || type->tag.tag != DW_TAG_structure_type)
return 0;
if (type->visited)
return 0;
out:
type->visited = 1;
printf("%s%s;\n", tag_name(cu, type->tag.tag), type->name);
return 1;
return NULL;
}
struct class *cu__find_class_by_name(const struct cu *self, const char *name)
{
struct class *pos;
struct tag *pos;
if (name == NULL)
return NULL;
list_for_each_entry(pos, &self->classes, tag.node)
if (pos->name != NULL &&
list_for_each_entry(pos, &self->classes, node) {
struct class *class = tag__class(pos);
if (class->name != NULL &&
/* FIXME: here there shouldn't be anything other
* than DW_TAG_structure types anyway... */
pos->tag.tag == DW_TAG_structure_type &&
strcmp(pos->name, name) == 0)
return pos;
pos->tag == DW_TAG_structure_type &&
strcmp(class->name, name) == 0)
return tag__class(pos);
}
return NULL;
}
@ -468,20 +455,6 @@ static void cus__add_fwd_decl(struct cus *self, struct class *class)
list_add_tail(&class->node, self->fwd_decls);
}
struct class *cu__find_class_by_id(const struct cu *self, const Dwarf_Off id)
{
struct class *pos;
if (id == 0)
return NULL;
list_for_each_entry(pos, &self->classes, tag.node)
if (pos->tag.id == id)
return pos;
return NULL;
}
struct function *cu__find_function_by_name(const struct cu *self,
const char *name)
{
@ -520,82 +493,78 @@ struct variable *cu__find_variable_by_id(const struct cu *self, const Dwarf_Off
return NULL;
}
int class__is_struct(const struct class *self,
struct class **typedef_alias)
int tag__is_struct(const struct tag *self, struct tag **typedef_alias,
const struct cu *cu)
{
*typedef_alias = NULL;
if (self->tag.tag == DW_TAG_typedef) {
*typedef_alias = cu__find_class_by_id(self->cu, self->tag.type);
if (self->tag == DW_TAG_typedef) {
*typedef_alias = cu__find_tag_by_id(cu, self->type);
if (*typedef_alias == NULL)
return 0;
return (*typedef_alias)->tag.tag == DW_TAG_structure_type;
return (*typedef_alias)->tag == DW_TAG_structure_type;
}
return self->tag.tag == DW_TAG_structure_type;
return self->tag == DW_TAG_structure_type;
}
static size_t class__array_nr_entries(const struct class *self)
static size_t array_type__nr_entries(const struct array_type *self)
{
int i;
size_t nr_entries = 1;
for (i = 0; i < self->array_dimensions; ++i)
nr_entries *= self->array_nr_entries[i];
for (i = 0; i < self->dimensions; ++i)
nr_entries *= self->nr_entries[i];
return nr_entries;
}
static size_t class__size(const struct class *self)
static size_t tag__size(const struct tag *self, const struct cu *cu)
{
size_t size = self->size;
size_t size = 0;
if (self->tag.tag != DW_TAG_pointer_type && self->tag.type != 0) {
struct class *class = cu__find_class_by_id(self->cu,
self->tag.type);
if (class != NULL)
size = class__size(class);
}
if (self->tag != DW_TAG_pointer_type && self->type != 0) {
struct tag *type = cu__find_tag_by_id(cu, self->type);
if (type != NULL)
size = tag__size(type, cu);
} else
size = tag__class(self)->size;
if (self->tag.tag == DW_TAG_array_type)
size *= class__array_nr_entries(self);
if (self->tag == DW_TAG_array_type)
return size * array_type__nr_entries(tag__array_type(self));
return size;
}
const char *class__name(const struct class *self, char *bf, size_t len)
const char *tag__name(const struct tag *self, const struct cu *cu,
char *bf, size_t len)
{
struct tag *type;
char tmpbf[128];
if (self == NULL)
strncpy(bf, "void", len);
else if (self->tag.tag == DW_TAG_pointer_type) {
if (self->tag.type == 0) /* No type == void */
else if (self->tag == DW_TAG_pointer_type) {
if (self->type == 0) /* No type == void */
strncpy(bf, "void *", len);
else {
struct class *ptr_class =
cu__find_class_by_id(self->cu,
self->tag.type);
char ptr_class_name[128];
snprintf(bf, len, "%s *",
class__name(ptr_class, ptr_class_name,
sizeof(ptr_class_name)));
type = cu__find_tag_by_id(cu, self->type);
snprintf(bf, len, "%s *", tag__name(type, cu, tmpbf,
sizeof(tmpbf)));
}
} else if (self->tag.tag == DW_TAG_volatile_type ||
self->tag.tag == DW_TAG_const_type) {
struct class *vol_class = cu__find_class_by_id(self->cu,
self->tag.type);
char vol_class_name[128];
} else if (self->tag == DW_TAG_volatile_type ||
self->tag == DW_TAG_const_type) {
type = cu__find_tag_by_id(cu, self->type);
snprintf(bf, len, "%s %s ",
self->tag.tag == DW_TAG_volatile_type ?
"volatile" : "const",
class__name(vol_class, vol_class_name,
sizeof(vol_class_name)));
} else if (self->tag.tag == DW_TAG_array_type) {
struct class *ptr_class = cu__find_class_by_id(self->cu,
self->tag.type);
return class__name(ptr_class, bf, len);
self->tag == DW_TAG_volatile_type ? "volatile" :
"const",
tag__name(type, cu, tmpbf, sizeof(tmpbf)));
} else if (self->tag == DW_TAG_array_type) {
type = cu__find_tag_by_id(cu, self->type);
return tag__name(type, cu, bf, len);
} else
snprintf(bf, len, "%s%s", tag_name(self->cu, self->tag.tag),
self->name ?: "");
snprintf(bf, len, "%s%s", tag__prefix(cu, self->tag),
tag__class(self)->name ?: "");
return bf;
}
@ -603,9 +572,8 @@ const char *variable__type_name(const struct variable *self,
char *bf, size_t len)
{
if (self->tag.type != 0) {
struct class *class = cu__find_class_by_id(self->cu,
self->tag.type);
return class__name(class, bf, len);
struct tag *tag = cu__find_tag_by_id(self->cu, self->tag.type);
return tag__name(tag, self->cu, bf, len);
} else if (self->abstract_origin != 0) {
struct variable *var;
@ -665,31 +633,29 @@ static struct class_member *class_member__new(Dwarf_Off id,
static size_t class_member__size(const struct class_member *self)
{
struct class *class = cu__find_class_by_id(self->class->cu,
self->tag.type);
assert(class != NULL);
return class__size(class);
struct tag *type = cu__find_tag_by_id(self->class->cu, self->tag.type);
assert(type != NULL);
return tag__size(type, self->class->cu);
}
const char *class__subroutine_mask(const struct class *self,
char *bf, size_t len, int is_pointer)
const char *tag__subroutine_mask(const struct tag *self,
const struct cu *cu,
char *bf, size_t len, int is_pointer)
{
char ret_type_name[128];
if (self->tag.type == 0)
if (self->type == 0)
snprintf(ret_type_name, sizeof(ret_type_name), "void");
else {
struct class *ret_class = cu__find_class_by_id(self->cu,
self->tag.type);
class__name(ret_class, ret_type_name, sizeof(ret_type_name));
struct tag *ret_type = cu__find_tag_by_id(cu, self->type);
tag__name(ret_type, cu, ret_type_name, sizeof(ret_type_name));
}
snprintf(bf, len, "%s (%s%%s)(void /* FIXME: add parm list */)",
ret_type_name, is_pointer ? "*" : "");
return bf;
}
size_t class_member__names(const struct class *type,
size_t class_member__names(const struct tag *type,
const struct class_member *self,
char *class_name, size_t class_name_size,
char *member_name, size_t member_name_size)
@ -697,36 +663,36 @@ size_t class_member__names(const struct class *type,
size_t size = -1;
if (type == NULL)
type = cu__find_class_by_id(self->class->cu, self->tag.type);
type = cu__find_tag_by_id(self->class->cu, self->tag.type);
snprintf(member_name, member_name_size, "%s;", self->name ?: "");
if (type == NULL)
snprintf(class_name, class_name_size, "<%llx>",
self->tag.type);
else {
if (type->tag.tag == DW_TAG_const_type)
type = cu__find_class_by_id(type->cu, type->tag.type);
size = class__size(type);
if (type->tag == DW_TAG_const_type)
type = cu__find_tag_by_id(self->class->cu, type->type);
size = tag__size(type, self->class->cu);
/* Is it a function pointer? */
if (type->tag.tag == DW_TAG_pointer_type) {
struct class *ptr_class =
cu__find_class_by_id(self->class->cu,
type->tag.type);
if (type->tag == DW_TAG_pointer_type) {
struct tag *ptype =
cu__find_tag_by_id(self->class->cu, type->type);
if (ptr_class != NULL &&
ptr_class->tag.tag == DW_TAG_subroutine_type) {
if (ptype != NULL &&
ptype->tag == DW_TAG_subroutine_type) {
/* function has no return value (void) */
if (ptr_class->tag.type == 0)
if (ptype->type == 0)
snprintf(class_name,
class_name_size, "void");
else {
struct class *ret_class =
cu__find_class_by_id(self->class->cu,
ptr_class->tag.type);
struct tag *ret_type =
cu__find_tag_by_id(self->class->cu,
ptype->type);
class__name(ret_class, class_name,
class_name_size);
tag__name(ret_type, self->class->cu,
class_name,
class_name_size);
}
snprintf(member_name, member_name_size,
"(*%s)(void /* FIXME: add parm list */);",
@ -735,18 +701,18 @@ size_t class_member__names(const struct class *type,
}
}
class__name(type, class_name, class_name_size);
if (type->tag.tag == DW_TAG_array_type) {
tag__name(type, self->class->cu, class_name, class_name_size);
if (type->tag == DW_TAG_array_type) {
struct array_type *array = tag__array_type(type);
int i = 0;
size_t n = snprintf(member_name, member_name_size,
"%s", self->name);
member_name += n;
member_name_size -= n;
for (i = 0; i < type->array_dimensions; ++i) {
for (i = 0; i < array->dimensions; ++i) {
n = snprintf(member_name, member_name_size,
"[%u]",
type->array_nr_entries[i]);
"[%u]", array->nr_entries[i]);
member_name += n;
member_name_size -= n;
}
@ -764,40 +730,39 @@ size_t parameter__names(const struct parameter *self,
char *class_name, size_t class_name_size,
char *parameter_name, size_t parameter_name_size)
{
struct class *class = cu__find_class_by_id(self->function->cu,
self->tag.type);
struct tag *type = cu__find_tag_by_id(self->function->cu,
self->tag.type);
size_t size = -1;
snprintf(parameter_name, parameter_name_size, "%s", self->name ?: "");
if (class == NULL)
if (type == NULL)
snprintf(class_name, class_name_size, "<%llx>",
self->tag.type);
else {
if (class->tag.tag == DW_TAG_const_type)
class = cu__find_class_by_id(class->cu,
class->tag.type);
size = class__size(class);
if (type->tag == DW_TAG_const_type)
type = cu__find_tag_by_id(self->function->cu,
type->type);
size = tag__size(type, self->function->cu);
/* Is it a function pointer? */
if (class->tag.tag == DW_TAG_pointer_type) {
struct class *ptr_class =
cu__find_class_by_id(self->function->cu,
class->tag.type);
if (type->tag == DW_TAG_pointer_type) {
struct tag *ptype =
cu__find_tag_by_id(self->function->cu, type->type);
if (ptr_class != NULL &&
ptr_class->tag.tag == DW_TAG_subroutine_type) {
if (ptype != NULL &&
ptype->tag == DW_TAG_subroutine_type) {
/* function has no return value (void) */
if (ptr_class->tag.type == 0)
if (ptype->type == 0)
snprintf(class_name,
class_name_size, "void");
else {
struct class *ret_class =
cu__find_class_by_id(self->function->cu,
ptr_class->tag.type);
struct tag *ret_type =
cu__find_tag_by_id(self->function->cu,
ptype->type);
class__name(ret_class, class_name,
class_name_size);
tag__name(ret_type, self->function->cu,
class_name, class_name_size);
}
snprintf(parameter_name, parameter_name_size,
"(*%s)(void /* FIXME: add "
@ -807,8 +772,10 @@ size_t parameter__names(const struct parameter *self,
}
}
class__name(class, class_name, class_name_size);
if (class->tag.tag == DW_TAG_array_type) {
tag__name(type, self->function->cu,
class_name, class_name_size);
if (type->tag == DW_TAG_array_type) {
struct array_type *array = tag__array_type(type);
int i = 0;
size_t n = snprintf(parameter_name,
parameter_name_size,
@ -816,10 +783,10 @@ size_t parameter__names(const struct parameter *self,
parameter_name += n;
parameter_name_size -= n;
for (i = 0; i < class->array_dimensions; ++i) {
for (i = 0; i < array->dimensions; ++i) {
n = snprintf(parameter_name,
parameter_name_size, "[%u]",
class->array_nr_entries[i]);
array->nr_entries[i]);
parameter_name += n;
parameter_name_size -= n;
}
@ -834,21 +801,21 @@ static size_t class_member__print(struct class_member *self)
size_t size;
char class_name[4096];
char member_name[128];
struct class *type = cu__find_class_by_id(self->class->cu,
self->tag.type);
struct tag *type = cu__find_tag_by_id(self->class->cu, self->tag.type);
assert(type != NULL);
if (type->tag.tag == DW_TAG_enumeration_type) {
size = type->size;
if (type->tag == DW_TAG_enumeration_type) {
const struct class *ctype = tag__class(type);
size = ctype->size;
if (type->name != NULL) {
if (ctype->name != NULL) {
snprintf(class_name, sizeof(class_name), "enum %s",
type->name);
ctype->name);
snprintf(member_name, sizeof(member_name), "%s;",
self->name);
} else {
const size_t spacing = 45 - strlen(self->name);
enumeration__snprintf(type, class_name,
enumeration__snprintf(ctype, class_name,
sizeof(class_name),
self->name, 1);
@ -857,18 +824,19 @@ static size_t class_member__print(struct class_member *self)
self->offset, size);
goto out;
}
} else if (type->tag.tag == DW_TAG_union_type) {
size = type->size;
} else if (type->tag == DW_TAG_union_type) {
const struct class *ctype = tag__class(type);
size = ctype->size;
if (type->name != NULL) {
if (ctype->name != NULL) {
snprintf(class_name, sizeof(class_name), "union %s",
type->name);
ctype->name);
snprintf(member_name, sizeof(member_name), "%s;",
self->name);
} else {
const size_t spacing = 45 - (self->name ?
strlen(self->name) : -1);
union__snprintf(type, class_name, sizeof(class_name),
union__snprintf(ctype, class_name, sizeof(class_name),
self->name, 1);
printf("%s %*.*s/* %5u %5u */",
class_name, spacing, spacing, " ",
@ -945,6 +913,19 @@ static struct label *label__new(Dwarf_Off id, Dwarf_Off type,
return self;
}
static struct array_type *array_type__new(Dwarf_Off id, Dwarf_Off type,
const char *decl_file,
uint32_t decl_line)
{
struct array_type *self = zalloc(sizeof(*self));
if (self != NULL)
tag__init(&self->tag, DW_TAG_array_type, id, type,
decl_file, decl_line);
return self;
}
static struct class *class__new(const uint32_t tag,
Dwarf_Off id, Dwarf_Off type,
const char *name, size_t size,
@ -1015,18 +996,16 @@ static struct function *function__new(Dwarf_Off id, Dwarf_Off type,
}
int function__has_parameter_of_type(const struct function *self,
const struct class *target)
const struct tag *target)
{
struct class_member *pos;
list_for_each_entry(pos, &self->parameters, tag.node) {
struct class *class = cu__find_class_by_id(self->cu,
pos->tag.type);
struct tag *type = cu__find_tag_by_id(self->cu, pos->tag.type);
if (class != NULL && class->tag.tag == DW_TAG_pointer_type) {
class = cu__find_class_by_id(self->cu, class->tag.type);
if (class != NULL &&
class->tag.id == target->tag.id)
if (type != NULL && type->tag == DW_TAG_pointer_type) {
type = cu__find_tag_by_id(self->cu, type->type);
if (type != NULL && type->id == target->id)
return 1;
}
}
@ -1214,7 +1193,7 @@ static void tags__add(void *tags, const struct tag *tag)
tsearch(tag, tags, tags__compare);
}
static void tag__print(const struct tag *tag)
static void function__tag_print(const struct tag *tag)
{
char bf[512];
const void *vtag = tag;
@ -1253,11 +1232,12 @@ static void tag__print(const struct tag *tag)
printf("%-*.*s// %5u\n", 70 - c, 70 - c, " ", tag->decl_line);
}
static void tags__action(const void *nodep, const VISIT which, const int depth)
static void function__tags_action(const void *nodep, const VISIT which,
const int depth)
{
if (which == postorder || which == leaf) {
const struct tag *tag = *(struct tag **)nodep;
tag__print(tag);
function__tag_print(tag);
}
}
@ -1291,7 +1271,7 @@ static void function__print_body(const struct function *self,
}
puts("{");
twalk(tags, tags__action);
twalk(tags, function__tags_action);
puts("}\n");
tdestroy(tags, tags__free);
@ -1302,13 +1282,13 @@ void function__print(const struct function *self, int show_stats,
const int show_inline_expansions)
{
char bf[256];
struct class *class_type;
struct tag *class_type;
const char *type = "<ERROR>";
struct parameter *pos;
int first_parameter = 1;
class_type = cu__find_class_by_id(self->cu, self->tag.type);
type = class__name(class_type, bf, sizeof(bf));
class_type = cu__find_tag_by_id(self->cu, self->tag.type);
type = tag__name(class_type, self->cu, bf, sizeof(bf));
printf("/* %s:%u */\n", self->tag.decl_file, self->tag.decl_line);
printf("%s%s %s(", function__declared_inline(self) ? "inline " : "",
@ -1319,8 +1299,8 @@ void function__print(const struct function *self, int show_stats,
else
first_parameter = 0;
type = "<ERROR>";
class_type = cu__find_class_by_id(self->cu, pos->tag.type);
type = class__name(class_type, bf, sizeof(bf));
class_type = cu__find_tag_by_id(self->cu, pos->tag.type);
type = tag__name(class_type, self->cu, bf, sizeof(bf));
printf("%s %s", type, pos->name ?: "");
}
@ -1380,9 +1360,10 @@ static int class__print_cacheline_boundary(uint32_t last_cacheline,
return cacheline;
}
static void class__print_struct(const struct class *self,
static void class__print_struct(const struct tag *tag,
const char *prefix, const char *suffix)
{
struct class *self = tag__class(tag);
uint32_t sum = 0;
uint32_t sum_holes = 0;
struct class_member *pos;
@ -1507,37 +1488,38 @@ static void class__print_struct(const struct class *self,
self->size - (sum + sum_holes));
}
void class__print(const struct class *self,
const char *prefix, const char *suffix)
void tag__print(const struct tag *self, const struct cu *cu,
const char *prefix, const char *suffix)
{
printf("/* %s:%u */\n", self->tag.decl_file, self->tag.decl_line);
printf("/* %s:%u */\n", self->decl_file, self->decl_line);
switch (self->tag.tag) {
switch (self->tag) {
case DW_TAG_structure_type:
class__print_struct(self, prefix, suffix);
break;
default:
printf("%s%s;\n", tag_name(self->cu, self->tag.tag),
self->name ?: "");
printf("%s: %s tag not supported!\n", __FUNCTION__,
dwarf_tag_name(self->tag));
break;
}
}
int cu__for_each_class(struct cu *self,
int (*iterator)(struct class *class, void *cookie),
void *cookie,
struct class *(*filter)(struct class *class))
int cu__for_each_tag(struct cu *self,
int (*iterator)(struct tag *tag, struct cu *cu,
void *cookie),
void *cookie,
struct tag *(*filter)(struct tag *tag, struct cu *cu))
{
struct class *pos;
struct tag *pos;
list_for_each_entry(pos, &self->classes, tag.node) {
struct class *class = pos;
list_for_each_entry(pos, &self->classes, node) {
struct tag *tag = pos;
if (filter != NULL) {
class = filter(pos);
if (class == NULL)
tag = filter(pos, self);
if (tag == NULL)
continue;
}
if (iterator(class, cookie))
if (iterator(tag, self, cookie))
return 1;
}
return 0;
@ -1731,7 +1713,8 @@ static void cu__create_new_class(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
oom("class__new");
if (dwarf_haschildren(die) != 0 && dwarf_child(die, &child) == 0)
cu__process_class(dwarf, &child, class, cu);
cu__add_class(cu, class);
class->cu = cu;
cu__add_tag(cu, &class->tag);
}
static void cu__create_new_array(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
@ -1742,11 +1725,10 @@ static void cu__create_new_array(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
/* "64 dimensions will be enough for everybody." acme, 2006 */
const uint8_t max_dimensions = 64;
uint32_t nr_entries[max_dimensions];
const size_t size = attr_numeric(die, DW_AT_byte_size);
struct class *class = class__new(DW_TAG_array_type, cu_offset, type,
NULL, size, decl_file, decl_line, 0);
if (class == NULL)
oom("class__new");
struct array_type *array = array_type__new(cu_offset, type,
decl_file, decl_line);
if (array == NULL)
oom("array_type__new");
if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0) {
fprintf(stderr, "%s: DW_TAG_array_type with no children!\n",
@ -1755,13 +1737,13 @@ static void cu__create_new_array(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
}
die = &child;
class->array_dimensions = 0;
array->dimensions = 0;
do {
const uint16_t tag = dwarf_tag(die);
if (tag == DW_TAG_subrange_type) {
nr_entries[class->array_dimensions++] = attr_upper_bound(die);
if (class->array_dimensions == max_dimensions) {
nr_entries[array->dimensions++] = attr_upper_bound(die);
if (array->dimensions == max_dimensions) {
fprintf(stderr, "%s: only %u dimensions are "
"supported!\n",
__FUNCTION__, max_dimensions);
@ -1772,13 +1754,12 @@ static void cu__create_new_array(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
__FUNCTION__, dwarf_tag_name(tag));
} while (dwarf_siblingof(die, die) == 0);
class->array_nr_entries = memdup(nr_entries,
(class->array_dimensions *
sizeof(uint32_t)));
if (class->array_nr_entries == NULL)
array->nr_entries = memdup(nr_entries,
array->dimensions * sizeof(uint32_t));
if (array->nr_entries == NULL)
oom("memdup(array.nr_entries)");
cu__add_class(cu, class);
cu__add_tag(cu, &array->tag);
}
static void cu__process_class(Dwarf *dwarf, Dwarf_Die *die, struct class *class,
@ -2023,7 +2004,8 @@ static void cu__create_new_enumeration(Dwarf *dwarf, Dwarf_Die *die, struct cu *
enumeration__add(enumeration, enumerator);
} while (dwarf_siblingof(die, die) == 0);
cu__add_class(cu, enumeration);
enumeration->cu = cu;
cu__add_tag(cu, &enumeration->tag);
}
static void cu__process_die(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu)
@ -2211,9 +2193,10 @@ struct cus *cus__new(struct list_head *definitions,
return self;
}
static int cus__emit_typedef_definitions(struct cus *self, struct class *class)
static int cus__emit_typedef_definitions(struct cus *self, struct tag *tdef)
{
struct class *type, *ptr_type;
struct class *class = tag__class(tdef);
struct tag *type, *ptr_type;
int is_pointer = 0;
char bf[512];
@ -2230,35 +2213,39 @@ static int cus__emit_typedef_definitions(struct cus *self, struct class *class)
class->visited = 1;
return 0;
}
type = cu__find_class_by_id(class->cu, class->tag.type);
type = cu__find_tag_by_id(class->cu, class->tag.type);
if (type->tag.tag == DW_TAG_typedef)
if (type->tag == DW_TAG_typedef)
cus__emit_typedef_definitions(self, type);
switch (type->tag.tag) {
switch (type->tag) {
case DW_TAG_pointer_type:
ptr_type = cu__find_class_by_id(type->cu, type->tag.type);
if (ptr_type->tag.tag != DW_TAG_subroutine_type)
ptr_type = cu__find_tag_by_id(class->cu, type->type);
if (ptr_type->tag != DW_TAG_subroutine_type)
break;
type = ptr_type;
is_pointer = 1;
/* Fall thru */
case DW_TAG_subroutine_type:
class__subroutine_mask(type, bf, sizeof(bf), is_pointer);
tag__subroutine_mask(type, class->cu, bf, sizeof(bf),
is_pointer);
fputs("typedef ", stdout);
printf(bf, class->name);
puts(";");
goto out;
case DW_TAG_structure_type:
if (type->name == NULL)
cus__emit_struct_definitions(self, type,
case DW_TAG_structure_type: {
struct class *ctype = tag__class(type);
if (ctype->name == NULL)
cus__emit_struct_definitions(self, ctype,
"typedef", class->name);
else
printf("typedef struct %s %s;\n",
type->name, class->name);
ctype->name, class->name);
}
goto out;
}
printf("typedef %s %s;\n", class__name(type, bf, sizeof(bf)),
printf("typedef %s %s;\n", tag__name(type, class->cu, bf, sizeof(bf)),
class->name);
out:
cus__add_definition(self, class);
@ -2313,36 +2300,39 @@ int cus__emit_fwd_decl(struct cus *self, struct class *class)
static int cus__emit_tag_definitions(struct cus *self, struct cu *cu,
struct tag *tag)
{
struct class *type = cu__find_class_by_id(cu, tag->type);
struct tag *type = cu__find_tag_by_id(cu, tag->type);
struct class *ctype;
int pointer = 0;
if (type == NULL)
return 0;
next_indirection:
if (type->tag.tag == DW_TAG_pointer_type ||
type->tag.tag == DW_TAG_array_type ||
type->tag.tag == DW_TAG_const_type ||
type->tag.tag == DW_TAG_volatile_type) {
if (type->tag == DW_TAG_pointer_type ||
type->tag == DW_TAG_array_type ||
type->tag == DW_TAG_const_type ||
type->tag == DW_TAG_volatile_type) {
pointer = 1;
type = cu__find_class_by_id(cu, type->tag.type);
type = cu__find_tag_by_id(cu, type->type);
if (type == NULL)
return 0;
goto next_indirection;
}
switch (type->tag.tag) {
ctype = tag__class(type);
switch (type->tag) {
case DW_TAG_typedef:
return cus__emit_typedef_definitions(self, type);
case DW_TAG_enumeration_type:
if (type->name != NULL)
return cus__emit_enumeration_definitions(self, type);
if (tag__class(type)->name != NULL)
return cus__emit_enumeration_definitions(self, ctype);
break;
case DW_TAG_structure_type:
if (pointer)
return cus__emit_fwd_decl(self, type);
return cus__emit_struct_definitions(self, type, NULL, NULL);
return cus__emit_fwd_decl(self, ctype);
return cus__emit_struct_definitions(self, ctype, NULL, NULL);
case DW_TAG_subroutine_type:
return cus__emit_tag_definitions(self, cu, &type->tag);
return cus__emit_tag_definitions(self, cu, type);
}
return 0;
@ -2390,7 +2380,8 @@ int cus__emit_struct_definitions(struct cus *self, struct class *class,
putchar('\n');
class__find_holes(class);
class__print(class, prefix, suffix);
tag__print(&class->tag, class->cu, prefix, suffix);
class->visited = 1;
putchar('\n');
return 1;
}

View File

@ -49,6 +49,7 @@ struct tag {
uint16_t tag;
uint16_t decl_line;
const char *decl_file;
uint32_t refcnt;
};
struct class {
@ -66,13 +67,27 @@ struct class {
uint8_t declaration:1;
uint8_t visited:1;
uint8_t fwd_decl_emitted:1;
uint8_t array_dimensions:5;
uint32_t refcnt;
uint32_t *array_nr_entries;
int32_t diff;
struct class *class_to_diff;
};
struct class *tag__class(const struct tag *self)
{
return (struct class *)self;
}
struct array_type {
struct tag tag;
const char *name;
uint32_t *nr_entries;
uint8_t dimensions;
};
struct array_type *tag__array_type(const struct tag *self)
{
return (struct array_type *)self;
}
struct class_member {
struct tag tag;
char *name;
@ -113,7 +128,6 @@ struct function {
uint8_t unspecified_parameters:1;
/* fields used by tools */
struct list_head tool_node;
uint32_t refcnt;
int32_t diff;
struct class *class_to_diff;
};
@ -155,8 +169,8 @@ struct enumerator {
#define DEFAULT_CACHELINE_SIZE 32
extern void class__find_holes(struct class *self);
extern void class__print(const struct class *self,
const char *prefix, const char *suffix);
extern void tag__print(const struct tag *self, const struct cu *cu,
const char *prefix, const char *suffix);
extern void function__print(const struct function *self, const int show_stats,
const int show_variables,
const int show_inline_expansions);
@ -177,20 +191,22 @@ extern int cus__emit_struct_definitions(struct cus *self, struct class *class,
const char *suffix);
extern int cus__emit_fwd_decl(struct cus *self, struct class *class);
extern struct class *cu__find_class_by_id(const struct cu *cu,
const Dwarf_Off type);
extern struct tag *cu__find_tag_by_id(const struct cu *self,
const Dwarf_Off id);
extern struct class *cu__find_class_by_name(const struct cu *cu,
const char *name);
extern int class__is_struct(const struct class *self,
struct class **typedef_alias);
extern int tag__is_struct(const struct tag *self, struct tag **typedef_alias,
const struct cu *cu);
extern struct class *cus__find_class_by_name(const struct cus *self,
const char *name);
extern void cu__account_inline_expansions(struct cu *self);
extern int cu__for_each_class(struct cu *self,
int (*iterator)(struct class *class,
void *cookie),
void *cookie,
struct class *(*filter)(struct class *class));
extern int cu__for_each_tag(struct cu *self,
int (*iterator)(struct tag *tag,
struct cu *cu,
void *cookie),
void *cookie,
struct tag *(*filter)(struct tag *tag,
struct cu *cu));
extern int cu__for_each_function(struct cu *cu,
int (*iterator)(struct function *func,
void *cookie),
@ -231,14 +247,15 @@ static inline int function__inlined(const struct function *self)
}
extern int function__has_parameter_of_type(const struct function *self,
const struct class *target);
const struct tag *target);
extern const char *class__name(const struct class *self, char *bf, size_t len);
extern const char *tag__name(const struct tag *self, const struct cu *cu,
char *bf, size_t len);
extern struct class_member *class__find_member_by_name(const struct class *self,
const char *name);
extern size_t class_member__names(const struct class *type,
extern size_t class_member__names(const struct tag *type,
const struct class_member *self,
char *class_name, size_t class_name_size,
char *member_name, size_t member_name_size);
@ -250,8 +267,6 @@ extern const char *variable__type_name(const struct variable *self,
extern const char *dwarf_tag_name(const uint32_t tag);
extern int tag__fwd_decl(const struct cu *cu, const struct tag *tag);
extern size_t parameter__names(const struct parameter *self,
char *class_name, size_t class_name_size,
char *parameter_name,

View File

@ -204,10 +204,10 @@ out:
structure->class_to_diff = new_structure;
}
static int diff_class_iterator(struct class *class, void *new_cu)
static int diff_class_iterator(struct tag *tag, struct cu *cu, void *new_cu)
{
if (class->tag.tag == DW_TAG_structure_type)
diff_struct(new_cu, class);
if (tag->tag == DW_TAG_structure_type)
diff_struct(new_cu, tag__class(tag));
return 0;
}
@ -240,11 +240,16 @@ static int find_new_functions_iterator(struct function *function, void *old_cu)
return 0;
}
static int find_new_classes_iterator(struct class *class, void *old_cu)
static int find_new_classes_iterator(struct tag *tag, struct cu *cu, void *old_cu)
{
struct class *class;
size_t len;
if (class->tag.tag != DW_TAG_structure_type || class->name == NULL)
if (tag->tag != DW_TAG_structure_type)
return 0;
class = tag__class(tag);
if (class->name == NULL)
return 0;
if (class->size == 0)
@ -268,8 +273,8 @@ static int cu_find_new_classes_iterator(struct cu *new_cu, void *old_cus)
struct cu *old_cu = cus__find_cu_by_name(old_cus, new_cu->name);
if (old_cu != NULL) {
cu__for_each_class(new_cu, find_new_classes_iterator,
old_cu, NULL);
cu__for_each_tag(new_cu, find_new_classes_iterator,
old_cu, NULL);
cu__for_each_function(new_cu, find_new_functions_iterator,
old_cu, NULL);
}
@ -282,7 +287,7 @@ static int cu_diff_iterator(struct cu *cu, void *new_cus)
struct cu *new_cu = cus__find_cu_by_name(new_cus, cu->name);
if (new_cu != NULL) {
cu__for_each_class(cu, diff_class_iterator, new_cu, NULL);
cu__for_each_tag(cu, diff_class_iterator, new_cu, NULL);
cu__for_each_function(cu, diff_function_iterator, new_cu, NULL);
}
@ -406,9 +411,16 @@ static int show_function_diffs_iterator(struct function *function, void *new_cu)
return 0;
}
static int show_structure_diffs_iterator(struct class *class, void *new_cu)
static int show_structure_diffs_iterator(struct tag *tag, struct cu *cu,
void *new_cu)
{
if (class->diff != 0 && class->tag.tag == DW_TAG_structure_type)
struct class *class;
if (tag->tag != DW_TAG_structure_type)
return 0;
class = tag__class(tag);
if (class->diff != 0)
show_diffs_structure(class);
return 0;
}
@ -431,14 +443,14 @@ static int cu_show_diffs_iterator(struct cu *cu, void *cookie)
printf("%s:\n", cu->name);
if (show_terse_type_changes) {
cu__for_each_class(cu, show_structure_diffs_iterator,
NULL, NULL);
cu__for_each_tag(cu, show_structure_diffs_iterator,
NULL, NULL);
return 0;
}
if (cu->nr_structures_changed != 0 && show_struct_diffs) {
cu__for_each_class(cu, show_structure_diffs_iterator,
NULL, NULL);
cu__for_each_tag(cu, show_structure_diffs_iterator,
NULL, NULL);
printf(" %u struct%s changed\n", cu->nr_structures_changed,
cu->nr_structures_changed > 1 ? "s" : "");
}

View File

@ -54,15 +54,15 @@ static int cu_find_methods_iterator(struct cu *cu, void *cookie)
}
static int function__emit_kprobes(const struct function *self,
const struct class *target)
const struct tag *target)
{
char bf[128];
size_t bodyl = 2048, printed;
char body[bodyl], *bodyp = body;
char class_name[128], parm_name[256];
struct parameter *pos;
struct class *type = cu__find_class_by_id(self->cu, self->tag.type);
const char *stype = class__name(type, bf, sizeof(bf));
struct tag *type = cu__find_tag_by_id(self->cu, self->tag.type);
const char *stype = tag__name(type, self->cu, bf, sizeof(bf));
int first = 1;
body[0] = '\0';
@ -70,7 +70,7 @@ static int function__emit_kprobes(const struct function *self,
printf("static %s jprobe_entry__%s(", stype, self->name);
list_for_each_entry(pos, &self->parameters, tag.node) {
type = cu__find_class_by_id(self->cu, pos->tag.type);
type = cu__find_tag_by_id(self->cu, pos->tag.type);
parameter__names(pos, class_name, sizeof(class_name),
parm_name, sizeof(parm_name));
@ -81,11 +81,11 @@ static int function__emit_kprobes(const struct function *self,
printf("%s %s", class_name, parm_name);
if (type->tag.tag != DW_TAG_pointer_type)
if (type->tag != DW_TAG_pointer_type)
continue;
type = cu__find_class_by_id(self->cu, type->tag.type);
if (type == NULL || type->tag.id != target->tag.id)
type = cu__find_tag_by_id(self->cu, type->type);
if (type == NULL || type->id != target->id)
continue;
printed = snprintf(bodyp, bodyl,
@ -110,7 +110,7 @@ static int cu_emit_kprobes_iterator(struct cu *cu, void *cookie)
list_for_each_entry(pos, &cu->tool_list, tool_node) {
cus__emit_function_definitions(cus, pos);
function__emit_kprobes(pos, target);
function__emit_kprobes(pos, &target->tag);
}
return 0;

View File

@ -20,15 +20,15 @@ static void print_malloc_stats(void)
fprintf(stderr, "size: %u\n", m.uordblks);
}
static int class__tag_name(struct class *self, void *cookie)
static int class__tag_name(struct tag *self, struct cu *cu, void *cookie)
{
puts(dwarf_tag_name(self->tag.tag));
puts(dwarf_tag_name(self->tag));
return 0;
}
static int cu__dump_class_tag_names(struct cu *self, void *cookie)
{
cu__for_each_class(self, class__tag_name, NULL, NULL);
cu__for_each_tag(self, class__tag_name, NULL, NULL);
return 0;
}

View File

@ -90,7 +90,7 @@ static void class_name_len_formatter(const struct structure *self)
static void class_formatter(const struct structure *self)
{
class__print(self->class, NULL, NULL);
tag__print(&self->class->tag, self->class->cu, NULL, NULL);
printf(" /* definitions: %u */\n", self->nr_files);
putchar('\n');
}
@ -177,23 +177,26 @@ static void class__chkdupdef(const struct class *self, struct class *dup)
putchar('\n');
}
static struct class *class__to_struct(struct class *class)
static struct tag *tag__to_struct(struct tag *tag, const struct cu *cu)
{
struct class *typedef_alias;
struct tag *typedef_alias;
if (!class__is_struct(class, &typedef_alias))
if (!tag__is_struct(tag, &typedef_alias, cu))
return NULL;
return typedef_alias ?: class;
return typedef_alias ?: tag;
}
static struct class *class__filter(struct class *class)
static struct tag *tag__filter(struct tag *tag, struct cu *cu)
{
struct structure *str;
struct class *class;
class = class__to_struct(class);
if (class == NULL) /* Not a structure */
tag = tag__to_struct(tag, cu);
if (tag == NULL) /* Not a structure */
return NULL;
class = tag__class(tag);
if (class->name == NULL)
return NULL;
@ -227,19 +230,18 @@ static struct class *class__filter(struct class *class)
if (show_packable && !class__packable(class))
return NULL;
return class;
return tag;
}
static int unique_iterator(struct class *class, void *cookie)
static int unique_iterator(struct tag *tag, struct cu *cu, void *cookie)
{
structures__add(class);
structures__add(tag__class(tag));
return 0;
}
static int cu_unique_iterator(struct cu *cu, void *cookie)
{
return cu__for_each_class(cu, unique_iterator, cookie,
class__filter);
return cu__for_each_tag(cu, unique_iterator, cookie, tag__filter);
}
static struct option long_options[] = {
@ -343,7 +345,7 @@ int main(int argc, char *argv[])
printf("struct %s not found!\n", class_name);
return EXIT_FAILURE;
}
class__print(s->class, NULL, NULL);
tag__print(&s->class->tag, s->class->cu, NULL, NULL);
} else
print_classes(formatter);

View File

@ -29,7 +29,7 @@ static void usage(void)
" -h, --help usage options\n");
}
static void refcnt_class(struct class *class);
static void refcnt_tag(struct tag *tag);
static void refcnt_member(struct class_member *member)
{
@ -37,52 +37,53 @@ static void refcnt_member(struct class_member *member)
return;
member->visited = 1;
if (member->tag.type != 0) { /* if not void */
struct class *type = cu__find_class_by_id(member->class->cu,
member->tag.type);
struct tag *type = cu__find_tag_by_id(member->class->cu,
member->tag.type);
if (type != NULL)
refcnt_class(type);
refcnt_tag(type);
}
}
static void refcnt_parameter(const struct parameter *parameter)
{
if (parameter->tag.type != 0) { /* if not void */
struct class *type = cu__find_class_by_id(parameter->function->cu,
parameter->tag.type);
struct tag *type = cu__find_tag_by_id(parameter->function->cu,
parameter->tag.type);
if (type != NULL)
refcnt_class(type);
refcnt_tag(type);
}
}
static void refcnt_variable(const struct variable *variable)
{
if (variable->tag.type != 0) { /* if not void */
struct class *type = cu__find_class_by_id(variable->cu,
variable->tag.type);
struct tag *type = cu__find_tag_by_id(variable->cu,
variable->tag.type);
if (type != NULL)
refcnt_class(type);
refcnt_tag(type);
}
}
static void refcnt_inline_expansion(const struct inline_expansion *exp)
{
if (exp->tag.type != 0) { /* if not void */
struct class *type = cu__find_class_by_id(exp->function->cu,
exp->tag.type);
struct tag *type = cu__find_tag_by_id(exp->function->cu,
exp->tag.type);
if (type != NULL)
refcnt_class(type);
refcnt_tag(type);
}
}
static void refcnt_class(struct class *class)
static void refcnt_tag(struct tag *tag)
{
struct class_member *member;
class->refcnt++;
tag->refcnt++;
list_for_each_entry(member, &class->members, tag.node)
refcnt_member(member);
if (tag->tag == DW_TAG_structure_type ||
tag->tag == DW_TAG_union_type)
list_for_each_entry(member, &tag__class(tag)->members, tag.node)
refcnt_member(member);
}
static void refcnt_function(struct function *function)
@ -91,13 +92,13 @@ static void refcnt_function(struct function *function)
struct inline_expansion *exp;
struct variable *variable;
function->refcnt++;
function->tag.refcnt++;
if (function->tag.type != 0) /* if not void */ {
struct class *type = cu__find_class_by_id(function->cu,
function->tag.type);
struct tag *type = cu__find_tag_by_id(function->cu,
function->tag.type);
if (type != NULL)
refcnt_class(type);
refcnt_tag(type);
}
list_for_each_entry(parameter, &function->parameters, tag.node)
@ -116,31 +117,31 @@ static int refcnt_function_iterator(struct function *function, void *cookie)
return 0;
}
static int refcnt_class_iterator(struct class *class, void *cookie)
static int refcnt_tag_iterator(struct tag *tag, struct cu *cu, void *cookie)
{
if (class->tag.tag == DW_TAG_structure_type)
class__find_holes(class);
if (tag->tag == DW_TAG_structure_type)
class__find_holes(tag__class(tag));
return 0;
}
static int cu_refcnt_iterator(struct cu *cu, void *cookie)
{
cu__for_each_class(cu, refcnt_class_iterator, cookie, NULL);
cu__for_each_tag(cu, refcnt_tag_iterator, cookie, NULL);
cu__for_each_function(cu, refcnt_function_iterator, cookie, NULL);
return 0;
}
static int lost_iterator(struct class *class, void *cookie)
static int lost_iterator(struct tag *tag, struct cu *cu, void *cookie)
{
if (class->refcnt == 0 && class->tag.decl_file != NULL)
class__print(class, NULL, NULL);
if (tag->refcnt == 0 && tag->decl_file != NULL)
tag__print(tag, cu, NULL, NULL);
return 0;
}
static int cu_lost_iterator(struct cu *cu, void *cookie)
{
return cu__for_each_class(cu, lost_iterator, cookie, NULL);
return cu__for_each_tag(cu, lost_iterator, cookie, NULL);
}
int main(int argc, char *argv[])