diff --git a/classes.c b/classes.c index 8a0a1fa..8c58037 100644 --- a/classes.c +++ b/classes.c @@ -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 = ""; 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 = ""; - 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; } diff --git a/classes.h b/classes.h index 3469b82..b7b3481 100644 --- a/classes.h +++ b/classes.h @@ -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, diff --git a/codiff.c b/codiff.c index e2674da..e110c8f 100644 --- a/codiff.c +++ b/codiff.c @@ -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" : ""); } diff --git a/ctracer.c b/ctracer.c index 06979e9..a9c2025 100644 --- a/ctracer.c +++ b/ctracer.c @@ -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; diff --git a/dtagnames.c b/dtagnames.c index b207e74..41c8be7 100644 --- a/dtagnames.c +++ b/dtagnames.c @@ -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; } diff --git a/pahole.c b/pahole.c index 27ff81a..93da4e3 100644 --- a/pahole.c +++ b/pahole.c @@ -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); diff --git a/prefcnt.c b/prefcnt.c index 89e15b3..d621a37 100644 --- a/prefcnt.c +++ b/prefcnt.c @@ -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[])