diff --git a/CMakeLists.txt b/CMakeLists.txt index 88e5f7a..cf57ea4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -31,7 +31,7 @@ find_package(ZLIB REQUIRED) _set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}${CMAKE_INSTALL_PREFIX}/${__LIB}" "libdir") -set(dwarves_LIB_SRCS dwarves.c ctf_loader.c libctf.c dwarf_loader.c) +set(dwarves_LIB_SRCS dwarves.c strings ctf_loader.c libctf.c dwarf_loader.c) add_library(dwarves SHARED ${dwarves_LIB_SRCS}) set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1) target_link_libraries(dwarves ${DWARF_LIBRARIES} ${ZLIB_LIBRARIES}) diff --git a/codiff.c b/codiff.c index 60b8aab..1ddbee3 100644 --- a/codiff.c +++ b/codiff.c @@ -165,7 +165,7 @@ static int check_print_change(const struct class_member *old, printf(" %s\n" " from: %-21s /* %5u(%u) %5zd(%d) */\n" " to: %-21s /* %5u(%u) %5zd(%u) */\n", - old->name, + class_member__name(old), old_type_name, old->offset, old->bit_offset, old_size, old->bit_size, new_type_name, new->offset, new->bit_offset, @@ -185,7 +185,8 @@ static int check_print_members_changes(const struct class *structure, type__for_each_member(&structure->type, member) { struct class_member *twin = - class__find_member_by_name(new_structure, member->name); + class__find_member_by_name(new_structure, + class_member__name(member)); if (twin != NULL) if (check_print_change(member, cu, twin, new_cu, print)) changes = 1; @@ -351,14 +352,16 @@ static void show_diffs_function(struct function *function, const struct cu *cu, if (di->tag == NULL) puts(cookie ? " (added)" : " (removed)"); else { - const struct function *twin = tag__function(di->tag); + struct function *twin = tag__function(di->tag); if (twin->inlined) puts(cookie ? " (uninlined)" : " (inlined)"); - else if (strcmp(function->name, twin->name) != 0) + else if (strcmp(function__name(function, cu), + function__name(twin, di->cu)) != 0) printf("%s: BRAIN FART ALERT: comparing %s to %s, " "should be the same name\n", __FUNCTION__, - function->name, twin->name); + function__name(function, cu), + function__name(twin, di->cu)); else { char proto[1024], twin_proto[1024]; @@ -398,7 +401,8 @@ static void show_changed_member(char change, const struct class_member *member, tag__assert_search_result(type); printf(" %c%-26s %-21s /* %5u %5zd */\n", - change, tag__name(type, cu, bf, sizeof(bf)), member->name, + change, tag__name(type, cu, bf, sizeof(bf)), + class_member__name(member), member->offset, tag__size(type, cu)); } @@ -412,7 +416,8 @@ static void show_nr_members_changes(const struct class *structure, /* Find the removed ones */ type__for_each_member(&structure->type, member) { struct class_member *twin = - class__find_member_by_name(new_structure, member->name); + class__find_member_by_name(new_structure, + class_member__name(member)); if (twin == NULL) show_changed_member('-', member, cu); } @@ -420,7 +425,8 @@ static void show_nr_members_changes(const struct class *structure, /* Find the new ones */ type__for_each_member(&new_structure->type, member) { struct class_member *twin = - class__find_member_by_name(structure, member->name); + class__find_member_by_name(structure, + class_member__name(member)); if (twin == NULL) show_changed_member('+', member, new_cu); } @@ -673,6 +679,11 @@ int main(int argc, char *argv[]) char *dwfl_argv[4]; struct stat st; + if (dwarves__init(0)) { + fputs("codiff: insufficient memory\n", stderr); + return EXIT_FAILURE; + } + argp_parse(&codiff__argp, argc, argv, 0, &remaining, NULL); if (remaining < argc) { @@ -692,8 +703,6 @@ failure: show_terse_type_changes == 0) show_function_diffs = show_struct_diffs = 1; - dwarves__init(0); - structs_printed = strlist__new(false); old_cus = cus__new(); new_cus = cus__new(); diff --git a/ctf_loader.c b/ctf_loader.c index 946a44d..b504c5f 100644 --- a/ctf_loader.c +++ b/ctf_loader.c @@ -24,6 +24,12 @@ #include "dutil.h" #include "dwarves.h" +/* + * FIXME: We should just get the table from the CTF ELF section + * and use it directly + */ +extern struct strings *strings; + static void *zalloc(const size_t size) { void *s = malloc(size); @@ -318,7 +324,7 @@ static struct base_type *base_type__new(const char *name, size_t size) struct base_type *self = zalloc(sizeof(*self)); if (self != NULL) { - self->name = strings__add(name); + self->name = strings__add(strings, name); self->bit_size = size; } return self; @@ -332,7 +338,7 @@ static void type__init(struct type *self, uint16_t tag, unsigned int id, self->size = size; self->namespace.tag.id = id; self->namespace.tag.tag = tag; - self->namespace.name = strings__add(name[0] == '(' ? NULL : name); + self->namespace.name = strings__add(strings, name[0] == '(' ? NULL : name); } static struct type *type__new(uint16_t tag, unsigned int id, @@ -456,7 +462,7 @@ static int create_new_subroutine_type(struct ctf_state *sp, void *ptr, if (self == NULL) oom("function__new"); - self->name = strings__add(name); + self->name = strings__add(strings, name); INIT_LIST_HEAD(&self->vtable_node); INIT_LIST_HEAD(&self->tool_node); INIT_LIST_HEAD(&self->proto.parms); @@ -497,7 +503,7 @@ static unsigned long create_full_members(struct ctf_state *sp, void *ptr, member->tag.tag = DW_TAG_member; member->tag.type = ctf__get16(sp->ctf, &mp[i].ctf_member_type); - member->name = strings__add(ctf_string(ctf__get32(sp->ctf, &mp[i].ctf_member_name), sp)); + member->name = strings__add(strings, ctf_string(ctf__get32(sp->ctf, &mp[i].ctf_member_name), sp)); bit_offset = (ctf__get32(sp->ctf, &mp[i].ctf_member_offset_high) << 16) | ctf__get32(sp->ctf, &mp[i].ctf_member_offset_low); member->offset = bit_offset / 8; @@ -524,7 +530,7 @@ static unsigned long create_short_members(struct ctf_state *sp, void *ptr, member->tag.tag = DW_TAG_member; member->tag.type = ctf__get16(sp->ctf, &mp[i].ctf_member_type); - member->name = strings__add(ctf_string(ctf__get32(sp->ctf, &mp[i].ctf_member_name), sp)); + member->name = strings__add(strings, ctf_string(ctf__get32(sp->ctf, &mp[i].ctf_member_name), sp)); bit_offset = ctf__get16(sp->ctf, &mp[i].ctf_member_offset); member->offset = bit_offset / 8; member->bit_offset = bit_offset % 8; @@ -580,7 +586,7 @@ static struct enumerator *enumerator__new(const char *name, struct enumerator *self = zalloc(sizeof(*self)); if (self != NULL) { - self->name = strings__add(name); + self->name = strings__add(strings, name); self->value = value; self->tag.tag = DW_TAG_enumerator; } diff --git a/ctracer.c b/ctracer.c index 3d821f7..9ff29c5 100644 --- a/ctracer.c +++ b/ctracer.c @@ -305,7 +305,8 @@ static size_t class__find_biggest_member_name(const struct class *self) size_t biggest_name_len = 0; type__for_each_data_member(&self->type, pos) { - const size_t len = pos->name ? strlen(pos->name) : 0; + const size_t len = pos->name ? + strlen(class_member__name(pos)) : 0; if (len > biggest_name_len) biggest_name_len = len; @@ -329,7 +330,7 @@ static void class__emit_class_state_collector(struct class *self, class__name(self, cu), class__name(clone, cu)); type__for_each_data_member(&clone->type, pos) fprintf(fp_collector, "\tmini_obj->%-*s = obj->%s;\n", - len, pos->name, pos->name); + len, class_member__name(pos), class_member__name(pos)); fputs("}\n\n", fp_collector); } @@ -468,10 +469,11 @@ static int class__emit_ostra_converter(struct tag *tag_self, plen -= n; p += n; } fprintf(fp_converter, "%%u"); - n = snprintf(p, plen, "obj.%s", pos->name); + n = snprintf(p, plen, "obj.%s", class_member__name(pos)); plen -= n; p += n; emit_struct_member_table_entry(fp_fields, field++, - pos->name, 1, "entry,exit"); + class_member__name(pos), + 1, "entry,exit"); } fprintf(fp_converter, "\\n\",\n\t\t\t %s);\n" @@ -717,12 +719,14 @@ static int function__emit_probes(struct function *self, const struct cu *cu, continue; if (member != NULL) - fprintf(fp_methods, "\tif ($%s)\n\t", pos->name); + fprintf(fp_methods, "\tif ($%s)\n\t", + parameter__name(pos, cu)); fprintf(fp_methods, "\tctracer__method_hook(%d, %#llx, $%s%s%s, %zd);\n", probe_type, - (unsigned long long)self->proto.tag.id, pos->name, + (unsigned long long)self->proto.tag.id, + parameter__name(pos, cu), member ? "->" : "", member ?: "", class__size(mini_class)); break; @@ -788,8 +792,10 @@ static int cu_emit_pointer_probes_iterator(struct cu *cu, void *cookie) continue; pos_tag->priv = (void *)1; /* Mark as visited, for the table iterator */ - function__emit_probes(pos_tag, cu, pointer, 0, pos_member->name); /* entry */ - function__emit_probes(pos_tag, cu, pointer, 1, pos_member->name); /* exit */ + function__emit_probes(pos_tag, cu, pointer, 0, + class_member__name(pos_member)); /* entry */ + function__emit_probes(pos_tag, cu, pointer, 1, + class_member__name(pos_member)); /* exit */ } return 0; @@ -888,6 +894,11 @@ int main(int argc, char *argv[]) struct structure *pos; FILE *fp_functions; + if (dwarves__init(0)) { + fputs("ctracer: insufficient memory\n", stderr); + return EXIT_FAILURE; + } + argp_parse(&ctracer__argp, argc, argv, 0, &remaining, NULL); if (remaining < argc) { @@ -903,12 +914,6 @@ failure: return EXIT_FAILURE; } - /* - * Initialize libdwarves, for now just to get the machine L1 cacheline - * size, in the future may do more stuff. - */ - dwarves__init(0); - type_emissions__init(&emissions); /* diff --git a/dtagnames.c b/dtagnames.c index bcb5de9..fcffb14 100644 --- a/dtagnames.c +++ b/dtagnames.c @@ -44,7 +44,7 @@ int main(int argc, char *argv[]) int err; struct cus *cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(0) || cus == NULL) { fputs("dtagnames: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -53,8 +53,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(0); - cus__dump_class_tag_names(cus); print_malloc_stats(); return EXIT_SUCCESS; diff --git a/dwarf_loader.c b/dwarf_loader.c index c378a59..a202f1a 100644 --- a/dwarf_loader.c +++ b/dwarf_loader.c @@ -25,6 +25,9 @@ #include "list.h" #include "dwarves.h" #include "dutil.h" +#include "strings.h" + +extern struct strings *strings; static void *zalloc(const size_t size) { @@ -186,7 +189,7 @@ static void tag__init(struct tag *self, Dwarf_Die *die) else self->type = attr_type(die, DW_AT_type); - self->decl_file = strings__add(dwarf_decl_file(die)); + self->decl_file = strings__add(strings, dwarf_decl_file(die)); dwarf_decl_line(die, &decl_line); self->decl_line = decl_line; self->recursivity_level = 0; @@ -221,7 +224,7 @@ static struct base_type *base_type__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->bit_size = attr_numeric(die, DW_AT_byte_size) * 8; } @@ -242,7 +245,7 @@ static void namespace__init(struct namespace *self, Dwarf_Die *die) { tag__init(&self->tag, die); INIT_LIST_HEAD(&self->tags); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->nr_tags = 0; } @@ -285,7 +288,7 @@ static struct enumerator *enumerator__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->value = attr_numeric(die, DW_AT_const_value); } @@ -320,7 +323,7 @@ static struct variable *variable__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->abstract_origin = attr_type(die, DW_AT_abstract_origin); /* variable is visible outside of its enclosing cu */ self->external = dwarf_hasattr(die, DW_AT_external); @@ -345,7 +348,7 @@ static struct class_member *class_member__new(Dwarf_Die *die) self->bit_offset = attr_numeric(die, DW_AT_bit_offset); self->accessibility = attr_numeric(die, DW_AT_accessibility); self->virtuality = attr_numeric(die, DW_AT_virtuality); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); } return self; @@ -357,7 +360,7 @@ static struct parameter *parameter__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, + self->name = strings__add(strings, attr_string(die, DW_AT_name)); self->abstract_origin = attr_type(die, DW_AT_abstract_origin); } @@ -372,7 +375,7 @@ static struct inline_expansion *inline_expansion__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); self->tag.decl_file = - strings__add(attr_string(die, DW_AT_call_file)); + strings__add(strings, attr_string(die, DW_AT_call_file)); self->tag.decl_line = attr_numeric(die, DW_AT_call_line); self->tag.type = attr_type(die, DW_AT_abstract_origin); @@ -409,7 +412,7 @@ static struct label *label__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); if (dwarf_lowpc(die, &self->low_pc)) self->low_pc = 0; } @@ -484,8 +487,8 @@ static struct function *function__new(Dwarf_Die *die) if (self != NULL) { ftype__init(&self->proto, die); lexblock__init(&self->lexblock, die); - self->name = strings__add(attr_string(die, DW_AT_name)); - self->linkage_name = strings__add(attr_string(die, DW_AT_MIPS_linkage_name)); + self->name = strings__add(strings, attr_string(die, DW_AT_name)); + self->linkage_name = strings__add(strings, attr_string(die, DW_AT_MIPS_linkage_name)); self->inlined = attr_numeric(die, DW_AT_inline); self->external = dwarf_hasattr(die, DW_AT_external); self->abstract_origin = attr_type(die, DW_AT_abstract_origin); diff --git a/dwarves.c b/dwarves.c index 6b68e6a..a938498 100644 --- a/dwarves.c +++ b/dwarves.c @@ -29,6 +29,14 @@ #include "list.h" #include "dwarves.h" #include "dutil.h" +#include "strings.h" + +struct strings *strings; + +static inline const char *s(strings_t i) +{ + return strings__ptr(strings, i); +} static const char *dwarf_tag_names[] = { [DW_TAG_array_type] = "array_type", @@ -108,37 +116,6 @@ static const char tabs[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; static size_t cacheline_size; -static void *strings; - -static int strings__compare(const void *a, const void *b) -{ - return strcmp(a, b); -} - -char *strings__add(const char *str) -{ - char **s; - - if (str == NULL) - return NULL; - - s = tsearch(str, &strings, strings__compare); - if (s != NULL) { - if (*s == str) { - char *dup = strdup(str); - if (dup != NULL) - *s = dup; - else { - tdelete(str, &strings, strings__compare); - return NULL; - } - } - } else - return NULL; - - return *s; -} - void tag__delete(struct tag *self) { assert(list_empty(&self->node)); @@ -216,7 +193,7 @@ size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp) { return fprintf(fp, "/* <%llx> %s:%u */\n", (unsigned long long)self->id, - self->decl_file, self->decl_line); + s(self->decl_file), self->decl_line); } static size_t type__fprintf(struct tag *type, const struct cu *cu, @@ -264,7 +241,7 @@ void namespace__delete(struct namespace *self) const char *type__name(struct type *self, const struct cu *cu) { /* Check if the tag doesn't comes with a DW_AT_name attribute... */ - if (self->namespace.name == NULL && + if (!self->namespace.name && /* No? So it can have a DW_TAG_specification... */ self->specification != 0 && cu != NULL) { @@ -277,7 +254,7 @@ const char *type__name(struct type *self, const struct cu *cu) self->namespace.name = tag__type(tag)->namespace.name; } - return self->namespace.name; + return s(self->namespace.name); } struct class_member * @@ -434,7 +411,7 @@ static size_t imported_module__fprintf(const struct tag *self, const char *name = ""; if (tag__is_namespace(module)) - name = tag__namespace(module)->name; + name = s(tag__namespace(module)->name); return fprintf(fp, "using namespace %s", name); } @@ -454,7 +431,7 @@ size_t enumeration__fprintf(const struct tag *tag_self, const struct cu *cu, type__for_each_enumerator(self, pos) printed += fprintf(fp, "%.*s\t%s = %u,\n", indent, tabs, - pos->name, pos->value); + s(pos->name), pos->value); return printed + fprintf(fp, "%.*s}%s%s", indent, tabs, conf->suffix ? " " : "", conf->suffix ?: ""); @@ -480,7 +457,7 @@ struct cu *cu__new(const char *name, uint8_t addr_size, INIT_LIST_HEAD(&self->tags); INIT_LIST_HEAD(&self->tool_list); - self->name = strings__add(name); + self->name = strdup(name); self->addr_size = addr_size; self->nr_inline_expansions = 0; @@ -595,7 +572,7 @@ struct tag *cu__find_base_type_by_name(const struct cu *self, const char *name) if (pos->tag == DW_TAG_base_type) { const struct base_type *bt = tag__base_type(pos); - if (bt->name != NULL && strcmp(bt->name, name) == 0) + if (bt->name && strcmp(s(bt->name), name) == 0) return pos; } @@ -690,7 +667,7 @@ struct cu *cus__find_cu_by_name(const struct cus *self, const char *name) struct cu *pos; list_for_each_entry(pos, &self->cus, node) - if (strcmp(pos->name, name) == 0) + if (pos->name && strcmp(pos->name, name) == 0) return pos; return NULL; @@ -708,7 +685,7 @@ struct tag *cu__find_function_by_name(const struct cu *self, const char *name) if (pos->tag != DW_TAG_subprogram) continue; fpos = tag__function(pos); - if (fpos->name != NULL && strcmp(fpos->name, name) == 0) + if (fpos->name && strcmp(s(fpos->name), name) == 0) return pos; } @@ -886,12 +863,12 @@ const char *tag__name(const struct tag *self, const struct cu *cu, else switch (self->tag) { case DW_TAG_base_type: { const struct base_type *bt = tag__base_type(self); - const char *s = "nameless base type!"; + const char *name = "nameless base type!"; - if (bt->name != NULL) - s = bt->name; + if (bt->name) + name = s(bt->name); - strncpy(bf, s, len); + strncpy(bf, name, len); } break; case DW_TAG_subprogram: @@ -983,14 +960,14 @@ const char *variable__type_name(const struct variable *self, const char *variable__name(const struct variable *self, const struct cu *cu) { - if (self->name != NULL) - return self->name; + if (self->name) + return s(self->name); if (self->abstract_origin != 0) { struct variable *var = cu__find_variable_by_id(cu, self->abstract_origin); if (var != NULL) - return var->name; + return s(var->name); } return NULL; } @@ -1044,7 +1021,7 @@ size_t class_member__size(const struct class_member *self, const char *parameter__name(struct parameter *self, const struct cu *cu) { /* Check if the tag doesn't comes with a DW_AT_name attribute... */ - if (self->name == NULL && self->abstract_origin != 0) { + if (!self->name && self->abstract_origin != 0) { /* No? Does it have a DW_AT_abstract_origin? */ struct tag *alias = cu__find_parameter_by_id(cu, self->abstract_origin); @@ -1056,7 +1033,7 @@ const char *parameter__name(struct parameter *self, const struct cu *cu) self->name = tag__parameter(alias)->name; } - return self->name; + return s(self->name); } Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu) @@ -1238,8 +1215,8 @@ static size_t struct_member__fprintf(struct class_member *self, struct conf_fprintf sconf = *conf; uint32_t offset = self->offset; size_t printed = 0; - const char *name = self->name; - + const char *name = s(self->name); + if (!sconf.rel_offset) { sconf.base_offset += self->offset; offset = sconf.base_offset; @@ -1265,8 +1242,8 @@ static size_t struct_member__fprintf(struct class_member *self, type__name(tag__type(type), cu) == NULL) { if (!sconf.suppress_offset_comment) { /* Check if this is a anonymous union */ - const int slen = self->name != NULL ? - (int)strlen(self->name) : -1; + const int slen = self->name ? + (int)strlen(s(self->name)) : -1; printed += fprintf(fp, "%*s/* %5u %5u */", (sconf.type_spacing + sconf.name_spacing - slen - 3), @@ -1303,7 +1280,7 @@ static size_t union_member__fprintf(struct class_member *self, const struct conf_fprintf *conf, FILE *fp) { const size_t size = tag__size(type, cu); - size_t printed = type__fprintf(type, cu, self->name, conf, fp); + size_t printed = type__fprintf(type, cu, s(self->name), conf, fp); if ((tag__is_union(type) || tag__is_struct(type) || tag__is_enumeration(type)) && @@ -1311,7 +1288,7 @@ static size_t union_member__fprintf(struct class_member *self, type__name(tag__type(type), cu) == NULL) { if (!conf->suppress_offset_comment) { /* Check if this is a anonymous union */ - const int slen = self->name != NULL ? (int)strlen(self->name) : -1; + const int slen = self->name ? (int)strlen(s(self->name)) : -1; /* * Add the comment with the union size after padding the * '} member_name;' last line of the type printed in the @@ -1439,7 +1416,8 @@ struct class *class__clone(const struct class *from, self = NULL; } if (new_class_name != NULL) - self->type.namespace.name = strings__add(new_class_name); + self->type.namespace.name = strings__add(strings, + new_class_name); } return self; @@ -1460,7 +1438,7 @@ void lexblock__add_lexblock(struct lexblock *self, struct lexblock *child) const char *function__name(struct function *self, const struct cu *cu) { /* Check if the tag doesn't comes with a DW_AT_name attribute... */ - if (self->name == NULL) { + if (!self->name) { /* No? So it must have a DW_AT_abstract_origin... */ struct tag *tag = cu__find_tag_by_id(cu, self->abstract_origin); @@ -1476,7 +1454,7 @@ const char *function__name(struct function *self, const struct cu *cu) self->name = tag__function(tag)->name; } - return self->name; + return s(self->name); } const char *function__prototype(const struct function *self, @@ -1675,7 +1653,7 @@ struct class_member *type__find_member_by_name(const struct type *self, if (name != NULL) { struct class_member *pos; type__for_each_data_member(self, pos) - if (pos->name != NULL && strcmp(pos->name, name) == 0) + if (pos->name && strcmp(s(pos->name), name) == 0) return pos; } @@ -1856,7 +1834,7 @@ static size_t function__tag_fprintf(const struct tag *tag, const struct cu *cu, printed = fprintf(fp, "%.*s", indent, tabs); fputc('\n', fp); ++printed; - c = fprintf(fp, "%s:", label->name); + c = fprintf(fp, "%s:", s(label->name)); printed += c; } break; @@ -2018,7 +1996,8 @@ static size_t class__vtable_fprintf(struct class *self, list_for_each_entry(pos, &self->vtable, vtable_node) { printed += fprintf(fp, "%.*s [%d] = %s(%s), \n", conf->indent, tabs, pos->vtable_entry, - pos->name, pos->linkage_name); + s(pos->name), + s(pos->linkage_name)); } printed += fprintf(fp, "%.*s} */", conf->indent, tabs); @@ -2340,7 +2319,8 @@ size_t class__fprintf(struct class *self, const struct cu *cu, struct class_member *m = type__find_first_biggest_size_base_type_member(tself, cu); printed += fprintf(fp, "\n%.*s/* first biggest size base type member: %s %u %zd */", - cconf.indent, tabs, m->name, m->offset, + cconf.indent, tabs, + s(m->name), m->offset, class_member__size(m, cu)); } @@ -2382,7 +2362,7 @@ static size_t namespace__fprintf(const struct tag *tself, const struct cu *cu, { struct namespace *self = tag__namespace(tself); struct conf_fprintf cconf = *conf; - size_t printed = fprintf(fp, "namespace %s {\n", self->name); + size_t printed = fprintf(fp, "namespace %s {\n", s(self->name)); struct tag *pos; ++cconf.indent; @@ -2479,8 +2459,9 @@ size_t tag__fprintf(struct tag *self, const struct cu *cu, !pconf->suppress_comments) { const struct function *fself = tag__function(self); - if (fself->linkage_name != NULL) - printed += fprintf(fp, " /* linkage=%s */", fself->linkage_name); + if (fself->linkage_name) + printed += fprintf(fp, " /* linkage=%s */", + s(fself->linkage_name)); } if (pconf->expand_types) @@ -2625,8 +2606,13 @@ struct cus *cus__new(void) return self; } -void dwarves__init(size_t user_cacheline_size) +int dwarves__init(size_t user_cacheline_size) { + strings = strings__new(); + + if (strings == NULL) + return -ENOMEM; + if (user_cacheline_size == 0) { long sys_cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); @@ -2636,4 +2622,6 @@ void dwarves__init(size_t user_cacheline_size) cacheline_size = 64; /* Fall back to a sane value */ } else cacheline_size = user_cacheline_size; + + return 0; } diff --git a/dwarves.h b/dwarves.h index 300b333..6b3c419 100644 --- a/dwarves.h +++ b/dwarves.h @@ -17,6 +17,9 @@ #include "list.h" #include "hash.h" +#include "strings.h" + +extern struct strings *strings; struct argp; @@ -58,7 +61,7 @@ struct tag { struct list_head hash_node; Dwarf_Off type; Dwarf_Off id; - const char *decl_file; + strings_t decl_file; uint16_t decl_line; uint16_t tag; uint16_t refcnt; @@ -98,6 +101,11 @@ static inline int tag__is_type(const struct tag *self) tag__is_typedef(self) || tag__is_enumeration(self); } + +static inline const char *tag__decl_file(const struct tag *self) +{ + return strings__ptr(strings, self->decl_file); +} struct ptr_to_member_type { struct tag tag; @@ -112,9 +120,9 @@ static inline struct ptr_to_member_type * struct namespace { struct tag tag; - const char *name; - struct list_head tags; + strings_t name; uint16_t nr_tags; + struct list_head tags; }; static inline struct namespace *tag__namespace(const struct tag *self) @@ -278,7 +286,7 @@ static inline int class__is_struct(const struct class *self) struct base_type { struct tag tag; - const char *name; + strings_t name; size_t bit_size; }; @@ -292,6 +300,11 @@ static inline size_t base_type__size(const struct tag *self) return tag__base_type(self)->bit_size / 8; } +static inline const char *base_type__name(const struct base_type *self) +{ + return strings__ptr(strings, self->name); +} + struct array_type { struct tag tag; uint32_t *nr_entries; @@ -305,7 +318,7 @@ static inline struct array_type *tag__array_type(const struct tag *self) struct class_member { struct tag tag; - char *name; + strings_t name; uint32_t offset; uint8_t bit_offset; uint8_t bit_size; @@ -326,6 +339,12 @@ static inline struct class_member *tag__class_member(const struct tag *self) extern size_t class_member__size(const struct class_member *self, const struct cu *cu); + +static inline const char *class_member__name(const struct class_member *self) +{ + return strings__ptr(strings, self->name); +} + extern void class_member__delete(struct class_member *self); struct lexblock { @@ -371,10 +390,10 @@ static inline struct ftype *tag__ftype(const struct tag *self) struct function { struct ftype proto; struct lexblock lexblock; - const char *name; - char *linkage_name; Dwarf_Off abstract_origin; Dwarf_Off specification; + strings_t name; + strings_t linkage_name; size_t cu_total_size_inline_expansions; uint16_t cu_total_nr_inline_expansions; uint8_t inlined:2; @@ -408,7 +427,7 @@ static inline struct tag *function__tag(const struct function *self) struct parameter { struct tag tag; - char *name; + strings_t name; Dwarf_Off abstract_origin; }; @@ -430,8 +449,8 @@ enum vlocation { struct variable { struct tag tag; - char *name; Dwarf_Off abstract_origin; + strings_t name; uint8_t external:1; uint8_t declaration:1; enum vlocation location; @@ -457,13 +476,13 @@ static inline struct inline_expansion * struct label { struct tag tag; - char *name; + strings_t name; Dwarf_Addr low_pc; }; struct enumerator { struct tag tag; - const char *name; + strings_t name; uint32_t value; }; @@ -486,7 +505,7 @@ struct conf_fprintf { uint8_t show_first_biggest_size_base_type_member:1; }; -extern void dwarves__init(size_t user_cacheline_size); +int dwarves__init(size_t user_cacheline_size); 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); @@ -659,5 +678,4 @@ extern const char *variable__type_name(const struct variable *self, extern const char *dwarf_tag_name(const uint32_t tag); -char *strings__add(const char *str); #endif /* _DWARVES_H_ */ diff --git a/dwarves_reorganize.c b/dwarves_reorganize.c index 597bdd8..8d4f6e6 100644 --- a/dwarves_reorganize.c +++ b/dwarves_reorganize.c @@ -260,7 +260,7 @@ static void class__move_member(struct class *class, struct class_member *dest, LIST_HEAD(from_list); if (verbose) - fprintf(fp, " bitfield('%s' ... ", from->name); + fprintf(fp, " bitfield('%s' ... ", class_member__name(from)); list_for_each_entry_safe_from(pos, tmp, class__tags(class), tag.node) { if (pos->tag.tag != DW_TAG_member) @@ -281,10 +281,10 @@ static void class__move_member(struct class *class, struct class_member *dest, tail_from->bit_hole = orig_tail_from_bit_hole; list_splice(&from_list, &dest->tag.node); if (verbose) - fprintf(fp, "'%s')", tail_from->name); + fprintf(fp, "'%s')", class_member__name(tail_from)); } else { if (verbose) - fprintf(fp, " '%s'", from->name); + fprintf(fp, " '%s'", class_member__name(from)); /* * Remove 'from' from the list */ @@ -299,7 +299,8 @@ static void class__move_member(struct class *class, struct class_member *dest, if (verbose) fprintf(fp, " from after '%s' to after '%s' */\n", - from_prev->name, dest->name); + class_member__name(from_prev), + class_member__name(dest)); if (from_padding) { /* @@ -319,7 +320,7 @@ static void class__move_member(struct class *class, struct class_member *dest, if (verbose) fprintf(fp, "/* adding %zd bytes from %s to " "the padding */\n", - from_size, from->name); + from_size, class_member__name(from)); } } else if (from_was_last) { class->type.size -= from_size + class->padding; @@ -378,8 +379,9 @@ static void class__move_bit_member(struct class *class, const struct cu *cu, if (verbose) fprintf(fp, "/* Moving '%s:%u' from after '%s' to " "after '%s:%u' */\n", - from->name, from->bit_size, from_prev->name, - dest->name, dest->bit_size); + class_member__name(from), from->bit_size, + class_member__name(from_prev), + class_member__name(dest), dest->bit_size); /* * Remove 'from' from the list */ @@ -546,9 +548,10 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu, if (verbose) fprintf(fp, "/* Demoting bitfield ('%s' ... '%s') " "from '%s' to '%s' */\n", - bitfield_head->name, member->name, - tag__base_type(old_type_tag)->name, - tag__base_type(new_type_tag)->name); + class_member__name(bitfield_head), + class_member__name(member), + base_type__name(tag__base_type(old_type_tag)), + base_type__name(tag__base_type(new_type_tag))); class__demote_bitfield_members(class, bitfield_head, member, @@ -593,9 +596,9 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu, if (verbose) fprintf(fp, "/* Demoting bitfield ('%s') " "from '%s' to '%s' */\n", - member->name, - tag__base_type(old_type_tag)->name, - tag__base_type(new_type_tag)->name); + class_member__name(member), + base_type__name(tag__base_type(old_type_tag)), + base_type__name(tag__base_type(new_type_tag))); class__demote_bitfield_members(class, member, member, tag__base_type(old_type_tag), diff --git a/pahole.c b/pahole.c index 9baf622..6efbb0a 100644 --- a/pahole.c +++ b/pahole.c @@ -228,7 +228,8 @@ static void print_classes(void (*formatter)(struct structure *s)) savings); else printf("%s(%d)%c%zd%c%zd%c%zd\n", - t->decl_file, t->decl_line, separator, + tag__decl_file(t), t->decl_line, + separator, orig_size, separator, new_size, separator, savings); @@ -368,8 +369,8 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu, if (decl_exclude_prefix != NULL && - (tag->decl_file == NULL || - strncmp(decl_exclude_prefix, tag->decl_file, + (!tag->decl_file || + strncmp(decl_exclude_prefix, tag__decl_file(tag), decl_exclude_prefix_len) == 0)) return NULL; @@ -462,8 +463,8 @@ static void class__resize_LP(struct tag *tag, struct cu *cu) case DW_TAG_base_type: { struct base_type *bt = tag__base_type(type); - if (strcmp(bt->name, "long int") != 0 && - strcmp(bt->name, "long unsigned int") != 0) + if (strcmp(base_type__name(bt), "long int") != 0 && + strcmp(base_type__name(bt), "long unsigned int") != 0) break; /* fallthru */ } @@ -565,11 +566,11 @@ static int tag_fixup_word_size_iterator(struct tag *tag, struct cu *cu, * built with GNU C 4.3.0 20080130 (Red Hat 4.3.0-0.7), * one was found, so just bail out. */ - if (bt->name == NULL) + if (!bt->name) return 0; - if (strcmp(bt->name, "long int") == 0 || - strcmp(bt->name, "long unsigned int") == 0) + if (strcmp(base_type__name(bt), "long int") == 0 || + strcmp(base_type__name(bt), "long unsigned int") == 0) bt->bit_size = word_size * 8; } break; @@ -667,7 +668,8 @@ static void print_structs_with_pointer_to(const struct structure *s) tag__assert_search_result(ctype); if (ctype->tag == DW_TAG_pointer_type && ctype->type == type) - printf("%s: %s\n", class__name(c, pos_structure->cu), pos_member->name); + printf("%s: %s\n", class__name(c, pos_structure->cu), + class_member__name(pos_member)); } } } @@ -956,11 +958,10 @@ static struct argp pahole__argp = { int main(int argc, char *argv[]) { - struct cus *cus; int err; + struct cus *cus = cus__new(); - cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(cacheline_size) || cus == NULL) { fputs("pahole: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -969,8 +970,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(cacheline_size); - if (word_size != 0) cus__for_each_cu(cus, cu_fixup_word_size_iterator, NULL, NULL); diff --git a/pdwtags.c b/pdwtags.c index dc7d0bc..8aaa70d 100644 --- a/pdwtags.c +++ b/pdwtags.c @@ -91,7 +91,7 @@ int main(int argc, char *argv[]) int err; struct cus *cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(0) || cus == NULL) { fputs("pwdtags: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -100,7 +100,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(0); cus__emit_tags(cus); return EXIT_SUCCESS; } diff --git a/pfunct.c b/pfunct.c index eed61a3..4a95680 100644 --- a/pfunct.c +++ b/pfunct.c @@ -223,7 +223,7 @@ static struct tag *function__filter(struct tag *tag, struct cu *cu, * FIXME: remove this check and try to fix the parameter abstract * origin code someday... */ - if (function->name == NULL) + if (!function->name) return NULL; name = function__name(function, cu); @@ -491,7 +491,7 @@ int main(int argc, char *argv[]) int err; struct cus *cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(0) || cus == NULL) { fputs("pfunct: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -500,8 +500,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(0); - cus__for_each_cu(cus, cu_unique_iterator, NULL, NULL); if (show_total_inline_expansion_stats) diff --git a/pglobal.c b/pglobal.c index 05afc0a..995f63e 100644 --- a/pglobal.c +++ b/pglobal.c @@ -313,7 +313,7 @@ int main(int argc, char *argv[]) int err; struct cus *cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(0) || cus == NULL) { fputs("pglobal: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -322,8 +322,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(0); - if (walk_var) { cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL); twalk(tree, declaration_action__walk); diff --git a/prefcnt.c b/prefcnt.c index 0a9335c..6be6578 100644 --- a/prefcnt.c +++ b/prefcnt.c @@ -135,7 +135,7 @@ static int cu_refcnt_iterator(struct cu *cu, void *cookie) static int lost_iterator(struct tag *tag, struct cu *cu, void *cookie __unused) { - if (tag->refcnt == 0 && tag->decl_file != NULL) { + if (tag->refcnt == 0 && tag->decl_file) { tag__fprintf(tag, cu, NULL, stdout); puts(";\n"); } @@ -152,7 +152,7 @@ int main(int argc, char *argv[]) int err; struct cus *cus = cus__new(); - if (cus == NULL) { + if (dwarves__init(0) || cus == NULL) { fputs("prefcnt: insufficient memory\n", stderr); return EXIT_FAILURE; } @@ -161,7 +161,6 @@ int main(int argc, char *argv[]) if (err != 0) return EXIT_FAILURE; - dwarves__init(0); cus__for_each_cu(cus, cu_refcnt_iterator, NULL, NULL); cus__for_each_cu(cus, cu_lost_iterator, NULL, NULL); diff --git a/strings.c b/strings.c new file mode 100644 index 0000000..62d1b48 --- /dev/null +++ b/strings.c @@ -0,0 +1,185 @@ +/* + Copyright (C) 2008 Arnaldo Carvalho de Melo + + 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 "strings.h" + +#include +#include +#include +#include +#include +#include + +#include "dutil.h" + +#define STRINGS__ZCHUNK (128 * 1024) +#define STRINGS__SCHUNK (8 * 1024) + +struct strings { + void *tree; + char *entries; + unsigned int nr_entries; + strings_t index; + strings_t allocated_size; +}; + +struct strings *strings__new(void) +{ + struct strings *self = malloc(sizeof(*self)); + + if (self != NULL) { + memset(self, 0, sizeof(*self)); + /* 0 == NULL */ + self->index = 1; + } + + return self; + +} + +const char *strings__entries(const struct strings *self) +{ + return self->entries; +} + +unsigned int strings__nr_entries(const struct strings *self) +{ + return self->nr_entries; +} + +strings_t strings__size(const struct strings *self) +{ + return self->index; +} + +static void do_nothing(void *ptr __unused) +{ +} + +void strings__delete(struct strings *self) +{ + tdestroy(self->tree, do_nothing); + free(self->entries); + free(self); +} + +const char *strings__ptr(const struct strings *self, strings_t s) +{ + return s ? self->entries + s : NULL; +} + +static strings_t strings__insert(struct strings *self, const char *s) +{ + const size_t len = strlen(s); + const strings_t rc = self->index; + const strings_t index = self->index + len + 1; + char *copy; + + if (index >= self->allocated_size) { + const strings_t allocated_size = (self->allocated_size + + STRINGS__SCHUNK); + char *entries = realloc(self->entries, allocated_size); + + if (entries == NULL) + return 0; + + self->allocated_size = allocated_size; + self->entries = entries; + } + + ++self->nr_entries; + copy = self->entries + rc; + memcpy(copy, s, len + 1); + self->index = index; + return rc; +} + +struct search_key { + struct strings *self; + const char *str; +}; + +static int strings__compare(const void *a, const void *b) +{ + const struct search_key *key = a; + + return strcmp(key->str, key->self->entries + *(strings_t *)&b); +} + +strings_t strings__add(struct strings *self, const char *str) +{ + strings_t *s; + strings_t index; + struct search_key key = { + .self = self, + .str = str, + }; + + if (str == NULL) + return 0; + + s = tsearch(&key, &self->tree, strings__compare); + if (s != NULL) { + if (*(struct search_key **)s == (void *)&key) { /* Not found, replace with the right key */ + index = strings__insert(self, str); + if (index != 0) + *s = index; + else { + tdelete(&key, &self->tree, strings__compare); + return 0; + } + } else /* Found! */ + index = *s; + } else + return 0; + + return index; +} + +const char *strings__compress(struct strings *self, unsigned int *size) +{ + z_stream z = { + .zalloc = Z_NULL, + .zfree = Z_NULL, + .opaque = Z_NULL, + .avail_in = strings__size(self), + .next_in = (Bytef *)strings__entries(self), + }; + char *bf = NULL; + unsigned int bf_size = 0; + + if (deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK) + goto out_free; + + do { + const unsigned int new_bf_size = bf_size + STRINGS__ZCHUNK; + char *nbf = realloc(bf, new_bf_size); + + if (nbf == NULL) + goto out_close_and_free; + + bf = nbf; + z.avail_out = STRINGS__ZCHUNK; + z.next_out = (Bytef *)bf + bf_size; + bf_size = new_bf_size; + if (deflate(&z, Z_FINISH) == Z_STREAM_ERROR) + goto out_close_and_free; + } while (z.avail_out == 0); + + deflateEnd(&z); + *size = bf_size - z.avail_out; +out: + return bf; + +out_close_and_free: + deflateEnd(&z); +out_free: + free(bf); + bf = NULL; + goto out; +} diff --git a/strings.h b/strings.h new file mode 100644 index 0000000..92f8047 --- /dev/null +++ b/strings.h @@ -0,0 +1,31 @@ +#ifndef _STRINGS_H_ +#define _STRINGS_H_ 1 +/* + Copyright (C) 2008 Arnaldo Carvalho de Melo + + 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. +*/ + +typedef unsigned int strings_t; + +struct strings; + +struct strings *strings__new(void); + +void strings__delete(struct strings *self); + +strings_t strings__add(struct strings *self, const char *str); + +const char *strings__ptr(const struct strings *self, strings_t s); + +const char *strings__entries(const struct strings *self); + +unsigned int strings__nr_entries(const struct strings *self); + +strings_t strings__size(const struct strings *self); + +const char *strings__compress(struct strings *self, unsigned int *size); + +#endif /* _STRINGS_H_ */ diff --git a/syscse.c b/syscse.c index 4865c3e..880453d 100644 --- a/syscse.c +++ b/syscse.c @@ -56,7 +56,8 @@ static void zero_extend(const int regparm, const struct base_type *bt, printf("\t%s\t$a%d, $a%d, 0" "\t/* zero extend $a%d(%s %s) from %zd to 64-bit */\n", - instr, regparm, regparm, regparm, bt->name, parm, bt->bit_size); + instr, regparm, regparm, regparm, base_type__name(bt), + parm, bt->bit_size); } static int emit_wrapper(struct tag *self, struct cu *cu, void *cookie __unused) @@ -75,7 +76,7 @@ static int emit_wrapper(struct tag *self, struct cu *cu, void *cookie __unused) struct base_type *bt = tag__base_type(type); if (bt->bit_size < 64 && - strncmp(bt->name, "unsigned", 8) == 0) { + strncmp(base_type__name(bt), "unsigned", 8) == 0) { if (!needs_wrapper) { printf("wrap_%s:\n", name); needs_wrapper = 1;