dwarves: Remove some more DWARF details from the core

Had to be a big sweeping change, but the regression tests shows just
improvements :-)

Now we stop using an id in struct tag, only storing the type, that now
uses 16 bits only, as CTF does.

Each format loader has to go on adding the types to the core, that
figures out if it is a tag that can be on the tag->type field
(tag__is_tag_type).

Formats that already have the types separated and in sequence, such as
CTF, just ask the core to insert in the types_table directly with its
original ID.

For DWARF, we ask the core to put it on the table, in sequence, and return the
index, that is then stashed with the DWARF specific info (original id, type,
decl_line, etc) and hashed by the original id. Later we recode everything,
looking up via the original type, getting the small_id to put on the tag->type.

The underlying debugging info not needed by the core is stashed in tag->priv,
and the DWARF loader now just allocates sizeof(struct dwarf_tag) at the end of
the core tag and points it there, and makes that info available thru
cu->orig_info. In the future we can ask, when loading a cu, that this info be
trown away, so that we reduce the memory footprint for big multi-cu files such
as the Linux kernel.

There is also a routine to ask for inserting a NULL, as we still have
bugs in the CTF decoding and thus some entries are being lost, to avoid
using an undefined pointer when traversing the types_table the ctf
loader puts a NULL there via cu__table_nullify_type_entry() and then
cu__for_each_type skips those.

There is some more cleanups for leftovers that I avoided cleaning to
reduce this changeset.

And also while doing this I saw that enums can appear without any
enumerators and that an array with DW_TAG_GNU_vector is actually a
different tag, encoded this way till we get to DWARF4 ;-)

So now we don't have to lookup on a hash table looking for DWARF
offsets, we can do the more sensible thing of just indexing the
types_tags array.

Now to do some cleanups and try to get the per cu encoder done. Then
order all the cus per number of type entries, pick the one with more,
then go on merging/recoding the types of the others and putting the
parent linkage in place.

Just to show the extent of the changes:

$ codiff /tmp/libdwarves.so.1.0.0 build/libdwarves.so.1.0.0
/home/acme/git/pahole/dwarves.c:
  struct cu                                      | -4048
  struct tag                                     |  -32
  struct ptr_to_member_type                      |  -32
  struct namespace                               |  -32
  struct type                                    |  -32
  struct class                                   |  -32
  struct base_type                               |  -32
  struct array_type                              |  -32
  struct class_member                            |  -32
  struct lexblock                                |  -32
  struct ftype                                   |  -32
  struct function                                |  -64
  struct parameter                               |  -32
  struct variable                                |  -32
  struct inline_expansion                        |  -32
  struct label                                   |  -32
  struct enumerator                              |  -32
 17 structs changed
  tag__follow_typedef                            |   +3
  tag__fprintf_decl_info                         |  +25
  array_type__fprintf                            |   +6
  type__name                                     | -126
  type__find_first_biggest_size_base_type_member |   -3
  typedef__fprintf                               |  +16
  imported_declaration__fprintf                  |   +6
  imported_module__fprintf                       |   +3
  cu__new                                        |  +26
  cu__delete                                     |  +26
  hashtags__hash                                 |  -65
  hash_64                                        | -124
  hlist_add_head                                 |  -78
  hashtags__find                                 | -157
  cu__hash                                       |  -80
  cu__add_tag                                    |  +20
  tag__prefix                                    |   -3
  cu__find_tag_by_id                             |   -2
  cu__find_type_by_id                            |   -3
  cu__find_first_typedef_of_type                 |  +38
  cu__find_base_type_by_name                     |  +68
  cu__find_base_type_by_name_and_size            |  +72
  cu__find_struct_by_name                        |  +59
  cus__find_struct_by_name                       |   +8
  cus__find_tag_by_id                            |   +5
  cus__find_cu_by_name                           |   -6
  lexblock__find_tag_by_id                       | -173
  cu__find_variable_by_id                        | -197
  list__find_tag_by_id                           | -308
  cu__find_parameter_by_id                       |  -60
  tag__ptr_name                                  |   +6
  tag__name                                      |  +15
  variable__type                                 |  +13
  variable__name                                 |   +7
  class_member__size                             |   +6
  parameter__name                                | -119
  tag__parameter                                 |  -14
  parameter__type                                | -143
  type__fprintf                                  |  -29
  union__fprintf                                 |   +6
  class__add_vtable_entry                        |   -9
  type__add_member                               |   -6
  type__clone_members                            |   -3
  enumeration__add                               |   -6
  function__name                                 | -156
  ftype__has_parm_of_type                        |  -39
  class__find_holes                              |  -27
  class__has_hole_ge                             |   -3
  type__nr_members_of_type                       |   +3
  lexblock__account_inline_expansions            |   +3
  cu__account_inline_expansions                  |  -18
  ftype__fprintf_parms                           |  +46
  function__tag_fprintf                          |  +24
  lexblock__fprintf                              |   -6
  ftype__fprintf                                 |   +3
  function__fprintf_stats                        |  -18
  function__size                                 |   -6
  class__vtable_fprintf                          |  -11
  class__fprintf                                 |  -21
  tag__fprintf                                   |  -35
 60 functions changed, 513 bytes added, 2054 bytes removed, diff: -1541

/home/acme/git/pahole/ctf_loader.c:
  struct ctf_short_type      |   +0
 14 structs changed
  type__init                 |  -14
  type__new                  |   -9
  class__new                 |  -12
  create_new_base_type       |   -7
  create_new_base_type_float |   -7
  create_new_array           |   -8
  create_new_subroutine_type |   -9
  create_full_members        |  -18
  create_short_members       |  -18
  create_new_class           |   +1
  create_new_union           |   +1
  create_new_enumeration     |  -19
  create_new_forward_decl    |   -2
  create_new_typedef         |   +3
  create_new_tag             |   -5
  load_types                 |  +16
  class__fixup_ctf_bitfields |   -3
 17 functions changed, 21 bytes added, 131 bytes removed, diff: -110

/home/acme/git/pahole/dwarf_loader.c:
 17 structs changed
  zalloc                           |  -56
  tag__init                        |   +3
  array_type__new                  |  +20
  type__init                       |  -24
  class_member__new                |  +46
  inline_expansion__new            |  +12
  class__new                       |  +81
  lexblock__init                   |  +19
  function__new                    |  +43
  die__create_new_array            |  +20
  die__create_new_parameter        |   +4
  die__create_new_label            |   +4
  die__create_new_subroutine_type  | +113
  die__create_new_enumeration      |  -21
  die__process_class               |  +79
  die__process_namespace           |  +76
  die__create_new_inline_expansion |   +4
  die__process_function            | +147
  __die__process_tag               |  +34
  die__process_unit                |  +56
  die__process                     |  +90
 21 functions changed, 851 bytes added, 101 bytes removed, diff: +750

/home/acme/git/pahole/dwarves.c:
  struct ptr_table             |  +16
  struct cu_orig_info          |  +32
 2 structs changed
  tag__decl_line               |  +68
  tag__decl_file               |  +70
  tag__orig_id                 |  +71
  ptr_table__init              |  +46
  ptr_table__exit              |  +37
  ptr_table__add               | +183
  ptr_table__add_with_id       | +165
  ptr_table__entry             |  +64
  cu__table_add_tag            | +171
  cu__table_nullify_type_entry |  +38
 10 functions changed, 913 bytes added, diff: +913

/home/acme/git/pahole/ctf_loader.c:
 2 structs changed
  tag__alloc          |  +52
 1 function changed, 52 bytes added, diff: +52

/home/acme/git/pahole/dwarf_loader.c:
  struct dwarf_tag                       |  +48
  struct dwarf_cu                        | +4104
 4 structs changed
  dwarf_cu__init                         |  +83
  hashtags__hash                         |  +61
  hash_64                                | +124
  hlist_add_head                         |  +78
  hashtags__find                         | +161
  cu__hash                               |  +95
  tag__is_tag_type                       | +171
  tag__is_type                           |  +85
  tag__is_union                          |  +28
  tag__is_struct                         |  +57
  tag__is_typedef                        |  +28
  tag__is_enumeration                    |  +28
  dwarf_cu__find_tag_by_id               |  +56
  dwarf_cu__find_type_by_id              |  +63
  tag__alloc                             | +114
  __tag__print_type_not_found            | +108
  namespace__recode_dwarf_types          | +346
  tag__namespace                         |  +14
  tag__has_namespace                     |  +86
  tag__is_namespace                      |  +28
  type__recode_dwarf_specification       | +182
  tag__type                              |  +14
  __tag__print_abstract_origin_not_found | +105
  ftype__recode_dwarf_types              | +322
  tag__ftype                             |  +14
  tag__parameter                         |  +14
  lexblock__recode_dwarf_types           | +736
  tag__lexblock                          |  +14
  tag__label                             |  +14
  tag__recode_dwarf_type                 | +766
  tag__ptr_to_member_type                |  +14
  cu__recode_dwarf_types_table           |  +88
  cu__recode_dwarf_types                 |  +48
  dwarf_tag__decl_file                   |  +77
  strings__ptr                           |  +33
  dwarf_tag__decl_line                   |  +59
  dwarf_tag__orig_id                     |  +59
  dwarf_tag__orig_type                   |  +59
 38 functions changed, 4432 bytes added, diff: +4432

build/libdwarves.so.1.0.0:
 147 functions changed, 6782 bytes added, 2286 bytes removed, diff: +4496

Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2009-03-05 20:29:35 -03:00
parent 2118fae5b0
commit c178f4698d
12 changed files with 1183 additions and 603 deletions

View File

@ -249,7 +249,8 @@ static void diff_struct(const struct cu *new_cu, struct class *structure,
if (class__size(structure) == 0 || class__name(structure, cu) == NULL)
return;
new_tag = cu__find_struct_by_name(new_cu, class__name(structure, cu), 0);
new_tag = cu__find_struct_by_name(new_cu, class__name(structure, cu),
0, NULL);
if (new_tag == NULL)
return;
@ -334,7 +335,8 @@ static int find_new_classes_iterator(struct tag *tag, struct cu *cu, void *old_c
if (class__size(class) == 0)
return 0;
if (cu__find_struct_by_name(old_cu, class__name(class, cu), 0) != NULL)
if (cu__find_struct_by_name(old_cu, class__name(class, cu), 0,
NULL) != NULL)
return 0;
class->priv = diff_info__new(NULL, NULL, 1);
@ -367,8 +369,7 @@ static int cu_find_new_tags_iterator(struct cu *new_cu, void *old_cus)
if (old_cu != NULL && cu__same_build_id(old_cu, new_cu))
return 0;
cu__for_each_tag(new_cu, find_new_tags_iterator,
old_cu, NULL);
cu__for_each_tag(new_cu, find_new_tags_iterator, old_cu, NULL);
return 0;
}

View File

@ -37,6 +37,16 @@ static void *zalloc(const size_t size)
return s;
}
static void *tag__alloc(const size_t size)
{
struct tag *self = zalloc(size);
if (self != NULL)
self->top_level = 1;
return self;
}
static void oom(const char *msg)
{
fprintf(stderr, "libclasses: out of memory(%s)\n", msg);
@ -326,7 +336,7 @@ static void dump_funcs(struct ctf_state *sp)
static struct base_type *base_type__new(const char *name, size_t size)
{
struct base_type *self = zalloc(sizeof(*self));
struct base_type *self = tag__alloc(sizeof(*self));
if (self != NULL) {
self->name = strings__add(strings, name);
@ -335,34 +345,32 @@ static struct base_type *base_type__new(const char *name, size_t size)
return self;
}
static void type__init(struct type *self, uint16_t tag, unsigned int id,
static void type__init(struct type *self, uint16_t tag,
const char *name, size_t size)
{
INIT_LIST_HEAD(&self->node);
INIT_LIST_HEAD(&self->namespace.tags);
self->size = size;
self->namespace.tag.id = id;
self->namespace.tag.tag = tag;
self->namespace.name = strings__add(strings, name[0] == '(' ? NULL : name);
}
static struct type *type__new(uint16_t tag, unsigned int id,
const char *name, size_t size)
static struct type *type__new(uint16_t tag, const char *name, size_t size)
{
struct type *self = zalloc(sizeof(*self));
struct type *self = tag__alloc(sizeof(*self));
if (self != NULL)
type__init(self, tag, id, name, size);
type__init(self, tag, name, size);
return self;
}
static struct class *class__new(const char *name, unsigned int id, size_t size)
static struct class *class__new(const char *name, size_t size)
{
struct class *self = zalloc(sizeof(*self));
struct class *self = tag__alloc(sizeof(*self));
if (self != NULL) {
type__init(&self->type, DW_TAG_structure_type, id, name, size);
type__init(&self->type, DW_TAG_structure_type, name, size);
INIT_LIST_HEAD(&self->vtable);
}
@ -371,7 +379,7 @@ static struct class *class__new(const char *name, unsigned int id, size_t size)
static int create_new_base_type(struct ctf_state *sp, void *ptr,
int vlen __unused, struct ctf_full_type *tp,
unsigned int id)
long id)
{
uint32_t *enc = ptr, name_idx;
char name[64], *buf = name;
@ -393,8 +401,7 @@ static int create_new_base_type(struct ctf_state *sp, void *ptr,
oom("base_type__new");
base->tag.tag = DW_TAG_base_type;
base->tag.id = id;
cu__add_tag(sp->cu, &base->tag);
cu__add_tag(sp->cu, &base->tag, &id);
return sizeof(*enc);
}
@ -402,7 +409,7 @@ static int create_new_base_type(struct ctf_state *sp, void *ptr,
static int create_new_base_type_float(struct ctf_state *sp, void *ptr,
int vlen __unused,
struct ctf_full_type *tp,
unsigned int id)
long id)
{
uint32_t *enc = ptr, eval;
char name[64];
@ -417,8 +424,7 @@ static int create_new_base_type_float(struct ctf_state *sp, void *ptr,
oom("base_type__new");
base->tag.tag = DW_TAG_base_type;
base->tag.id = id;
cu__add_tag(sp->cu, &base->tag);
cu__add_tag(sp->cu, &base->tag, &id);
return sizeof(*enc);
}
@ -426,10 +432,10 @@ static int create_new_base_type_float(struct ctf_state *sp, void *ptr,
static int create_new_array(struct ctf_state *sp, void *ptr,
int vlen __unused,
struct ctf_full_type *tp __unused,
unsigned int id)
long id)
{
struct ctf_array *ap = ptr;
struct array_type *self = zalloc(sizeof(*self));
struct array_type *self = tag__alloc(sizeof(*self));
if (self == NULL)
oom("array_type");
@ -444,23 +450,22 @@ static int create_new_array(struct ctf_state *sp, void *ptr,
self->nr_entries[0] = ctf__get32(sp->ctf, &ap->ctf_array_nelems);
self->tag.tag = DW_TAG_array_type;
self->tag.id = id;
self->tag.type = ctf__get16(sp->ctf, &ap->ctf_array_type);
cu__add_tag(sp->cu, &self->tag);
cu__add_tag(sp->cu, &self->tag, &id);
return sizeof(*ap);
}
static int create_new_subroutine_type(struct ctf_state *sp, void *ptr,
int vlen, struct ctf_full_type *tp,
unsigned int id)
long id)
{
uint16_t *args = ptr;
uint16_t i;
const char *name = ctf_string(ctf__get32(sp->ctf, &tp->base.ctf_name), sp);
unsigned int type = ctf__get16(sp->ctf, &tp->base.ctf_type);
struct function *self = zalloc(sizeof(*self));
struct function *self = tag__alloc(sizeof(*self));
if (self == NULL)
oom("function__new");
@ -470,12 +475,11 @@ static int create_new_subroutine_type(struct ctf_state *sp, void *ptr,
INIT_LIST_HEAD(&self->tool_node);
INIT_LIST_HEAD(&self->proto.parms);
self->proto.tag.tag = DW_TAG_subroutine_type;
self->proto.tag.id = id;
self->proto.tag.type = type;
INIT_LIST_HEAD(&self->lexblock.tags);
for (i = 0; i < vlen; i++) {
struct parameter *p = zalloc(sizeof(*p));
struct parameter *p = tag__alloc(sizeof(*p));
p->tag.tag = DW_TAG_formal_parameter;
p->tag.type = ctf__get16(sp->ctf, &args[i]);
@ -490,7 +494,7 @@ static int create_new_subroutine_type(struct ctf_state *sp, void *ptr,
if (vlen & 0x2)
vlen += 0x2;
cu__add_tag(sp->cu, &self->proto.tag);
cu__add_tag(sp->cu, &self->proto.tag, &id);
return vlen;
}
@ -516,7 +520,6 @@ static unsigned long create_full_members(struct ctf_state *sp, void *ptr,
member->offset = bit_offset / 8;
member->bit_offset = bit_offset % 8;
type__add_member(class, member);
cu__hash(sp->cu, &member->tag);
}
return sizeof(*mp);
@ -543,7 +546,6 @@ static unsigned long create_short_members(struct ctf_state *sp, void *ptr,
member->bit_offset = bit_offset % 8;
type__add_member(class, member);
cu__hash(sp->cu, &member->tag);
}
return sizeof(*mp);
@ -551,11 +553,11 @@ static unsigned long create_short_members(struct ctf_state *sp, void *ptr,
static int create_new_class(struct ctf_state *sp, void *ptr,
int vlen, struct ctf_full_type *tp,
uint64_t size, unsigned int id)
uint64_t size, long id)
{
unsigned long member_size;
const char *name = ctf_string(ctf__get32(sp->ctf, &tp->base.ctf_name), sp);
struct class *self = class__new(name, id, size);
struct class *self = class__new(name, size);
if (size >= CTF_SHORT_MEMBER_LIMIT) {
member_size = create_full_members(sp, ptr, vlen, &self->type);
@ -563,18 +565,18 @@ static int create_new_class(struct ctf_state *sp, void *ptr,
member_size = create_short_members(sp, ptr, vlen, &self->type);
}
cu__add_tag(sp->cu, &self->type.namespace.tag);
cu__add_tag(sp->cu, &self->type.namespace.tag, &id);
return (vlen * member_size);
}
static int create_new_union(struct ctf_state *sp, void *ptr,
int vlen, struct ctf_full_type *tp,
uint64_t size, unsigned int id)
uint64_t size, long id)
{
unsigned long member_size;
const char *name = ctf_string(ctf__get32(sp->ctf, &tp->base.ctf_name), sp);
struct type *self = type__new(DW_TAG_union_type, id, name, size);
struct type *self = type__new(DW_TAG_union_type, name, size);
if (size >= CTF_SHORT_MEMBER_LIMIT) {
member_size = create_full_members(sp, ptr, vlen, self);
@ -582,7 +584,7 @@ static int create_new_union(struct ctf_state *sp, void *ptr,
member_size = create_short_members(sp, ptr, vlen, self);
}
cu__add_tag(sp->cu, &self->namespace.tag);
cu__add_tag(sp->cu, &self->namespace.tag, &id);
return (vlen * member_size);
}
@ -590,7 +592,7 @@ static int create_new_union(struct ctf_state *sp, void *ptr,
static struct enumerator *enumerator__new(const char *name,
uint32_t value)
{
struct enumerator *self = zalloc(sizeof(*self));
struct enumerator *self = tag__alloc(sizeof(*self));
if (self != NULL) {
self->name = strings__add(strings, name);
@ -603,11 +605,11 @@ static struct enumerator *enumerator__new(const char *name,
static int create_new_enumeration(struct ctf_state *sp, void *ptr,
int vlen, struct ctf_full_type *tp,
unsigned int id)
long id)
{
struct ctf_enum *ep = ptr;
uint16_t i;
struct type *enumeration = type__new(DW_TAG_enumeration_type, id,
struct type *enumeration = type__new(DW_TAG_enumeration_type,
ctf_string(ctf__get32(sp->ctf,
&tp->base.ctf_name), sp),
sizeof(int)); /* FIXME: is this always the case? */
@ -624,32 +626,31 @@ static int create_new_enumeration(struct ctf_state *sp, void *ptr,
oom("enumerator__new");
enumeration__add(enumeration, enumerator);
cu__hash(sp->cu, &enumerator->tag);
}
cu__add_tag(sp->cu, &enumeration->namespace.tag);
cu__add_tag(sp->cu, &enumeration->namespace.tag, &id);
return (vlen * sizeof(*ep));
}
static int create_new_forward_decl(struct ctf_state *sp, void *ptr __unused,
int vlen __unused, struct ctf_full_type *tp,
uint64_t size, unsigned int id)
uint64_t size, long id)
{
char *name = ctf_string(ctf__get32(sp->ctf, &tp->base.ctf_name), sp);
struct class *self = class__new(name, id, size);
struct class *self = class__new(name, size);
if (self == NULL)
oom("class foward decl");
self->type.declaration = 1;
cu__add_tag(sp->cu, &self->type.namespace.tag);
cu__add_tag(sp->cu, &self->type.namespace.tag, &id);
return 0;
}
static int create_new_typedef(struct ctf_state *sp, int type,
void *ptr __unused, int vlen __unused,
struct ctf_full_type *tp,
uint64_t size, unsigned int id)
uint64_t size, long id)
{
const char *name = ctf_string(ctf__get32(sp->ctf, &tp->base.ctf_name), sp);
unsigned int type_id = ctf__get16(sp->ctf, &tp->base.ctf_type);
@ -663,18 +664,18 @@ static int create_new_typedef(struct ctf_state *sp, int type,
return 0;
}
self = type__new(tag, id, name, size);
self = type__new(tag, name, size);
if (self == NULL)
oom("type__new");
self->namespace.tag.type = type_id;
cu__add_tag(sp->cu, &self->namespace.tag);
cu__add_tag(sp->cu, &self->namespace.tag, &id);
return 0;
}
static int create_new_tag(struct ctf_state *sp, int type,
void *ptr __unused, int vlen __unused,
struct ctf_full_type *tp, unsigned int id)
struct ctf_full_type *tp, long id)
{
unsigned int type_id = ctf__get16(sp->ctf, &tp->base.ctf_type);
struct tag *self = zalloc(sizeof(*self));
@ -692,9 +693,8 @@ static int create_new_tag(struct ctf_state *sp, int type,
return 0;
}
self->id = id;
self->type = type_id;
cu__add_tag(sp->cu, self);
cu__add_tag(sp->cu, self, &id);
return 0;
}
@ -762,6 +762,7 @@ static void load_types(struct ctf_state *sp)
type == CTF_TYPE_KIND_RESTRICT) {
vlen = create_new_tag(sp, type, ptr, vlen, type_ptr, type_index);
} else if (type == CTF_TYPE_KIND_UNKN) {
cu__table_nullify_type_entry(sp->cu, type_index);
printf("CTF: [%#6x] %1d Unknown\n", type_index, CTF_ISROOT(val));
vlen = 0;
} else {
@ -825,10 +826,10 @@ static int class__fixup_ctf_bitfields(struct tag *self, struct cu *cu)
if (last_offset == -1)
last_offset = pos->offset;
struct tag *fixed_tag;
fixed_tag = cu__find_base_type_by_name_and_size(cu, base_type__name(bt),
bit_size);
if (fixed_tag == NULL) {
uint16_t fixed_tag_id;
if (cu__find_base_type_by_name_and_size(cu, base_type__name(bt),
bit_size, &fixed_tag_id) == NULL) {
fprintf(stderr,
"%s: BRAIN FART ALERT!: class: %s, member: %s\n",
__func__, type__name(type_self, cu),
@ -837,7 +838,7 @@ static int class__fixup_ctf_bitfields(struct tag *self, struct cu *cu)
}
pos->offset = last_offset;
pos->tag.type = fixed_tag->id;
pos->tag.type = fixed_tag_id;
pos->bit_size = bt->bit_size;
pos->bit_offset = bit_offset;
bit_offset += bt->bit_size;

180
ctracer.c
View File

@ -165,42 +165,26 @@ static int methods__add(void **table, const char *str)
return 0;
}
static void method__add(struct cu *cu, struct function *function)
static void method__add(struct cu *cu, struct function *function, uint32_t id)
{
list_add(&function->tool_node, &cu->tool_list);
function->priv = (void *)(long)id;
}
/*
* We want just the DW_TAG_subprogram tags that have as one of its parameters
* a pointer to the specified "class" (a struct, unions can be added later).
*/
static struct tag *function__filter(struct tag *tag, struct cu *cu, void *cookie)
static struct function *function__filter(struct function *function,
struct cu *cu, uint16_t target_type_id)
{
struct function *function;
if (tag->tag != DW_TAG_subprogram)
return NULL;
function = tag__function(tag);
if (function__inlined(function) ||
function->abstract_origin != 0 ||
!list_empty(&function->tool_node) ||
!ftype__has_parm_of_type(&function->proto, cookie, cu))
!ftype__has_parm_of_type(&function->proto, target_type_id, cu))
return NULL;
return tag;
}
/*
* Add the function to the list of methods since it matches function__filter
* criteria.
*/
static int find_methods_iterator(struct tag *tag, struct cu *cu,
void *cookie __unused)
{
struct function *function = tag__function(tag);
method__add(cu, function);
return 0;
return function;
}
/*
@ -210,14 +194,22 @@ static int find_methods_iterator(struct tag *tag, struct cu *cu,
*/
static int cu_find_methods_iterator(struct cu *cu, void *cookie)
{
struct tag *target = cu__find_struct_by_name(cu, cookie, 0);
uint16_t target_type_id;
uint32_t function_id;
struct function *function;
struct tag *target = cu__find_struct_by_name(cu, cookie, 0,
&target_type_id);
INIT_LIST_HEAD(&cu->tool_list);
if (target == NULL)
return 0;
return cu__for_each_tag(cu, find_methods_iterator, target, function__filter);
cu__for_each_function(cu, function_id, function)
if (function__filter(function, cu, target_type_id))
method__add(cu, function, function_id);
return 0;
}
static struct class_member *class_member__bitfield_tail(struct class_member *head,
@ -489,9 +481,10 @@ static int class__emit_ostra_converter(struct tag *tag_self,
* We want just the DW_TAG_structure_type tags that have a member that is a pointer
* to the target class.
*/
static struct tag *pointer_filter(struct tag *tag, struct cu *cu, void *target_tag)
static struct tag *pointer_filter(struct tag *tag, struct cu *cu,
uint16_t target_type_id)
{
struct type *type, *target_type;
struct type *type;
struct class_member *pos;
const char *class_name;
@ -506,41 +499,36 @@ static struct tag *pointer_filter(struct tag *tag, struct cu *cu, void *target_t
if (class_name == NULL || structures__find(&pointers, class_name))
return NULL;
target_type = tag__type(target_tag);
type__for_each_member(type, pos) {
struct tag *ctype = cu__find_type_by_id(cu, pos->tag.type);
tag__assert_search_result(ctype);
if (ctype->tag == DW_TAG_pointer_type && ctype->type == target_type->namespace.tag.id)
if (ctype->tag == DW_TAG_pointer_type &&
ctype->type == target_type_id)
return tag;
}
return NULL;
}
/*
* Add the struct to the list of pointers since it matches pointer_filter
* criteria.
*/
static int find_pointers_iterator(struct tag *tag, struct cu *cu,
void *cookie __unused)
{
structures__add(&pointers, tag, cu);
return 0;
}
/*
* Iterate thru all the tags in the compilation unit, looking for classes
* that have as one member that is a pointer to the target type.
*/
static int cu_find_pointers_iterator(struct cu *cu, void *class_name)
{
struct tag *target = cu__find_struct_by_name(cu, class_name, 0);
uint16_t target_type_id, id;
struct tag *target = cu__find_struct_by_name(cu, class_name, 0,
&target_type_id), *pos;
if (target == NULL)
return 0;
return cu__for_each_tag(cu, find_pointers_iterator, target, pointer_filter);
cu__for_each_type(cu, id, pos)
if (pointer_filter(pos, cu, target_type_id))
structures__add(&pointers, pos, cu);
return 0;
}
static void class__find_pointers(const char *class_name)
@ -552,9 +540,10 @@ static void class__find_pointers(const char *class_name)
* We want just the DW_TAG_structure_type tags that have as its first member
* a struct of type target.
*/
static struct tag *alias_filter(struct tag *tag, struct cu *cu, void *target_tag)
static struct tag *alias_filter(struct tag *tag,
struct cu *cu, uint16_t target_type_id)
{
struct type *type, *target_type;
struct type *type;
struct class_member *first_member;
if (!tag__is_struct(tag))
@ -566,8 +555,7 @@ static struct tag *alias_filter(struct tag *tag, struct cu *cu, void *target_tag
first_member = list_first_entry(&type->namespace.tags,
struct class_member, tag.node);
target_type = tag__type(target_tag);
if (first_member->tag.type != target_type->namespace.tag.id)
if (first_member->tag.type != target_type_id)
return NULL;
if (structures__find(&aliases, class__name(tag__class(tag), cu)))
@ -578,45 +566,41 @@ static struct tag *alias_filter(struct tag *tag, struct cu *cu, void *target_tag
static void class__find_aliases(const char *class_name);
/*
* Add the struct to the list of aliases since it matches alias_filter
* criteria.
*/
static int find_aliases_iterator(struct tag *tag, struct cu *cu,
void *cookie __unused)
{
const char *alias_name = class__name(tag__class(tag), cu);
structures__add(&aliases, tag, cu);
/*
* Now find aliases to this alias, e.g.:
*
* struct tcp_sock {
* struct inet_connection_sock {
* struct inet_sock {
* struct sock {
* }
* }
* }
* }
*/
class__find_aliases(alias_name);
return 0;
}
/*
* Iterate thru all the tags in the compilation unit, looking for classes
* that have as its first member the specified "class" (struct).
*/
static int cu_find_aliases_iterator(struct cu *cu, void *class_name)
{
struct tag *target = cu__find_struct_by_name(cu, class_name, 0);
uint16_t target_type_id, id;
struct tag *target = cu__find_struct_by_name(cu, class_name, 0,
&target_type_id), *pos;
if (target == NULL)
return 0;
return cu__for_each_tag(cu, find_aliases_iterator, target, alias_filter);
cu__for_each_type(cu, id, pos) {
if (alias_filter(pos, cu, target_type_id)) {
const char *alias_name = class__name(tag__class(pos), cu);
structures__add(&aliases, pos, cu);
/*
* Now find aliases to this alias, e.g.:
*
* struct tcp_sock {
* struct inet_connection_sock {
* struct inet_sock {
* struct sock {
* }
* }
* }
* }
*/
class__find_aliases(alias_name);
}
}
return 0;
}
static void class__find_aliases(const char *class_name)
@ -688,8 +672,9 @@ out:
* This marks the function entry, function__emit_kretprobes will emit the
* probe for the function exit.
*/
static int function__emit_probes(struct function *self, const struct cu *cu,
const struct tag *target, int probe_type,
static int function__emit_probes(struct function *self, uint32_t function_id,
const struct cu *cu,
const uint16_t target_type_id, int probe_type,
const char *member)
{
struct parameter *pos;
@ -711,11 +696,8 @@ static int function__emit_probes(struct function *self, const struct cu *cu,
struct tag *type = cu__find_type_by_id(cu, pos->tag.type);
tag__assert_search_result(type);
if (type->tag != DW_TAG_pointer_type)
continue;
type = cu__find_type_by_id(cu, type->type);
if (type == NULL || type->id != target->id)
if (type->tag != DW_TAG_pointer_type ||
type->type != target_type_id)
continue;
if (member != NULL)
@ -723,9 +705,9 @@ static int function__emit_probes(struct function *self, const struct cu *cu,
parameter__name(pos, cu));
fprintf(fp_methods,
"\tctracer__method_hook(%d, %#llx, $%s%s%s, %zd);\n",
"\tctracer__method_hook(%d, %d, $%s%s%s, %zd);\n",
probe_type,
(unsigned long long)self->proto.tag.id,
function_id,
parameter__name(pos, cu),
member ? "->" : "", member ?: "",
class__size(mini_class));
@ -744,16 +726,18 @@ static int function__emit_probes(struct function *self, const struct cu *cu,
*/
static int cu_emit_probes_iterator(struct cu *cu, void *cookie)
{
struct tag *target = cu__find_struct_by_name(cu, cookie, 0);
uint16_t target_type_id;
struct tag *target = cu__find_struct_by_name(cu, cookie, 0, &target_type_id);
struct function *pos;
tag__assert_search_result(target);
list_for_each_entry(pos, &cu->tool_list, tool_node) {
uint32_t function_id = (long)pos->priv;
if (methods__add(&probes_emitted, function__name(pos, cu)) != 0)
continue;
pos->priv = (void *)1; /* Mark as visited, for the table iterator */
function__emit_probes(pos, cu, target, 0, NULL); /* entry */
function__emit_probes(pos, cu, target, 1, NULL); /* exit */
function__emit_probes(pos, function_id, cu, target_type_id, 0, NULL); /* entry */
function__emit_probes(pos, function_id, cu, target_type_id, 1, NULL); /* exit */
}
return 0;
@ -765,6 +749,7 @@ static int cu_emit_probes_iterator(struct cu *cu, void *cookie)
*/
static int cu_emit_pointer_probes_iterator(struct cu *cu, void *cookie)
{
uint16_t target_type_id, pointer_id;
struct tag *target, *pointer;
struct function *pos_tag;
struct class_member *pos_member;
@ -773,8 +758,8 @@ static int cu_emit_pointer_probes_iterator(struct cu *cu, void *cookie)
if (list_empty(&cu->tool_list))
return 0;
target = cu__find_struct_by_name(cu, class_name, 1);
pointer = cu__find_struct_by_name(cu, cookie, 0);
target = cu__find_struct_by_name(cu, class_name, 1, &target_type_id);
pointer = cu__find_struct_by_name(cu, cookie, 0, &pointer_id);
tag__assert_search_result(target);
tag__assert_search_result(pointer);
@ -783,18 +768,19 @@ static int cu_emit_pointer_probes_iterator(struct cu *cu, void *cookie)
struct tag *ctype = cu__find_type_by_id(cu, pos_member->tag.type);
tag__assert_search_result(ctype);
if (ctype->tag == DW_TAG_pointer_type && ctype->type == target->id)
if (ctype->tag == DW_TAG_pointer_type && ctype->type == target_type_id)
break;
}
list_for_each_entry(pos_tag, &cu->tool_list, tool_node) {
uint32_t function_id = (long)pos_tag->priv;
if (methods__add(&probes_emitted, function__name(pos_tag, cu)) != 0)
continue;
pos_tag->priv = (void *)1; /* Mark as visited, for the table iterator */
function__emit_probes(pos_tag, cu, pointer, 0,
function__emit_probes(pos_tag, function_id, cu, target_type_id, 0,
class_member__name(pos_member)); /* entry */
function__emit_probes(pos_tag, cu, pointer, 1,
function__emit_probes(pos_tag, function_id, cu, target_type_id, 1,
class_member__name(pos_member)); /* exit */
}
@ -812,8 +798,8 @@ static int cu_emit_functions_table(struct cu *cu, void *fp)
list_for_each_entry(pos, &cu->tool_list, tool_node)
if (pos->priv != NULL) {
fprintf(fp, "%llu:%s\n",
(unsigned long long)pos->proto.tag.id,
uint32_t function_id = (long)pos->priv;
fprintf(fp, "%d:%s\n", function_id,
function__name(pos, cu));
pos->priv = NULL;
}
@ -958,7 +944,7 @@ failure:
/*
* See if the specified struct exists:
*/
class = cus__find_struct_by_name(methods_cus, &cu, class_name, 0);
class = cus__find_struct_by_name(methods_cus, &cu, class_name, 0, NULL);
if (class == NULL) {
fprintf(stderr, "ctracer: struct %s not found!\n", class_name);
return EXIT_FAILURE;

View File

@ -14,6 +14,8 @@
#define __unused __attribute__ ((unused))
#endif
#define roundup(x,y) ((((x) + ((y) - 1)) / (y)) * (y))
/* We need define two variables, argp_program_version_hook and
argp_program_bug_address, in all programs. argp.h declares these
variables as non-const (which is correct in general). But we can

File diff suppressed because it is too large Load Diff

435
dwarves.c
View File

@ -25,14 +25,11 @@
#include "config.h"
#include "ctf_loader.h"
#include "dwarf_loader.h"
#include "hash.h"
#include "list.h"
#include "dwarves.h"
#include "dutil.h"
#include "strings.h"
#define hashtags__fn(key) hash_64(key, HASHTAGS__BITS)
struct strings *strings;
static inline const char *s(strings_t i)
@ -191,11 +188,12 @@ static size_t __tag__id_not_found_fprintf(FILE *fp, Dwarf_Off id,
#define tag__id_not_found_fprintf(fp, id) \
__tag__id_not_found_fprintf(fp, id, __func__)
size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp)
size_t tag__fprintf_decl_info(const struct tag *self,
const struct cu *cu, FILE *fp)
{
return fprintf(fp, "/* <%llx> %s:%u */\n",
(unsigned long long)self->id,
s(self->decl_file), self->decl_line);
return fprintf(fp, "/* <%llx> %s:%u */\n", tag__orig_id(self, cu),
tag__decl_file(self, cu), tag__decl_line(self, cu));
return 0;
}
static size_t type__fprintf(struct tag *type, const struct cu *cu,
@ -237,22 +235,8 @@ void namespace__delete(struct namespace *self)
tag__delete(&self->tag);
}
const char *type__name(struct type *self, const struct cu *cu)
const char *type__name(struct type *self, const struct cu *cu __unused)
{
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
if (!self->namespace.name &&
/* No? So it can have a DW_TAG_specification... */
self->specification != 0 &&
cu != NULL) {
struct tag *tag = cu__find_type_by_id(cu, self->specification);
if (tag == NULL) {
tag__id_not_found_fprintf(stderr, self->specification);
return NULL;
}
/* ... and now we cache the result in this tag ->name field */
self->namespace.name = tag__type(tag)->namespace.name;
}
return s(self->namespace.name);
}
@ -293,11 +277,10 @@ reevaluate:
case DW_TAG_const_type:
case DW_TAG_typedef:
case DW_TAG_volatile_type: {
const struct tag *tag = type;
type = cu__find_type_by_id(cu, type->id);
struct tag *tag = type;
type = cu__find_type_by_id(cu, tag->type);
if (type == NULL) {
tag__id_not_found_fprintf(stderr, tag->id);
tag__id_not_found_fprintf(stderr, tag->type);
continue;
}
}
@ -440,6 +423,93 @@ void cus__add(struct cus *self, struct cu *cu)
{
list_add_tail(&cu->node, &self->cus);
}
static void ptr_table__init(struct ptr_table *self)
{
self->entries = NULL;
self->nr_entries = self->allocated_entries = 0;
}
static void ptr_table__exit(struct ptr_table *self)
{
free(self->entries);
self->entries = NULL;
}
static long ptr_table__add(struct ptr_table *self, void *ptr)
{
const uint32_t nr_entries = self->nr_entries + 1;
const long rc = self->nr_entries;
if (nr_entries > self->allocated_entries) {
uint32_t allocated_entries = self->allocated_entries + 256;
void *entries = realloc(self->entries,
sizeof(void *) * allocated_entries);
if (entries == NULL)
return -ENOMEM;
self->allocated_entries = allocated_entries;
self->entries = entries;
}
self->entries[rc] = ptr;
self->nr_entries = nr_entries;
return rc;
}
static int ptr_table__add_with_id(struct ptr_table *self, void *ptr,
uint32_t id)
{
/* Assume we won't be fed with the same id more than once */
if (id >= self->allocated_entries) {
uint32_t allocated_entries = roundup(id + 1, 256);
void *entries = realloc(self->entries,
sizeof(void *) * allocated_entries);
if (entries == NULL)
return -ENOMEM;
self->allocated_entries = allocated_entries;
self->entries = entries;
}
self->entries[id] = ptr;
++self->nr_entries;
return 0;
}
static void *ptr_table__entry(const struct ptr_table *self, uint32_t id)
{
return id >= self->nr_entries ? NULL : self->entries[id];
}
int cu__table_add_tag(struct cu *self, struct tag *tag, long *id)
{
struct ptr_table *pt = tag__is_tag_type(tag) ?
&self->types_table :
&self->tags_table;
if (*id < 0) {
*id = ptr_table__add(pt, tag);
if (*id < 0)
return -ENOMEM;
} else if (ptr_table__add_with_id(pt, tag, *id) < 0)
return -ENOMEM;
return 0;
}
int cu__table_nullify_type_entry(struct cu *self, uint32_t id)
{
return ptr_table__add_with_id(&self->types_table, NULL, id);
}
int cu__add_tag(struct cu *self, struct tag *tag, long *id)
{
int err = cu__table_add_tag(self, tag, id);
if (err == 0)
list_add_tail(&tag->node, &self->tags);
return err;
}
struct cu *cu__new(const char *name, uint8_t addr_size,
const unsigned char *build_id,
@ -448,17 +518,23 @@ struct cu *cu__new(const char *name, uint8_t addr_size,
struct cu *self = malloc(sizeof(*self) + build_id_len);
if (self != NULL) {
uint32_t i;
self->name = strdup(name);
if (self->name == NULL)
goto out_free;
for (i = 0; i < HASHTAGS__SIZE; ++i) {
INIT_HLIST_HEAD(&self->hash_tags[i]);
INIT_HLIST_HEAD(&self->hash_types[i]);
}
ptr_table__init(&self->tags_table);
ptr_table__init(&self->types_table);
/*
* the first entry is historically associated with void,
* so make sure we don't use it
*/
if (ptr_table__add(&self->types_table, NULL) < 0)
goto out_free_name;
self->orig_info = NULL;
INIT_LIST_HEAD(&self->tags);
INIT_LIST_HEAD(&self->tool_list);
self->name = strdup(name);
self->addr_size = addr_size;
self->nr_inline_expansions = 0;
@ -472,8 +548,14 @@ struct cu *cu__new(const char *name, uint8_t addr_size,
if (build_id_len > 0)
memcpy(self->build_id, build_id, build_id_len);
}
out:
return self;
out_free_name:
free(self->name);
out_free:
free(self);
self = NULL;
goto out;
}
void cu__delete(struct cu *self)
@ -487,49 +569,12 @@ void cu__delete(struct cu *self)
if (tag__has_namespace(pos))
namespace__delete(tag__namespace(pos));
}
ptr_table__exit(&self->tags_table);
ptr_table__exit(&self->types_table);
free(self);
}
static void hashtags__hash(struct hlist_head *hashtable, struct tag *tag)
{
struct hlist_head *head = hashtable + hashtags__fn(tag->id);
hlist_add_head(&tag->hash_node, head);
}
static struct tag *hashtags__find(const struct hlist_head *hashtable,
const Dwarf_Off id)
{
struct tag *tpos;
struct hlist_node *pos;
const struct hlist_head *head;
if (id == 0)
return NULL;
head = hashtable + hashtags__fn(id);
hlist_for_each_entry(tpos, pos, head, hash_node)
if (tpos->id == id)
return tpos;
return NULL;
}
void cu__hash(struct cu *self, struct tag *tag)
{
struct hlist_head *hashtable = tag__is_tag_type(tag) ?
self->hash_types :
self->hash_tags;
hashtags__hash(hashtable, tag);
}
void cu__add_tag(struct cu *self, struct tag *tag)
{
list_add_tail(&tag->node, &self->tags);
cu__hash(self, tag);
}
bool cu__same_build_id(const struct cu *self, const struct cu *other)
{
return self->build_id_len != 0 &&
@ -553,90 +598,118 @@ static const char *tag__prefix(const struct cu *cu, const uint32_t tag)
return "";
}
struct tag *cu__find_tag_by_id(const struct cu *self, const Dwarf_Off id)
struct tag *cu__find_tag_by_id(const struct cu *self, const uint32_t id)
{
return self ? hashtags__find(self->hash_tags, id) : NULL;
return self ? ptr_table__entry(&self->tags_table, id) : NULL;
}
struct tag *cu__find_type_by_id(const struct cu *self, const Dwarf_Off id)
struct tag *cu__find_type_by_id(const struct cu *self, const uint16_t id)
{
return self ? hashtags__find(self->hash_types, id) : NULL;
return self ? ptr_table__entry(&self->types_table, id) : NULL;
}
struct tag *cu__find_first_typedef_of_type(const struct cu *self,
const Dwarf_Off type)
{
uint16_t id;
struct tag *pos;
if (self == NULL || type == 0)
return NULL;
list_for_each_entry(pos, &self->tags, node)
cu__for_each_type(self, id, pos)
if (tag__is_typedef(pos) && pos->type == type)
return pos;
return NULL;
}
struct tag *cu__find_base_type_by_name(const struct cu *self, const char *name)
struct tag *cu__find_base_type_by_name(const struct cu *self,
const char *name, uint16_t *idp)
{
uint16_t id;
struct tag *pos;
if (self == NULL || name == NULL)
return NULL;
list_for_each_entry(pos, &self->tags, node)
strings_t sname = strings__find(strings, name);
if (sname == 0)
return NULL;
cu__for_each_type(self, id, pos) {
if (pos->tag == DW_TAG_base_type) {
const struct base_type *bt = tag__base_type(pos);
if (bt->name && strcmp(s(bt->name), name) == 0)
if (bt->name == sname) {
if (idp != NULL)
*idp = id;
return pos;
}
}
}
return NULL;
}
struct tag *cu__find_base_type_by_name_and_size(const struct cu *self,
const char *name,
size_t bit_size)
size_t bit_size,
uint16_t *idp)
{
uint16_t id;
struct tag *pos;
if (self == NULL || name == NULL)
return NULL;
list_for_each_entry(pos, &self->tags, node)
strings_t sname = strings__find(strings, name);
if (sname == 0)
return NULL;
cu__for_each_type(self, id, pos) {
if (pos->tag == DW_TAG_base_type) {
const struct base_type *bt = tag__base_type(pos);
if (bt->bit_size == bit_size &&
bt->name && strcmp(s(bt->name), name) == 0)
bt->name == sname) {
if (idp != NULL)
*idp = id;
return pos;
}
}
}
return NULL;
}
struct tag *cu__find_struct_by_name(const struct cu *self, const char *name,
const int include_decls)
const int include_decls, uint16_t *idp)
{
uint16_t id;
struct tag *pos;
if (self == NULL || name == NULL)
return NULL;
list_for_each_entry(pos, &self->tags, node) {
strings_t sname = strings__find(strings, name);
if (sname == 0)
return NULL;
cu__for_each_type(self, id, pos) {
struct type *type;
if (!tag__is_struct(pos))
continue;
type = tag__type(pos);
if (type__name(type, self) != NULL &&
strcmp(type__name(type, self), name) == 0) {
if (type->namespace.name == sname) {
if (type->declaration) {
if (include_decls)
if (include_decls) {
if (idp != NULL)
*idp = id;
return pos;
}
} else
return pos;
}
@ -647,13 +720,14 @@ struct tag *cu__find_struct_by_name(const struct cu *self, const char *name,
struct tag *cus__find_struct_by_name(const struct cus *self,
struct cu **cu, const char *name,
const int include_decls)
const int include_decls, uint16_t *id)
{
struct cu *pos;
list_for_each_entry(pos, &self->cus, node) {
struct tag *tag = cu__find_struct_by_name(pos, name,
include_decls);
include_decls,
id);
if (tag != NULL) {
if (cu != NULL)
*cu = pos;
@ -733,98 +807,6 @@ struct tag *cu__find_function_by_name(const struct cu *self, const char *name)
return NULL;
}
static struct tag *lexblock__find_tag_by_id(const struct lexblock *self,
const Dwarf_Off id)
{
struct tag *pos;
list_for_each_entry(pos, &self->tags, node) {
/* Allow find DW_TAG_lexical_block tags */
if (pos->id == id)
return pos;
/*
* Oh, not looking for DW_TAG_lexical_block tags? So lets look
* inside this lexblock:
*/
if (pos->tag == DW_TAG_lexical_block) {
const struct lexblock *child = tag__lexblock(pos);
struct tag *tag = lexblock__find_tag_by_id(child, id);
if (tag != NULL)
return tag;
}
}
return NULL;
}
static struct variable *cu__find_variable_by_id(const struct cu *self,
const Dwarf_Off id)
{
struct tag *pos;
if (self == NULL)
return NULL;
list_for_each_entry(pos, &self->tags, node) {
/* Look at global variables first */
if (pos->id == id)
return (struct variable *)(pos);
/* Now look inside function lexical blocks */
if (pos->tag == DW_TAG_subprogram) {
struct function *fn = tag__function(pos);
struct tag *tag =
lexblock__find_tag_by_id(&fn->lexblock, id);
if (tag != NULL)
return (struct variable *)(tag);
}
}
return NULL;
}
static struct tag *list__find_tag_by_id(const struct list_head *self,
const Dwarf_Off id)
{
struct tag *pos, *tag;
list_for_each_entry(pos, self, node) {
if (pos->id == id)
return pos;
switch (pos->tag) {
case DW_TAG_namespace:
case DW_TAG_class_type:
case DW_TAG_structure_type:
case DW_TAG_union_type:
tag = list__find_tag_by_id(&tag__namespace(pos)->tags, id);
break;
case DW_TAG_subprogram:
tag = list__find_tag_by_id(&tag__ftype(pos)->parms, id);
if (tag == NULL)
tag = list__find_tag_by_id(&tag__function(pos)->lexblock.tags, id);
break;
default:
continue;
}
if (tag != NULL)
return tag;
}
return NULL;
}
static struct tag *cu__find_parameter_by_id(const struct cu *self,
const Dwarf_Off id)
{
if (self == NULL)
return NULL;
return list__find_tag_by_id(&self->tags, id);
}
static size_t array_type__nr_entries(const struct array_type *self)
{
int i;
@ -978,14 +960,14 @@ const char *tag__name(const struct tag *self, const struct cu *cu,
static struct tag *variable__type(const struct variable *self,
const struct cu *cu)
{
struct variable *var;
struct tag *var;
if (self->tag.type != 0)
return cu__find_type_by_id(cu, self->tag.type);
else if (self->abstract_origin != 0) {
var = cu__find_variable_by_id(cu, self->abstract_origin);
var = cu__find_tag_by_id(cu, self->abstract_origin);
if (var)
return variable__type(var, cu);
return variable__type(tag__variable(var), cu);
}
return NULL;
@ -1005,10 +987,10 @@ const char *variable__name(const struct variable *self, const struct cu *cu)
return s(self->name);
if (self->abstract_origin != 0) {
struct variable *var =
cu__find_variable_by_id(cu, self->abstract_origin);
struct tag *var =
cu__find_tag_by_id(cu, self->abstract_origin);
if (var != NULL)
return s(var->name);
return s(tag__variable(var)->name);
}
return NULL;
}
@ -1059,40 +1041,13 @@ size_t class_member__size(const struct class_member *self,
return tag__size(type, cu);
}
const char *parameter__name(struct parameter *self, const struct cu *cu)
const char *parameter__name(struct parameter *self, const struct cu *cu __unused)
{
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
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);
if (alias == NULL) {
tag__id_not_found_fprintf(stderr, self->abstract_origin);
return NULL;
}
/* Now cache the result in this tag ->name field */
self->name = tag__parameter(alias)->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 __unused)
{
/* Check if the tag doesn't comes with a DW_AT_type attribute... */
if (self->tag.type == 0 && 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);
if (alias == NULL) {
tag__id_not_found_fprintf(stderr, self->abstract_origin);
return 0;
}
/* Now cache the result in this tag ->name and type fields */
self->name = tag__parameter(alias)->name;
self->tag.type = tag__parameter(alias)->tag.type;
}
return self->tag.type;
}
@ -1476,25 +1431,8 @@ void lexblock__add_lexblock(struct lexblock *self, struct lexblock *child)
list_add_tail(&child->tag.node, &self->tags);
}
const char *function__name(struct function *self, const struct cu *cu)
const char *function__name(struct function *self, const struct cu *cu __unused)
{
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
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);
if (tag == NULL) {
/* ... or a DW_TAG_specification... */
tag = cu__find_tag_by_id(cu, self->specification);
if (tag == NULL) {
tag__id_not_found_fprintf(stderr, self->specification);
return NULL;
}
}
/* ... and now we cache the result in this tag ->name field */
self->name = tag__function(tag)->name;
}
return s(self->name);
}
@ -1512,7 +1450,7 @@ const char *function__prototype(const struct function *self,
return bf;
}
int ftype__has_parm_of_type(const struct ftype *self, const struct tag *target,
int ftype__has_parm_of_type(const struct ftype *self, const uint16_t target,
const struct cu *cu)
{
struct parameter *pos;
@ -1522,8 +1460,7 @@ int ftype__has_parm_of_type(const struct ftype *self, const struct tag *target,
cu__find_type_by_id(cu, parameter__type(pos, cu));
if (type != NULL && type->tag == DW_TAG_pointer_type) {
type = cu__find_type_by_id(cu, type->type);
if (type != NULL && type->id == target->id)
if (type->type == target)
return 1;
}
}
@ -1779,7 +1716,9 @@ static size_t ftype__fprintf_parms(const struct ftype *self,
name = parameter__name(pos, cu);
type = cu__find_type_by_id(cu, parameter__type(pos, cu));
if (type == NULL) {
stype = "<ERROR>";
snprintf(sbf, sizeof(sbf),
"<ERROR: type %d not found>", pos->tag.type);
stype = sbf;
goto print_it;
}
if (type->tag == DW_TAG_pointer_type) {
@ -1886,14 +1825,13 @@ static size_t function__tag_fprintf(const struct tag *tag, const struct cu *cu,
default:
printed = fprintf(fp, "%.*s", indent, tabs);
n = fprintf(fp, "%s <%llx>", dwarf_tag_name(tag->tag),
(unsigned long long)tag->id);
tag__orig_id(tag, cu));
c += n;
printed += n;
break;
}
return printed + fprintf(fp, "%-*.*s// %5u\n", 70 - c, 70 - c, " ",
tag->decl_line);
tag__decl_line(tag, cu));
}
size_t lexblock__fprintf(const struct lexblock *self, const struct cu *cu,
@ -2452,7 +2390,7 @@ size_t tag__fprintf(struct tag *self, const struct cu *cu,
if (pconf->show_decl_info) {
printed += fprintf(fp, "%.*s", pconf->indent, tabs);
printed += tag__fprintf_decl_info(self, fp);
printed += tag__fprintf_decl_info(self, cu, fp);
}
printed += fprintf(fp, "%.*s", pconf->indent, tabs);
@ -2515,16 +2453,17 @@ size_t tag__fprintf(struct tag *self, const struct cu *cu,
}
int cu__for_each_tag(struct cu *self,
int (*iterator)(struct tag *tag, struct cu *cu,
void *cookie),
int (*iterator)(struct tag *tag,
struct cu *cu, void *cookie),
void *cookie,
struct tag *(*filter)(struct tag *tag, struct cu *cu,
void *cookie))
struct tag *(*filter)(struct tag *tag,
struct cu *cu, void *cookie))
{
struct tag *pos;
list_for_each_entry(pos, &self->tags, node) {
struct tag *tag = pos;
if (filter != NULL) {
tag = filter(pos, self, cookie);
if (tag == NULL)

131
dwarves.h
View File

@ -26,16 +26,66 @@ struct cus {
struct cus *cus__new(void);
#define HASHTAGS__BITS 8
#define HASHTAGS__SIZE (1UL << HASHTAGS__BITS)
struct ptr_table {
void **entries;
uint32_t nr_entries;
uint32_t allocated_entries;
};
/**
* cu__for_each_type - iterate thru all the type tags
* @cu: struct cu instance to iterate
* @pos: struct tag iterator
* @id: uint16_t tag id
*
* See cu__table_nullify_type_entry and users for the reason for
* the NULL test (hint: CTF Unknown types)
*/
#define cu__for_each_type(cu, id, pos) \
for (id = 1, pos = cu->types_table.entries[id]; \
id < cu->types_table.nr_entries; \
pos = cu->types_table.entries[++id]) \
if (pos == NULL) \
continue; \
else
/**
* cu__for_each_function - iterate thru all the function tags
* @cu: struct cu instance to iterate
* @pos: struct function iterator
* @id: uint32_t tag id
*/
#define cu__for_each_function(cu, id, pos) \
for (id = 0, pos = tag__function(cu->tags_table.entries[id]); \
id < cu->tags_table.nr_entries; \
pos = tag__function(cu->tags_table.entries[++id])) \
if (pos->proto.tag.tag != DW_TAG_subprogram) \
continue; \
else
struct tag;
struct cu;
struct cu_orig_info {
const char *(*tag__decl_file)(const struct tag *self,
const struct cu *cu);
uint32_t (*tag__decl_line)(const struct tag *self,
const struct cu *cu);
unsigned long long (*tag__orig_id)(const struct tag *self,
const struct cu *cu);
unsigned long long (*tag__orig_type)(const struct tag *self,
const struct cu *cu);
};
struct cu {
struct list_head node;
struct list_head tags;
struct hlist_head hash_tags[HASHTAGS__SIZE];
struct hlist_head hash_types[HASHTAGS__SIZE];
struct list_head tool_list; /* To be used by tools such as ctracer */
const char *name;
struct ptr_table types_table;
struct ptr_table tags_table;
char *name;
void *priv;
struct cu_orig_info *orig_info;
uint8_t addr_size;
uint16_t language;
unsigned long nr_inline_expansions;
@ -49,20 +99,18 @@ struct cu {
unsigned char build_id[0];
};
struct tag;
void cu__hash(struct cu *cu, struct tag *tag);
/** struct tag - basic representation of a debug info element
* @priv - extra data, for instance, DWARF offset, id, decl_{file,line}
* @top_level -
*/
struct tag {
struct list_head node;
struct hlist_node hash_node;
Dwarf_Off type;
Dwarf_Off id;
strings_t decl_file;
uint16_t decl_line;
uint16_t type;
uint16_t tag;
uint16_t visited:1;
uint16_t recursivity_level:15;
uint16_t top_level:1;
uint16_t recursivity_level;
void *priv;
};
static inline int tag__is_enumeration(const struct tag *self)
@ -129,9 +177,28 @@ static inline int tag__is_tag_type(const struct tag *self)
self->tag == DW_TAG_volatile_type;
}
static inline const char *tag__decl_file(const struct tag *self)
static inline const char *tag__decl_file(const struct tag *self,
const struct cu *cu)
{
return strings__ptr(strings, self->decl_file);
return cu->orig_info ? cu->orig_info->tag__decl_file(self, cu) : NULL;
}
static inline uint32_t tag__decl_line(const struct tag *self,
const struct cu *cu)
{
return cu->orig_info ? cu->orig_info->tag__decl_line(self, cu) : 0;
}
static inline unsigned long long tag__orig_id(const struct tag *self,
const struct cu *cu)
{
return cu->orig_info ? cu->orig_info->tag__orig_id(self, cu) : 0;
}
static inline unsigned long long tag__orig_type(const struct tag *self,
const struct cu *cu)
{
return cu->orig_info ? cu->orig_info->tag__orig_type(self, cu) : 0;
}
struct ptr_to_member_type {
@ -508,6 +575,11 @@ struct label {
Dwarf_Off abstract_origin;
};
static inline struct label *tag__label(const struct tag *self)
{
return (struct label *)self;
}
struct enumerator {
struct tag tag;
strings_t name;
@ -545,7 +617,8 @@ extern size_t enumeration__fprintf(const struct tag *tag_self,
const struct conf_fprintf *conf, FILE *fp);
extern size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
const struct conf_fprintf *conf, FILE *fp);
extern size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp);
size_t tag__fprintf_decl_info(const struct tag *self,
const struct cu *cu, FILE *fp);
extern size_t tag__fprintf(struct tag *self, const struct cu *cu,
const struct conf_fprintf *conf, FILE *fp);
@ -577,14 +650,17 @@ extern void cus__print_error_msg(const char *progname, const struct cus *cus,
extern struct cu *cus__find_cu_by_name(const struct cus *self,
const char *name);
extern struct tag *cu__find_base_type_by_name(const struct cu *self,
const char *name);
const char *name,
uint16_t *id);
struct tag *cu__find_base_type_by_name_and_size(const struct cu *self,
const char *name,
size_t bit_size);
size_t bit_size,
uint16_t *id);
extern struct tag *cus__find_struct_by_name(const struct cus *self,
struct cu **cu,
const char *name,
const int include_decls);
const int include_decls,
uint16_t *id);
extern struct tag *cus__find_function_by_name(const struct cus *self,
struct cu **cu,
const char *name);
@ -595,15 +671,18 @@ struct cu *cu__new(const char *name, uint8_t addr_size,
const unsigned char *build_id, int build_id_len);
extern void cu__delete(struct cu *self);
void cu__add_tag(struct cu *self, struct tag *tag);
int cu__add_tag(struct cu *self, struct tag *tag, long *id);
int cu__table_add_tag(struct cu *self, struct tag *tag, long *id);
int cu__table_nullify_type_entry(struct cu *self, uint32_t id);
extern struct tag *cu__find_tag_by_id(const struct cu *self,
const Dwarf_Off id);
struct tag *cu__find_type_by_id(const struct cu *self, const Dwarf_Off id);
const uint32_t id);
struct tag *cu__find_type_by_id(const struct cu *self, const uint16_t id);
extern struct tag *cu__find_first_typedef_of_type(const struct cu *self,
const Dwarf_Off type);
extern struct tag *cu__find_struct_by_name(const struct cu *cu,
const char *name,
const int include_decls);
const int include_decls,
uint16_t *id);
extern bool cu__same_build_id(const struct cu *self, const struct cu *other);
extern void cu__account_inline_expansions(struct cu *self);
extern int cu__for_each_tag(struct cu *self,
@ -651,7 +730,7 @@ extern size_t ftype__fprintf(const struct ftype *self, const struct cu *cu,
const int is_pointer, const int type_spacing,
FILE *fp);
extern int ftype__has_parm_of_type(const struct ftype *self,
const struct tag *target,
const uint16_t target,
const struct cu *cu);
void type__add_member(struct type *self, struct class_member *member);

View File

@ -446,7 +446,8 @@ static void class__demote_bitfield_members(struct class *class,
struct class_member *from,
struct class_member *to,
const struct base_type *old_type,
const struct base_type *new_type)
const struct base_type *new_type,
uint16_t new_type_id)
{
const uint8_t bit_diff = old_type->bit_size - new_type->bit_size;
struct class_member *member =
@ -459,7 +460,7 @@ static void class__demote_bitfield_members(struct class *class,
* Assume IA32 bitfield layout
*/
member->bit_offset -= bit_diff;
member->tag.type = new_type->tag.id;
member->tag.type = new_type_id;
if (member == to)
break;
member->bit_hole = 0;
@ -467,7 +468,7 @@ static void class__demote_bitfield_members(struct class *class,
}
static struct tag *cu__find_base_type_of_size(const struct cu *cu,
const size_t size)
const size_t size, uint16_t *id)
{
const char *type_name, *type_name_alt = NULL;
@ -493,8 +494,8 @@ static struct tag *cu__find_base_type_of_size(const struct cu *cu,
return NULL;
}
struct tag *ret = cu__find_base_type_by_name(cu, type_name);
return ret ?: cu__find_base_type_by_name(cu, type_name_alt);
struct tag *ret = cu__find_base_type_by_name(cu, type_name, id);
return ret ?: cu__find_base_type_by_name(cu, type_name_alt, id);
}
static int class__demote_bitfields(struct class *class, const struct cu *cu,
@ -543,8 +544,10 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
if (bytes_needed == size)
continue;
uint16_t new_type_id;
old_type_tag = cu__find_type_by_id(cu, member->tag.type);
new_type_tag = cu__find_base_type_of_size(cu, bytes_needed);
new_type_tag = cu__find_base_type_of_size(cu, bytes_needed,
&new_type_id);
if (new_type_tag == NULL) {
fprintf(fp, "/* BRAIN FART ALERT! couldn't find a "
@ -562,7 +565,8 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
class__demote_bitfield_members(class,
bitfield_head, member,
tag__base_type(old_type_tag),
tag__base_type(new_type_tag));
tag__base_type(new_type_tag),
new_type_id);
new_size = class_member__size(member, cu);
member->hole = size - new_size;
if (member->hole != 0)
@ -593,8 +597,10 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
if (bytes_needed < size) {
old_type_tag =
cu__find_type_by_id(cu, member->tag.type);
uint16_t new_type_id;
new_type_tag =
cu__find_base_type_of_size(cu, bytes_needed);
cu__find_base_type_of_size(cu, bytes_needed,
&new_type_id);
tag__assert_search_result(old_type_tag);
tag__assert_search_result(new_type_tag);
@ -608,7 +614,8 @@ static int class__demote_bitfields(struct class *class, const struct cu *cu,
class__demote_bitfield_members(class,
member, member,
tag__base_type(old_type_tag),
tag__base_type(new_type_tag));
tag__base_type(new_type_tag),
new_type_id);
new_size = class_member__size(member, cu);
member->hole = 0;
/*
@ -667,7 +674,7 @@ restart:
static void class__fixup_bitfield_types(struct class *self,
struct class_member *from,
struct class_member *to_before,
Dwarf_Off type)
uint16_t type)
{
struct class_member *member =
list_prepare_entry(from, class__tags(self), tag.node);
@ -733,9 +740,11 @@ static void class__fixup_member_types(struct class *self, const struct cu *cu,
const size_t size = class_member__size(bitfield_head,
cu);
if (real_size != size) {
uint16_t new_type_id;
struct tag *new_type_tag =
cu__find_base_type_of_size(cu,
real_size);
real_size,
&new_type_id);
if (new_type_tag == NULL) {
fprintf(stderr, "pahole: couldn't find"
" a base_type of %d bytes!\n",
@ -744,7 +753,7 @@ static void class__fixup_member_types(struct class *self, const struct cu *cu,
}
class__fixup_bitfield_types(self,
bitfield_head, pos,
new_type_tag->id);
new_type_id);
fixup_was_done = 1;
}
}

View File

@ -63,9 +63,10 @@ struct structure {
const struct cu *cu;
uint32_t nr_files;
uint32_t nr_methods;
uint16_t id;
};
static struct structure *structure__new(struct class *class,
static struct structure *structure__new(struct class *class, uint16_t id,
const struct cu *cu)
{
struct structure *self = malloc(sizeof(*self));
@ -75,6 +76,7 @@ static struct structure *structure__new(struct class *class,
self->cu = cu;
self->nr_files = 1;
self->nr_methods = 0;
self->id = id;
}
return self;
@ -84,9 +86,10 @@ static void *structures__tree;
static LIST_HEAD(structures__anonymous_list);
static LIST_HEAD(structures__named_list);
static void structures__add_anonymous(struct class *class, const struct cu *cu)
static void structures__add_anonymous(struct class *class, uint16_t id,
const struct cu *cu)
{
struct structure *str = structure__new(class, cu);
struct structure *str = structure__new(class, id, cu);
if (str != NULL)
list_add_tail(&str->node, &structures__anonymous_list);
@ -100,7 +103,8 @@ static int structure__compare(const void *a, const void *b)
return strings__cmp(strings, *key, pos->class->type.namespace.name);
}
static int structures__add_named(struct class *class, const struct cu *cu)
static int structures__add_named(struct class *class, uint16_t id,
const struct cu *cu)
{
struct structure *str;
strings_t *s = tsearch(&class->type.namespace.name, &structures__tree,
@ -113,7 +117,7 @@ static int structures__add_named(struct class *class, const struct cu *cu)
* calling structures__add_named */
assert(*s != class->type.namespace.name);
str = structure__new(class, cu);
str = structure__new(class, id, cu);
if (str == NULL)
return -ENOMEM;
@ -125,17 +129,15 @@ static int structures__add_named(struct class *class, const struct cu *cu)
return 0;
}
static int structures__add(struct class *class, const struct cu *cu)
static int structures__add(struct class *class, uint16_t id,
const struct cu *cu)
{
/* Let it follow abstract_origin, etc */
class__name(class, cu);
if (!class->type.namespace.name) {
structures__add_anonymous(class, cu);
structures__add_anonymous(class, id, cu);
return 0;
}
return structures__add_named(class, cu);
return structures__add_named(class, id, cu);
}
static struct structure *structures__find_anonymous(strings_t name)
@ -144,7 +146,7 @@ static struct structure *structures__find_anonymous(strings_t name)
list_for_each_entry(pos, &structures__anonymous_list, node) {
struct class *c = pos->class;
const struct tag *tdef = cu__find_first_typedef_of_type(pos->cu, class__tag(c)->id);
const struct tag *tdef = cu__find_first_typedef_of_type(pos->cu, pos->id);
if (tdef == NULL)
continue;
@ -225,7 +227,7 @@ static void class_formatter(struct structure *self)
* affected.
*/
typedef_alias = cu__find_first_typedef_of_type(self->cu,
tag->id);
self->id);
/*
* If there is no typedefs for this anonymous struct it is
* found just inside another struct, and in this case it'll
@ -265,7 +267,7 @@ static void print_packable_info(struct structure *pos)
/* Anonymous struct? Try finding a typedef */
if (name == NULL) {
const struct tag *tdef =
cu__find_first_typedef_of_type(pos->cu, t->id);
cu__find_first_typedef_of_type(pos->cu, pos->id);
if (tdef != NULL)
name = class__name(tag__class(tdef), pos->cu);
@ -278,7 +280,8 @@ static void print_packable_info(struct structure *pos)
savings);
else
printf("%s(%d)%c%zd%c%zd%c%zd\n",
tag__decl_file(t), t->decl_line,
tag__decl_file(t, pos->cu),
tag__decl_line(t, pos->cu),
separator,
orig_size, separator,
new_size, separator,
@ -391,7 +394,7 @@ static void class__chkdupdef(struct class *self, const struct cu *cu,
}
static struct tag *tag__filter(struct tag *tag, struct cu *cu,
void *cookie __unused)
uint16_t tag_id)
{
struct structure *str;
struct class *class;
@ -401,6 +404,9 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
if (!tag__is_struct(tag))
return NULL;
if (!tag->top_level)
return NULL;
class = tag__class(tag);
name = class__name(class, cu);
stname = class->type.namespace.name;
@ -414,7 +420,7 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
if (class__exclude_prefix != NULL) {
if (name == NULL) {
const struct tag *tdef =
cu__find_first_typedef_of_type(cu, tag->id);
cu__find_first_typedef_of_type(cu, tag_id);
if (tdef != NULL) {
struct class *c = tag__class(tdef);
@ -422,7 +428,6 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
stname = c->type.namespace.name;
}
}
if (name != NULL && strncmp(class__exclude_prefix, name,
class__exclude_prefix_len) == 0)
return NULL;
@ -431,7 +436,7 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
if (class__include_prefix != NULL) {
if (name == NULL) {
const struct tag *tdef =
cu__find_first_typedef_of_type(cu, tag->id);
cu__find_first_typedef_of_type(cu, tag_id);
if (tdef != NULL) {
struct class *c = tag__class(tdef);
@ -439,7 +444,6 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
stname = c->type.namespace.name;
}
}
if (name != NULL && strncmp(class__include_prefix, name,
class__include_prefix_len) != 0)
return NULL;
@ -447,8 +451,8 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
if (decl_exclude_prefix != NULL &&
(!tag->decl_file ||
strncmp(decl_exclude_prefix, tag__decl_file(tag),
(!tag__decl_file(tag, cu) ||
strncmp(decl_exclude_prefix, tag__decl_file(tag, cu),
decl_exclude_prefix_len) == 0))
return NULL;
@ -473,26 +477,23 @@ static struct tag *tag__filter(struct tag *tag, struct cu *cu,
return tag;
}
static int unique_iterator(struct tag *tag, struct cu *cu,
void *cookie __unused)
static int cu_unique_iterator(struct cu *cu, void *cookie __unused)
{
if (structures__add(tag__class(tag), cu)) {
fprintf(stderr, "pahole: not enough memory! "
"Continuing with partial results\n");
return -1;
}
return 0;
}
uint16_t id;
struct tag *tag;
static int cu_unique_iterator(struct cu *cu, void *cookie)
{
if (defined_in) {
struct tag *tag = cu__find_struct_by_name(cu, class_name, 0);
tag = cu__find_struct_by_name(cu, class_name, 0, &id);
if (tag != NULL)
puts(cu->name);
} else
return cu__for_each_tag(cu, unique_iterator, cookie, tag__filter);
} else {
cu__for_each_type(cu, id, tag) {
if (tag__filter(tag, cu, id) &&
structures__add(tag__class(tag), id, cu))
fprintf(stderr, "pahole: not enough memory! "
"Continuing with partial results\n");
}
}
return 0;
}
@ -728,7 +729,7 @@ static char tab[128];
static void print_structs_with_pointer_to(const struct structure *s)
{
struct structure *pos_structure;
Dwarf_Off type;
uint16_t type;
const char *class_name = class__name(s->class, s->cu);
const struct cu *current_cu = NULL;
@ -737,13 +738,16 @@ static void print_structs_with_pointer_to(const struct structure *s)
struct class_member *pos_member;
if (pos_structure->cu != current_cu) {
uint16_t class_id;
struct tag *class;
class = cu__find_struct_by_name(pos_structure->cu, class_name, 1);
class = cu__find_struct_by_name(pos_structure->cu,
class_name, 1,
&class_id);
if (class == NULL)
continue;
current_cu = pos_structure->cu;
type = class->id;
type = class_id;
}
type__for_each_member(&c->type, pos_member) {
@ -760,7 +764,7 @@ static void print_structs_with_pointer_to(const struct structure *s)
static void print_containers(const struct structure *s, int ident)
{
struct structure *pos;
const Dwarf_Off type = s->class->type.namespace.tag.id;
const uint16_t type = s->id;
list_for_each_entry(pos, &structures__named_list, node) {
struct class *c = pos->class;

View File

@ -18,46 +18,43 @@ static struct conf_fprintf conf = {
.emit_stats = 1,
};
static int emit_tag(struct tag *self, struct cu *cu, void *cookie __unused)
static void emit_tag(struct tag *self, uint32_t tag_id, struct cu *cu)
{
if (self->tag != DW_TAG_array_type &&
self->tag != DW_TAG_const_type &&
self->tag != DW_TAG_formal_parameter &&
self->tag != DW_TAG_reference_type &&
self->tag != DW_TAG_subroutine_type &&
self->tag != DW_TAG_volatile_type) {
if (tag__is_struct(self))
class__find_holes(tag__class(self), cu);
if (tag__is_struct(self))
class__find_holes(tag__class(self), cu);
conf.no_semicolon = self->tag == DW_TAG_subprogram;
conf.no_semicolon = self->tag == DW_TAG_subprogram;
printf("%lld ", (unsigned long long)self->id);
printf("%d ", tag_id);
if (self->tag == DW_TAG_base_type) {
const char *name = base_type__name(tag__base_type(self));
if (self->tag == DW_TAG_base_type) {
const char *name = base_type__name(tag__base_type(self));
if (name == NULL)
printf("anonymous base_type\n");
else
puts(name);
} else if (self->tag == DW_TAG_pointer_type)
printf("pointer to %lld\n", (unsigned long long)self->type);
if (name == NULL)
printf("anonymous base_type\n");
else
tag__fprintf(self, cu, &conf, stdout);
puts(name);
} else if (self->tag == DW_TAG_pointer_type)
printf("pointer to %lld\n", (unsigned long long)self->type);
else
tag__fprintf(self, cu, &conf, stdout);
if (self->tag == DW_TAG_subprogram) {
struct function *fn = tag__function(self);
putchar('\n');
lexblock__fprintf(&fn->lexblock, cu, fn, 0, stdout);
}
puts("\n");
if (self->tag == DW_TAG_subprogram) {
struct function *fn = tag__function(self);
putchar('\n');
lexblock__fprintf(&fn->lexblock, cu, fn, 0, stdout);
}
return 0;
puts("\n");
}
static int cu__emit_tags(struct cu *self, void *cookie __unused)
{
cu__for_each_tag(self, emit_tag, NULL, NULL);
uint16_t i;
for (i = 1; i < self->types_table.nr_entries; ++i) {
struct tag *tag = self->types_table.entries[i];
emit_tag(tag, i, self);
}
return 0;
}

View File

@ -218,6 +218,9 @@ static struct tag *function__filter(struct tag *tag, struct cu *cu,
if (tag->tag != DW_TAG_subprogram)
return NULL;
if (!tag->top_level)
return NULL;
function = tag__function(tag);
/*
* FIXME: remove this check and try to fix the parameter abstract
@ -271,6 +274,7 @@ static int cu_unique_iterator(struct cu *cu, void *cookie)
static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
{
uint16_t *target_id = cookie;
struct function *function;
if (tag->tag != DW_TAG_subprogram)
@ -280,7 +284,7 @@ static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
if (function->inlined)
return 0;
if (ftype__has_parm_of_type(&function->proto, cookie, cu)) {
if (ftype__has_parm_of_type(&function->proto, *target_id, cu)) {
if (verbose)
tag__fprintf(tag, cu, &conf, stdout);
else
@ -292,12 +296,13 @@ static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
static int cu_class_iterator(struct cu *cu, void *cookie)
{
struct tag *target = cu__find_struct_by_name(cu, cookie, 0);
uint16_t target_id;
struct tag *target = cu__find_struct_by_name(cu, cookie, 0, &target_id);
if (target == NULL)
return 0;
return cu__for_each_tag(cu, class_iterator, target, NULL);
return cu__for_each_tag(cu, class_iterator, &target_id, NULL);
}
static int function__emit_type_definitions(struct function *self,

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->visited && tag->decl_file) {
if (!tag->visited && tag__decl_file(tag, cu)) {
tag__fprintf(tag, cu, NULL, stdout);
puts(";\n");
}