strings: Introduce the strings class

And make the dwarves use it, so that we can remove duplicate strings in
a multi-CU file (vmlinux anyone?) and have it ready for insertion in a
compressed DWARF format with just the types, or better, CTF or some new
compressed debugging info format.

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2008-10-02 14:34:42 -03:00
parent 964c6b0666
commit 212b994ab5
17 changed files with 405 additions and 165 deletions

View File

@ -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})

View File

@ -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();

View File

@ -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;
}

View File

@ -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);
/*

View File

@ -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;

View File

@ -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);

120
dwarves.c
View File

@ -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 = "<IMPORTED MODULE ERROR!>";
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;
}

View File

@ -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_ */

View File

@ -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),

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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);

View File

@ -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);

185
strings.c Normal file
View File

@ -0,0 +1,185 @@
/*
Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
#include "strings.h"
#include <search.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>
#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;
}

31
strings.h Normal file
View File

@ -0,0 +1,31 @@
#ifndef _STRINGS_H_
#define _STRINGS_H_ 1
/*
Copyright (C) 2008 Arnaldo Carvalho de Melo <acme@redhat.com>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
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_ */

View File

@ -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;