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:
parent
964c6b0666
commit
212b994ab5
|
@ -31,7 +31,7 @@ find_package(ZLIB REQUIRED)
|
||||||
|
|
||||||
_set_fancy(LIB_INSTALL_DIR "${EXEC_INSTALL_PREFIX}${CMAKE_INSTALL_PREFIX}/${__LIB}" "libdir")
|
_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})
|
add_library(dwarves SHARED ${dwarves_LIB_SRCS})
|
||||||
set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
set_target_properties(dwarves PROPERTIES VERSION 1.0.0 SOVERSION 1)
|
||||||
target_link_libraries(dwarves ${DWARF_LIBRARIES} ${ZLIB_LIBRARIES})
|
target_link_libraries(dwarves ${DWARF_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||||
|
|
29
codiff.c
29
codiff.c
|
@ -165,7 +165,7 @@ static int check_print_change(const struct class_member *old,
|
||||||
printf(" %s\n"
|
printf(" %s\n"
|
||||||
" from: %-21s /* %5u(%u) %5zd(%d) */\n"
|
" from: %-21s /* %5u(%u) %5zd(%d) */\n"
|
||||||
" to: %-21s /* %5u(%u) %5zd(%u) */\n",
|
" to: %-21s /* %5u(%u) %5zd(%u) */\n",
|
||||||
old->name,
|
class_member__name(old),
|
||||||
old_type_name, old->offset, old->bit_offset,
|
old_type_name, old->offset, old->bit_offset,
|
||||||
old_size, old->bit_size,
|
old_size, old->bit_size,
|
||||||
new_type_name, new->offset, new->bit_offset,
|
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) {
|
type__for_each_member(&structure->type, member) {
|
||||||
struct class_member *twin =
|
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 (twin != NULL)
|
||||||
if (check_print_change(member, cu, twin, new_cu, print))
|
if (check_print_change(member, cu, twin, new_cu, print))
|
||||||
changes = 1;
|
changes = 1;
|
||||||
|
@ -351,14 +352,16 @@ static void show_diffs_function(struct function *function, const struct cu *cu,
|
||||||
if (di->tag == NULL)
|
if (di->tag == NULL)
|
||||||
puts(cookie ? " (added)" : " (removed)");
|
puts(cookie ? " (added)" : " (removed)");
|
||||||
else {
|
else {
|
||||||
const struct function *twin = tag__function(di->tag);
|
struct function *twin = tag__function(di->tag);
|
||||||
|
|
||||||
if (twin->inlined)
|
if (twin->inlined)
|
||||||
puts(cookie ? " (uninlined)" : " (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, "
|
printf("%s: BRAIN FART ALERT: comparing %s to %s, "
|
||||||
"should be the same name\n", __FUNCTION__,
|
"should be the same name\n", __FUNCTION__,
|
||||||
function->name, twin->name);
|
function__name(function, cu),
|
||||||
|
function__name(twin, di->cu));
|
||||||
else {
|
else {
|
||||||
char proto[1024], twin_proto[1024];
|
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);
|
tag__assert_search_result(type);
|
||||||
printf(" %c%-26s %-21s /* %5u %5zd */\n",
|
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));
|
member->offset, tag__size(type, cu));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -412,7 +416,8 @@ static void show_nr_members_changes(const struct class *structure,
|
||||||
/* Find the removed ones */
|
/* Find the removed ones */
|
||||||
type__for_each_member(&structure->type, member) {
|
type__for_each_member(&structure->type, member) {
|
||||||
struct class_member *twin =
|
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 (twin == NULL)
|
||||||
show_changed_member('-', member, cu);
|
show_changed_member('-', member, cu);
|
||||||
}
|
}
|
||||||
|
@ -420,7 +425,8 @@ static void show_nr_members_changes(const struct class *structure,
|
||||||
/* Find the new ones */
|
/* Find the new ones */
|
||||||
type__for_each_member(&new_structure->type, member) {
|
type__for_each_member(&new_structure->type, member) {
|
||||||
struct class_member *twin =
|
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)
|
if (twin == NULL)
|
||||||
show_changed_member('+', member, new_cu);
|
show_changed_member('+', member, new_cu);
|
||||||
}
|
}
|
||||||
|
@ -673,6 +679,11 @@ int main(int argc, char *argv[])
|
||||||
char *dwfl_argv[4];
|
char *dwfl_argv[4];
|
||||||
struct stat st;
|
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);
|
argp_parse(&codiff__argp, argc, argv, 0, &remaining, NULL);
|
||||||
|
|
||||||
if (remaining < argc) {
|
if (remaining < argc) {
|
||||||
|
@ -692,8 +703,6 @@ failure:
|
||||||
show_terse_type_changes == 0)
|
show_terse_type_changes == 0)
|
||||||
show_function_diffs = show_struct_diffs = 1;
|
show_function_diffs = show_struct_diffs = 1;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
|
|
||||||
structs_printed = strlist__new(false);
|
structs_printed = strlist__new(false);
|
||||||
old_cus = cus__new();
|
old_cus = cus__new();
|
||||||
new_cus = cus__new();
|
new_cus = cus__new();
|
||||||
|
|
18
ctf_loader.c
18
ctf_loader.c
|
@ -24,6 +24,12 @@
|
||||||
#include "dutil.h"
|
#include "dutil.h"
|
||||||
#include "dwarves.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)
|
static void *zalloc(const size_t size)
|
||||||
{
|
{
|
||||||
void *s = malloc(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));
|
struct base_type *self = zalloc(sizeof(*self));
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
self->name = strings__add(name);
|
self->name = strings__add(strings, name);
|
||||||
self->bit_size = size;
|
self->bit_size = size;
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
|
@ -332,7 +338,7 @@ static void type__init(struct type *self, uint16_t tag, unsigned int id,
|
||||||
self->size = size;
|
self->size = size;
|
||||||
self->namespace.tag.id = id;
|
self->namespace.tag.id = id;
|
||||||
self->namespace.tag.tag = tag;
|
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,
|
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)
|
if (self == NULL)
|
||||||
oom("function__new");
|
oom("function__new");
|
||||||
|
|
||||||
self->name = strings__add(name);
|
self->name = strings__add(strings, name);
|
||||||
INIT_LIST_HEAD(&self->vtable_node);
|
INIT_LIST_HEAD(&self->vtable_node);
|
||||||
INIT_LIST_HEAD(&self->tool_node);
|
INIT_LIST_HEAD(&self->tool_node);
|
||||||
INIT_LIST_HEAD(&self->proto.parms);
|
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.tag = DW_TAG_member;
|
||||||
member->tag.type = ctf__get16(sp->ctf, &mp[i].ctf_member_type);
|
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) |
|
bit_offset = (ctf__get32(sp->ctf, &mp[i].ctf_member_offset_high) << 16) |
|
||||||
ctf__get32(sp->ctf, &mp[i].ctf_member_offset_low);
|
ctf__get32(sp->ctf, &mp[i].ctf_member_offset_low);
|
||||||
member->offset = bit_offset / 8;
|
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.tag = DW_TAG_member;
|
||||||
member->tag.type = ctf__get16(sp->ctf, &mp[i].ctf_member_type);
|
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);
|
bit_offset = ctf__get16(sp->ctf, &mp[i].ctf_member_offset);
|
||||||
member->offset = bit_offset / 8;
|
member->offset = bit_offset / 8;
|
||||||
member->bit_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));
|
struct enumerator *self = zalloc(sizeof(*self));
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
self->name = strings__add(name);
|
self->name = strings__add(strings, name);
|
||||||
self->value = value;
|
self->value = value;
|
||||||
self->tag.tag = DW_TAG_enumerator;
|
self->tag.tag = DW_TAG_enumerator;
|
||||||
}
|
}
|
||||||
|
|
33
ctracer.c
33
ctracer.c
|
@ -305,7 +305,8 @@ static size_t class__find_biggest_member_name(const struct class *self)
|
||||||
size_t biggest_name_len = 0;
|
size_t biggest_name_len = 0;
|
||||||
|
|
||||||
type__for_each_data_member(&self->type, pos) {
|
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)
|
if (len > biggest_name_len)
|
||||||
biggest_name_len = 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));
|
class__name(self, cu), class__name(clone, cu));
|
||||||
type__for_each_data_member(&clone->type, pos)
|
type__for_each_data_member(&clone->type, pos)
|
||||||
fprintf(fp_collector, "\tmini_obj->%-*s = obj->%s;\n",
|
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);
|
fputs("}\n\n", fp_collector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,10 +469,11 @@ static int class__emit_ostra_converter(struct tag *tag_self,
|
||||||
plen -= n; p += n;
|
plen -= n; p += n;
|
||||||
}
|
}
|
||||||
fprintf(fp_converter, "%%u");
|
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;
|
plen -= n; p += n;
|
||||||
emit_struct_member_table_entry(fp_fields, field++,
|
emit_struct_member_table_entry(fp_fields, field++,
|
||||||
pos->name, 1, "entry,exit");
|
class_member__name(pos),
|
||||||
|
1, "entry,exit");
|
||||||
}
|
}
|
||||||
fprintf(fp_converter,
|
fprintf(fp_converter,
|
||||||
"\\n\",\n\t\t\t %s);\n"
|
"\\n\",\n\t\t\t %s);\n"
|
||||||
|
@ -717,12 +719,14 @@ static int function__emit_probes(struct function *self, const struct cu *cu,
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (member != NULL)
|
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,
|
fprintf(fp_methods,
|
||||||
"\tctracer__method_hook(%d, %#llx, $%s%s%s, %zd);\n",
|
"\tctracer__method_hook(%d, %#llx, $%s%s%s, %zd);\n",
|
||||||
probe_type,
|
probe_type,
|
||||||
(unsigned long long)self->proto.tag.id, pos->name,
|
(unsigned long long)self->proto.tag.id,
|
||||||
|
parameter__name(pos, cu),
|
||||||
member ? "->" : "", member ?: "",
|
member ? "->" : "", member ?: "",
|
||||||
class__size(mini_class));
|
class__size(mini_class));
|
||||||
break;
|
break;
|
||||||
|
@ -788,8 +792,10 @@ static int cu_emit_pointer_probes_iterator(struct cu *cu, void *cookie)
|
||||||
continue;
|
continue;
|
||||||
pos_tag->priv = (void *)1; /* Mark as visited, for the table iterator */
|
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, 0,
|
||||||
function__emit_probes(pos_tag, cu, pointer, 1, pos_member->name); /* exit */
|
class_member__name(pos_member)); /* entry */
|
||||||
|
function__emit_probes(pos_tag, cu, pointer, 1,
|
||||||
|
class_member__name(pos_member)); /* exit */
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -888,6 +894,11 @@ int main(int argc, char *argv[])
|
||||||
struct structure *pos;
|
struct structure *pos;
|
||||||
FILE *fp_functions;
|
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);
|
argp_parse(&ctracer__argp, argc, argv, 0, &remaining, NULL);
|
||||||
|
|
||||||
if (remaining < argc) {
|
if (remaining < argc) {
|
||||||
|
@ -903,12 +914,6 @@ failure:
|
||||||
return EXIT_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);
|
type_emissions__init(&emissions);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -44,7 +44,7 @@ int main(int argc, char *argv[])
|
||||||
int err;
|
int err;
|
||||||
struct cus *cus = cus__new();
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
if (cus == NULL) {
|
if (dwarves__init(0) || cus == NULL) {
|
||||||
fputs("dtagnames: insufficient memory\n", stderr);
|
fputs("dtagnames: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
|
|
||||||
cus__dump_class_tag_names(cus);
|
cus__dump_class_tag_names(cus);
|
||||||
print_malloc_stats();
|
print_malloc_stats();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "dwarves.h"
|
#include "dwarves.h"
|
||||||
#include "dutil.h"
|
#include "dutil.h"
|
||||||
|
#include "strings.h"
|
||||||
|
|
||||||
|
extern struct strings *strings;
|
||||||
|
|
||||||
static void *zalloc(const size_t size)
|
static void *zalloc(const size_t size)
|
||||||
{
|
{
|
||||||
|
@ -186,7 +189,7 @@ static void tag__init(struct tag *self, Dwarf_Die *die)
|
||||||
else
|
else
|
||||||
self->type = attr_type(die, DW_AT_type);
|
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);
|
dwarf_decl_line(die, &decl_line);
|
||||||
self->decl_line = decl_line;
|
self->decl_line = decl_line;
|
||||||
self->recursivity_level = 0;
|
self->recursivity_level = 0;
|
||||||
|
@ -221,7 +224,7 @@ static struct base_type *base_type__new(Dwarf_Die *die)
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
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;
|
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);
|
tag__init(&self->tag, die);
|
||||||
INIT_LIST_HEAD(&self->tags);
|
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;
|
self->nr_tags = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -285,7 +288,7 @@ static struct enumerator *enumerator__new(Dwarf_Die *die)
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
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);
|
self->value = attr_numeric(die, DW_AT_const_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +323,7 @@ static struct variable *variable__new(Dwarf_Die *die)
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
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);
|
self->abstract_origin = attr_type(die, DW_AT_abstract_origin);
|
||||||
/* variable is visible outside of its enclosing cu */
|
/* variable is visible outside of its enclosing cu */
|
||||||
self->external = dwarf_hasattr(die, DW_AT_external);
|
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->bit_offset = attr_numeric(die, DW_AT_bit_offset);
|
||||||
self->accessibility = attr_numeric(die, DW_AT_accessibility);
|
self->accessibility = attr_numeric(die, DW_AT_accessibility);
|
||||||
self->virtuality = attr_numeric(die, DW_AT_virtuality);
|
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;
|
return self;
|
||||||
|
@ -357,7 +360,7 @@ static struct parameter *parameter__new(Dwarf_Die *die)
|
||||||
|
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
tag__init(&self->tag, die);
|
||||||
self->name = strings__add(attr_string(die,
|
self->name = strings__add(strings, attr_string(die,
|
||||||
DW_AT_name));
|
DW_AT_name));
|
||||||
self->abstract_origin = attr_type(die, DW_AT_abstract_origin);
|
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) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
tag__init(&self->tag, die);
|
||||||
self->tag.decl_file =
|
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.decl_line = attr_numeric(die, DW_AT_call_line);
|
||||||
self->tag.type = attr_type(die, DW_AT_abstract_origin);
|
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) {
|
if (self != NULL) {
|
||||||
tag__init(&self->tag, die);
|
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))
|
if (dwarf_lowpc(die, &self->low_pc))
|
||||||
self->low_pc = 0;
|
self->low_pc = 0;
|
||||||
}
|
}
|
||||||
|
@ -484,8 +487,8 @@ static struct function *function__new(Dwarf_Die *die)
|
||||||
if (self != NULL) {
|
if (self != NULL) {
|
||||||
ftype__init(&self->proto, die);
|
ftype__init(&self->proto, die);
|
||||||
lexblock__init(&self->lexblock, die);
|
lexblock__init(&self->lexblock, die);
|
||||||
self->name = strings__add(attr_string(die, DW_AT_name));
|
self->name = strings__add(strings, attr_string(die, DW_AT_name));
|
||||||
self->linkage_name = strings__add(attr_string(die, DW_AT_MIPS_linkage_name));
|
self->linkage_name = strings__add(strings, attr_string(die, DW_AT_MIPS_linkage_name));
|
||||||
self->inlined = attr_numeric(die, DW_AT_inline);
|
self->inlined = attr_numeric(die, DW_AT_inline);
|
||||||
self->external = dwarf_hasattr(die, DW_AT_external);
|
self->external = dwarf_hasattr(die, DW_AT_external);
|
||||||
self->abstract_origin = attr_type(die, DW_AT_abstract_origin);
|
self->abstract_origin = attr_type(die, DW_AT_abstract_origin);
|
||||||
|
|
118
dwarves.c
118
dwarves.c
|
@ -29,6 +29,14 @@
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "dwarves.h"
|
#include "dwarves.h"
|
||||||
#include "dutil.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[] = {
|
static const char *dwarf_tag_names[] = {
|
||||||
[DW_TAG_array_type] = "array_type",
|
[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 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)
|
void tag__delete(struct tag *self)
|
||||||
{
|
{
|
||||||
assert(list_empty(&self->node));
|
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",
|
return fprintf(fp, "/* <%llx> %s:%u */\n",
|
||||||
(unsigned long long)self->id,
|
(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,
|
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)
|
const char *type__name(struct type *self, const struct cu *cu)
|
||||||
{
|
{
|
||||||
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
|
/* 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... */
|
/* No? So it can have a DW_TAG_specification... */
|
||||||
self->specification != 0 &&
|
self->specification != 0 &&
|
||||||
cu != NULL) {
|
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;
|
self->namespace.name = tag__type(tag)->namespace.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self->namespace.name;
|
return s(self->namespace.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct class_member *
|
struct class_member *
|
||||||
|
@ -434,7 +411,7 @@ static size_t imported_module__fprintf(const struct tag *self,
|
||||||
const char *name = "<IMPORTED MODULE ERROR!>";
|
const char *name = "<IMPORTED MODULE ERROR!>";
|
||||||
|
|
||||||
if (tag__is_namespace(module))
|
if (tag__is_namespace(module))
|
||||||
name = tag__namespace(module)->name;
|
name = s(tag__namespace(module)->name);
|
||||||
|
|
||||||
return fprintf(fp, "using namespace %s", 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)
|
type__for_each_enumerator(self, pos)
|
||||||
printed += fprintf(fp, "%.*s\t%s = %u,\n", indent, tabs,
|
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,
|
return printed + fprintf(fp, "%.*s}%s%s", indent, tabs,
|
||||||
conf->suffix ? " " : "", conf->suffix ?: "");
|
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->tags);
|
||||||
INIT_LIST_HEAD(&self->tool_list);
|
INIT_LIST_HEAD(&self->tool_list);
|
||||||
|
|
||||||
self->name = strings__add(name);
|
self->name = strdup(name);
|
||||||
self->addr_size = addr_size;
|
self->addr_size = addr_size;
|
||||||
|
|
||||||
self->nr_inline_expansions = 0;
|
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) {
|
if (pos->tag == DW_TAG_base_type) {
|
||||||
const struct base_type *bt = tag__base_type(pos);
|
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;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -690,7 +667,7 @@ struct cu *cus__find_cu_by_name(const struct cus *self, const char *name)
|
||||||
struct cu *pos;
|
struct cu *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->cus, node)
|
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 pos;
|
||||||
|
|
||||||
return NULL;
|
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)
|
if (pos->tag != DW_TAG_subprogram)
|
||||||
continue;
|
continue;
|
||||||
fpos = tag__function(pos);
|
fpos = tag__function(pos);
|
||||||
if (fpos->name != NULL && strcmp(fpos->name, name) == 0)
|
if (fpos->name && strcmp(s(fpos->name), name) == 0)
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,12 +863,12 @@ const char *tag__name(const struct tag *self, const struct cu *cu,
|
||||||
else switch (self->tag) {
|
else switch (self->tag) {
|
||||||
case DW_TAG_base_type: {
|
case DW_TAG_base_type: {
|
||||||
const struct base_type *bt = tag__base_type(self);
|
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)
|
if (bt->name)
|
||||||
s = bt->name;
|
name = s(bt->name);
|
||||||
|
|
||||||
strncpy(bf, s, len);
|
strncpy(bf, name, len);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DW_TAG_subprogram:
|
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)
|
const char *variable__name(const struct variable *self, const struct cu *cu)
|
||||||
{
|
{
|
||||||
if (self->name != NULL)
|
if (self->name)
|
||||||
return self->name;
|
return s(self->name);
|
||||||
|
|
||||||
if (self->abstract_origin != 0) {
|
if (self->abstract_origin != 0) {
|
||||||
struct variable *var =
|
struct variable *var =
|
||||||
cu__find_variable_by_id(cu, self->abstract_origin);
|
cu__find_variable_by_id(cu, self->abstract_origin);
|
||||||
if (var != NULL)
|
if (var != NULL)
|
||||||
return var->name;
|
return s(var->name);
|
||||||
}
|
}
|
||||||
return NULL;
|
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)
|
const char *parameter__name(struct parameter *self, const struct cu *cu)
|
||||||
{
|
{
|
||||||
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
|
/* 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? */
|
/* No? Does it have a DW_AT_abstract_origin? */
|
||||||
struct tag *alias =
|
struct tag *alias =
|
||||||
cu__find_parameter_by_id(cu, self->abstract_origin);
|
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;
|
self->name = tag__parameter(alias)->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self->name;
|
return s(self->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu)
|
Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu)
|
||||||
|
@ -1238,7 +1215,7 @@ static size_t struct_member__fprintf(struct class_member *self,
|
||||||
struct conf_fprintf sconf = *conf;
|
struct conf_fprintf sconf = *conf;
|
||||||
uint32_t offset = self->offset;
|
uint32_t offset = self->offset;
|
||||||
size_t printed = 0;
|
size_t printed = 0;
|
||||||
const char *name = self->name;
|
const char *name = s(self->name);
|
||||||
|
|
||||||
if (!sconf.rel_offset) {
|
if (!sconf.rel_offset) {
|
||||||
sconf.base_offset += self->offset;
|
sconf.base_offset += self->offset;
|
||||||
|
@ -1265,8 +1242,8 @@ static size_t struct_member__fprintf(struct class_member *self,
|
||||||
type__name(tag__type(type), cu) == NULL) {
|
type__name(tag__type(type), cu) == NULL) {
|
||||||
if (!sconf.suppress_offset_comment) {
|
if (!sconf.suppress_offset_comment) {
|
||||||
/* Check if this is a anonymous union */
|
/* Check if this is a anonymous union */
|
||||||
const int slen = self->name != NULL ?
|
const int slen = self->name ?
|
||||||
(int)strlen(self->name) : -1;
|
(int)strlen(s(self->name)) : -1;
|
||||||
printed += fprintf(fp, "%*s/* %5u %5u */",
|
printed += fprintf(fp, "%*s/* %5u %5u */",
|
||||||
(sconf.type_spacing +
|
(sconf.type_spacing +
|
||||||
sconf.name_spacing - slen - 3),
|
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 struct conf_fprintf *conf, FILE *fp)
|
||||||
{
|
{
|
||||||
const size_t size = tag__size(type, cu);
|
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) ||
|
if ((tag__is_union(type) || tag__is_struct(type) ||
|
||||||
tag__is_enumeration(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) {
|
type__name(tag__type(type), cu) == NULL) {
|
||||||
if (!conf->suppress_offset_comment) {
|
if (!conf->suppress_offset_comment) {
|
||||||
/* Check if this is a anonymous union */
|
/* 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
|
* Add the comment with the union size after padding the
|
||||||
* '} member_name;' last line of the type printed in 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;
|
self = NULL;
|
||||||
}
|
}
|
||||||
if (new_class_name != 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;
|
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)
|
const char *function__name(struct function *self, const struct cu *cu)
|
||||||
{
|
{
|
||||||
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
|
/* 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... */
|
/* No? So it must have a DW_AT_abstract_origin... */
|
||||||
struct tag *tag = cu__find_tag_by_id(cu,
|
struct tag *tag = cu__find_tag_by_id(cu,
|
||||||
self->abstract_origin);
|
self->abstract_origin);
|
||||||
|
@ -1476,7 +1454,7 @@ const char *function__name(struct function *self, const struct cu *cu)
|
||||||
self->name = tag__function(tag)->name;
|
self->name = tag__function(tag)->name;
|
||||||
}
|
}
|
||||||
|
|
||||||
return self->name;
|
return s(self->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *function__prototype(const struct function *self,
|
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) {
|
if (name != NULL) {
|
||||||
struct class_member *pos;
|
struct class_member *pos;
|
||||||
type__for_each_data_member(self, 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;
|
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);
|
printed = fprintf(fp, "%.*s", indent, tabs);
|
||||||
fputc('\n', fp);
|
fputc('\n', fp);
|
||||||
++printed;
|
++printed;
|
||||||
c = fprintf(fp, "%s:", label->name);
|
c = fprintf(fp, "%s:", s(label->name));
|
||||||
printed += c;
|
printed += c;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -2018,7 +1996,8 @@ static size_t class__vtable_fprintf(struct class *self,
|
||||||
list_for_each_entry(pos, &self->vtable, vtable_node) {
|
list_for_each_entry(pos, &self->vtable, vtable_node) {
|
||||||
printed += fprintf(fp, "%.*s [%d] = %s(%s), \n",
|
printed += fprintf(fp, "%.*s [%d] = %s(%s), \n",
|
||||||
conf->indent, tabs, pos->vtable_entry,
|
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);
|
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);
|
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 */",
|
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));
|
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 namespace *self = tag__namespace(tself);
|
||||||
struct conf_fprintf cconf = *conf;
|
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;
|
struct tag *pos;
|
||||||
|
|
||||||
++cconf.indent;
|
++cconf.indent;
|
||||||
|
@ -2479,8 +2459,9 @@ size_t tag__fprintf(struct tag *self, const struct cu *cu,
|
||||||
!pconf->suppress_comments) {
|
!pconf->suppress_comments) {
|
||||||
const struct function *fself = tag__function(self);
|
const struct function *fself = tag__function(self);
|
||||||
|
|
||||||
if (fself->linkage_name != NULL)
|
if (fself->linkage_name)
|
||||||
printed += fprintf(fp, " /* linkage=%s */", fself->linkage_name);
|
printed += fprintf(fp, " /* linkage=%s */",
|
||||||
|
s(fself->linkage_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pconf->expand_types)
|
if (pconf->expand_types)
|
||||||
|
@ -2625,8 +2606,13 @@ struct cus *cus__new(void)
|
||||||
return self;
|
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) {
|
if (user_cacheline_size == 0) {
|
||||||
long sys_cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
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 */
|
cacheline_size = 64; /* Fall back to a sane value */
|
||||||
} else
|
} else
|
||||||
cacheline_size = user_cacheline_size;
|
cacheline_size = user_cacheline_size;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
44
dwarves.h
44
dwarves.h
|
@ -17,6 +17,9 @@
|
||||||
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
#include "strings.h"
|
||||||
|
|
||||||
|
extern struct strings *strings;
|
||||||
|
|
||||||
struct argp;
|
struct argp;
|
||||||
|
|
||||||
|
@ -58,7 +61,7 @@ struct tag {
|
||||||
struct list_head hash_node;
|
struct list_head hash_node;
|
||||||
Dwarf_Off type;
|
Dwarf_Off type;
|
||||||
Dwarf_Off id;
|
Dwarf_Off id;
|
||||||
const char *decl_file;
|
strings_t decl_file;
|
||||||
uint16_t decl_line;
|
uint16_t decl_line;
|
||||||
uint16_t tag;
|
uint16_t tag;
|
||||||
uint16_t refcnt;
|
uint16_t refcnt;
|
||||||
|
@ -99,6 +102,11 @@ static inline int tag__is_type(const struct tag *self)
|
||||||
tag__is_enumeration(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 ptr_to_member_type {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
Dwarf_Off containing_type;
|
Dwarf_Off containing_type;
|
||||||
|
@ -112,9 +120,9 @@ static inline struct ptr_to_member_type *
|
||||||
|
|
||||||
struct namespace {
|
struct namespace {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
const char *name;
|
strings_t name;
|
||||||
struct list_head tags;
|
|
||||||
uint16_t nr_tags;
|
uint16_t nr_tags;
|
||||||
|
struct list_head tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct namespace *tag__namespace(const struct tag *self)
|
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 base_type {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
const char *name;
|
strings_t name;
|
||||||
size_t bit_size;
|
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;
|
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 array_type {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
uint32_t *nr_entries;
|
uint32_t *nr_entries;
|
||||||
|
@ -305,7 +318,7 @@ static inline struct array_type *tag__array_type(const struct tag *self)
|
||||||
|
|
||||||
struct class_member {
|
struct class_member {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
char *name;
|
strings_t name;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint8_t bit_offset;
|
uint8_t bit_offset;
|
||||||
uint8_t bit_size;
|
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,
|
extern size_t class_member__size(const struct class_member *self,
|
||||||
const struct cu *cu);
|
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);
|
extern void class_member__delete(struct class_member *self);
|
||||||
|
|
||||||
struct lexblock {
|
struct lexblock {
|
||||||
|
@ -371,10 +390,10 @@ static inline struct ftype *tag__ftype(const struct tag *self)
|
||||||
struct function {
|
struct function {
|
||||||
struct ftype proto;
|
struct ftype proto;
|
||||||
struct lexblock lexblock;
|
struct lexblock lexblock;
|
||||||
const char *name;
|
|
||||||
char *linkage_name;
|
|
||||||
Dwarf_Off abstract_origin;
|
Dwarf_Off abstract_origin;
|
||||||
Dwarf_Off specification;
|
Dwarf_Off specification;
|
||||||
|
strings_t name;
|
||||||
|
strings_t linkage_name;
|
||||||
size_t cu_total_size_inline_expansions;
|
size_t cu_total_size_inline_expansions;
|
||||||
uint16_t cu_total_nr_inline_expansions;
|
uint16_t cu_total_nr_inline_expansions;
|
||||||
uint8_t inlined:2;
|
uint8_t inlined:2;
|
||||||
|
@ -408,7 +427,7 @@ static inline struct tag *function__tag(const struct function *self)
|
||||||
|
|
||||||
struct parameter {
|
struct parameter {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
char *name;
|
strings_t name;
|
||||||
Dwarf_Off abstract_origin;
|
Dwarf_Off abstract_origin;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -430,8 +449,8 @@ enum vlocation {
|
||||||
|
|
||||||
struct variable {
|
struct variable {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
char *name;
|
|
||||||
Dwarf_Off abstract_origin;
|
Dwarf_Off abstract_origin;
|
||||||
|
strings_t name;
|
||||||
uint8_t external:1;
|
uint8_t external:1;
|
||||||
uint8_t declaration:1;
|
uint8_t declaration:1;
|
||||||
enum vlocation location;
|
enum vlocation location;
|
||||||
|
@ -457,13 +476,13 @@ static inline struct inline_expansion *
|
||||||
|
|
||||||
struct label {
|
struct label {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
char *name;
|
strings_t name;
|
||||||
Dwarf_Addr low_pc;
|
Dwarf_Addr low_pc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct enumerator {
|
struct enumerator {
|
||||||
struct tag tag;
|
struct tag tag;
|
||||||
const char *name;
|
strings_t name;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -486,7 +505,7 @@ struct conf_fprintf {
|
||||||
uint8_t show_first_biggest_size_base_type_member:1;
|
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 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);
|
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);
|
extern const char *dwarf_tag_name(const uint32_t tag);
|
||||||
|
|
||||||
char *strings__add(const char *str);
|
|
||||||
#endif /* _DWARVES_H_ */
|
#endif /* _DWARVES_H_ */
|
||||||
|
|
|
@ -260,7 +260,7 @@ static void class__move_member(struct class *class, struct class_member *dest,
|
||||||
LIST_HEAD(from_list);
|
LIST_HEAD(from_list);
|
||||||
|
|
||||||
if (verbose)
|
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),
|
list_for_each_entry_safe_from(pos, tmp, class__tags(class),
|
||||||
tag.node) {
|
tag.node) {
|
||||||
if (pos->tag.tag != DW_TAG_member)
|
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;
|
tail_from->bit_hole = orig_tail_from_bit_hole;
|
||||||
list_splice(&from_list, &dest->tag.node);
|
list_splice(&from_list, &dest->tag.node);
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, "'%s')", tail_from->name);
|
fprintf(fp, "'%s')", class_member__name(tail_from));
|
||||||
} else {
|
} else {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, " '%s'", from->name);
|
fprintf(fp, " '%s'", class_member__name(from));
|
||||||
/*
|
/*
|
||||||
* Remove 'from' from the list
|
* Remove 'from' from the list
|
||||||
*/
|
*/
|
||||||
|
@ -299,7 +299,8 @@ static void class__move_member(struct class *class, struct class_member *dest,
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, " from after '%s' to after '%s' */\n",
|
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) {
|
if (from_padding) {
|
||||||
/*
|
/*
|
||||||
|
@ -319,7 +320,7 @@ static void class__move_member(struct class *class, struct class_member *dest,
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, "/* adding %zd bytes from %s to "
|
fprintf(fp, "/* adding %zd bytes from %s to "
|
||||||
"the padding */\n",
|
"the padding */\n",
|
||||||
from_size, from->name);
|
from_size, class_member__name(from));
|
||||||
}
|
}
|
||||||
} else if (from_was_last) {
|
} else if (from_was_last) {
|
||||||
class->type.size -= from_size + class->padding;
|
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)
|
if (verbose)
|
||||||
fprintf(fp, "/* Moving '%s:%u' from after '%s' to "
|
fprintf(fp, "/* Moving '%s:%u' from after '%s' to "
|
||||||
"after '%s:%u' */\n",
|
"after '%s:%u' */\n",
|
||||||
from->name, from->bit_size, from_prev->name,
|
class_member__name(from), from->bit_size,
|
||||||
dest->name, dest->bit_size);
|
class_member__name(from_prev),
|
||||||
|
class_member__name(dest), dest->bit_size);
|
||||||
/*
|
/*
|
||||||
* Remove 'from' from the list
|
* Remove 'from' from the list
|
||||||
*/
|
*/
|
||||||
|
@ -546,9 +548,10 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, "/* Demoting bitfield ('%s' ... '%s') "
|
fprintf(fp, "/* Demoting bitfield ('%s' ... '%s') "
|
||||||
"from '%s' to '%s' */\n",
|
"from '%s' to '%s' */\n",
|
||||||
bitfield_head->name, member->name,
|
class_member__name(bitfield_head),
|
||||||
tag__base_type(old_type_tag)->name,
|
class_member__name(member),
|
||||||
tag__base_type(new_type_tag)->name);
|
base_type__name(tag__base_type(old_type_tag)),
|
||||||
|
base_type__name(tag__base_type(new_type_tag)));
|
||||||
|
|
||||||
class__demote_bitfield_members(class,
|
class__demote_bitfield_members(class,
|
||||||
bitfield_head, member,
|
bitfield_head, member,
|
||||||
|
@ -593,9 +596,9 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
|
||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(fp, "/* Demoting bitfield ('%s') "
|
fprintf(fp, "/* Demoting bitfield ('%s') "
|
||||||
"from '%s' to '%s' */\n",
|
"from '%s' to '%s' */\n",
|
||||||
member->name,
|
class_member__name(member),
|
||||||
tag__base_type(old_type_tag)->name,
|
base_type__name(tag__base_type(old_type_tag)),
|
||||||
tag__base_type(new_type_tag)->name);
|
base_type__name(tag__base_type(new_type_tag)));
|
||||||
class__demote_bitfield_members(class,
|
class__demote_bitfield_members(class,
|
||||||
member, member,
|
member, member,
|
||||||
tag__base_type(old_type_tag),
|
tag__base_type(old_type_tag),
|
||||||
|
|
27
pahole.c
27
pahole.c
|
@ -228,7 +228,8 @@ static void print_classes(void (*formatter)(struct structure *s))
|
||||||
savings);
|
savings);
|
||||||
else
|
else
|
||||||
printf("%s(%d)%c%zd%c%zd%c%zd\n",
|
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,
|
orig_size, separator,
|
||||||
new_size, separator,
|
new_size, separator,
|
||||||
savings);
|
savings);
|
||||||
|
@ -368,8 +369,8 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
|
||||||
|
|
||||||
|
|
||||||
if (decl_exclude_prefix != NULL &&
|
if (decl_exclude_prefix != NULL &&
|
||||||
(tag->decl_file == NULL ||
|
(!tag->decl_file ||
|
||||||
strncmp(decl_exclude_prefix, tag->decl_file,
|
strncmp(decl_exclude_prefix, tag__decl_file(tag),
|
||||||
decl_exclude_prefix_len) == 0))
|
decl_exclude_prefix_len) == 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
@ -462,8 +463,8 @@ static void class__resize_LP(struct tag *tag, struct cu *cu)
|
||||||
case DW_TAG_base_type: {
|
case DW_TAG_base_type: {
|
||||||
struct base_type *bt = tag__base_type(type);
|
struct base_type *bt = tag__base_type(type);
|
||||||
|
|
||||||
if (strcmp(bt->name, "long int") != 0 &&
|
if (strcmp(base_type__name(bt), "long int") != 0 &&
|
||||||
strcmp(bt->name, "long unsigned int") != 0)
|
strcmp(base_type__name(bt), "long unsigned int") != 0)
|
||||||
break;
|
break;
|
||||||
/* fallthru */
|
/* 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),
|
* built with GNU C 4.3.0 20080130 (Red Hat 4.3.0-0.7),
|
||||||
* one was found, so just bail out.
|
* one was found, so just bail out.
|
||||||
*/
|
*/
|
||||||
if (bt->name == NULL)
|
if (!bt->name)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (strcmp(bt->name, "long int") == 0 ||
|
if (strcmp(base_type__name(bt), "long int") == 0 ||
|
||||||
strcmp(bt->name, "long unsigned int") == 0)
|
strcmp(base_type__name(bt), "long unsigned int") == 0)
|
||||||
bt->bit_size = word_size * 8;
|
bt->bit_size = word_size * 8;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -667,7 +668,8 @@ static void print_structs_with_pointer_to(const struct structure *s)
|
||||||
|
|
||||||
tag__assert_search_result(ctype);
|
tag__assert_search_result(ctype);
|
||||||
if (ctype->tag == DW_TAG_pointer_type && ctype->type == type)
|
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[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
struct cus *cus;
|
|
||||||
int err;
|
int err;
|
||||||
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
cus = cus__new();
|
if (dwarves__init(cacheline_size) || cus == NULL) {
|
||||||
if (cus == NULL) {
|
|
||||||
fputs("pahole: insufficient memory\n", stderr);
|
fputs("pahole: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -969,8 +970,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(cacheline_size);
|
|
||||||
|
|
||||||
if (word_size != 0)
|
if (word_size != 0)
|
||||||
cus__for_each_cu(cus, cu_fixup_word_size_iterator, NULL, NULL);
|
cus__for_each_cu(cus, cu_fixup_word_size_iterator, NULL, NULL);
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ int main(int argc, char *argv[])
|
||||||
int err;
|
int err;
|
||||||
struct cus *cus = cus__new();
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
if (cus == NULL) {
|
if (dwarves__init(0) || cus == NULL) {
|
||||||
fputs("pwdtags: insufficient memory\n", stderr);
|
fputs("pwdtags: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
cus__emit_tags(cus);
|
cus__emit_tags(cus);
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
6
pfunct.c
6
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
|
* FIXME: remove this check and try to fix the parameter abstract
|
||||||
* origin code someday...
|
* origin code someday...
|
||||||
*/
|
*/
|
||||||
if (function->name == NULL)
|
if (!function->name)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
name = function__name(function, cu);
|
name = function__name(function, cu);
|
||||||
|
@ -491,7 +491,7 @@ int main(int argc, char *argv[])
|
||||||
int err;
|
int err;
|
||||||
struct cus *cus = cus__new();
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
if (cus == NULL) {
|
if (dwarves__init(0) || cus == NULL) {
|
||||||
fputs("pfunct: insufficient memory\n", stderr);
|
fputs("pfunct: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -500,8 +500,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
|
|
||||||
cus__for_each_cu(cus, cu_unique_iterator, NULL, NULL);
|
cus__for_each_cu(cus, cu_unique_iterator, NULL, NULL);
|
||||||
|
|
||||||
if (show_total_inline_expansion_stats)
|
if (show_total_inline_expansion_stats)
|
||||||
|
|
|
@ -313,7 +313,7 @@ int main(int argc, char *argv[])
|
||||||
int err;
|
int err;
|
||||||
struct cus *cus = cus__new();
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
if (cus == NULL) {
|
if (dwarves__init(0) || cus == NULL) {
|
||||||
fputs("pglobal: insufficient memory\n", stderr);
|
fputs("pglobal: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -322,8 +322,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
|
|
||||||
if (walk_var) {
|
if (walk_var) {
|
||||||
cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL);
|
cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL);
|
||||||
twalk(tree, declaration_action__walk);
|
twalk(tree, declaration_action__walk);
|
||||||
|
|
|
@ -135,7 +135,7 @@ static int cu_refcnt_iterator(struct cu *cu, void *cookie)
|
||||||
static int lost_iterator(struct tag *tag, struct cu *cu,
|
static int lost_iterator(struct tag *tag, struct cu *cu,
|
||||||
void *cookie __unused)
|
void *cookie __unused)
|
||||||
{
|
{
|
||||||
if (tag->refcnt == 0 && tag->decl_file != NULL) {
|
if (tag->refcnt == 0 && tag->decl_file) {
|
||||||
tag__fprintf(tag, cu, NULL, stdout);
|
tag__fprintf(tag, cu, NULL, stdout);
|
||||||
puts(";\n");
|
puts(";\n");
|
||||||
}
|
}
|
||||||
|
@ -152,7 +152,7 @@ int main(int argc, char *argv[])
|
||||||
int err;
|
int err;
|
||||||
struct cus *cus = cus__new();
|
struct cus *cus = cus__new();
|
||||||
|
|
||||||
if (cus == NULL) {
|
if (dwarves__init(0) || cus == NULL) {
|
||||||
fputs("prefcnt: insufficient memory\n", stderr);
|
fputs("prefcnt: insufficient memory\n", stderr);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -161,7 +161,6 @@ int main(int argc, char *argv[])
|
||||||
if (err != 0)
|
if (err != 0)
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
dwarves__init(0);
|
|
||||||
cus__for_each_cu(cus, cu_refcnt_iterator, NULL, NULL);
|
cus__for_each_cu(cus, cu_refcnt_iterator, NULL, NULL);
|
||||||
cus__for_each_cu(cus, cu_lost_iterator, NULL, NULL);
|
cus__for_each_cu(cus, cu_lost_iterator, NULL, NULL);
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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_ */
|
5
syscse.c
5
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"
|
printf("\t%s\t$a%d, $a%d, 0"
|
||||||
"\t/* zero extend $a%d(%s %s) from %zd to 64-bit */\n",
|
"\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)
|
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);
|
struct base_type *bt = tag__base_type(type);
|
||||||
|
|
||||||
if (bt->bit_size < 64 &&
|
if (bt->bit_size < 64 &&
|
||||||
strncmp(bt->name, "unsigned", 8) == 0) {
|
strncmp(base_type__name(bt), "unsigned", 8) == 0) {
|
||||||
if (!needs_wrapper) {
|
if (!needs_wrapper) {
|
||||||
printf("wrap_%s:\n", name);
|
printf("wrap_%s:\n", name);
|
||||||
needs_wrapper = 1;
|
needs_wrapper = 1;
|
||||||
|
|
Loading…
Reference in New Issue