From 0872d8e312f34ff6e9e547622fdcca76c49f85fa Mon Sep 17 00:00:00 2001 From: Arnaldo Carvalho de Melo Date: Sun, 7 Jan 2007 17:57:00 -0200 Subject: [PATCH] [CLASSES]: Support abstract origin in formal parameters Sortof, mostly works, but still has a problem where the abstract origin is not being found, but for now its ok to keep the bandaid, everything works as before, there are more important things to do right now. Signed-off-by: Arnaldo Carvalho de Melo --- classes.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++-------- classes.h | 6 ++++ pfunct.c | 10 +++++-- 3 files changed, 86 insertions(+), 14 deletions(-) diff --git a/classes.c b/classes.c index aafba7a..ae7ac6d 100644 --- a/classes.c +++ b/classes.c @@ -684,6 +684,27 @@ static struct variable *cu__find_variable_by_id(const struct cu *self, return NULL; } +static struct parameter *cu__find_parameter_by_id(const struct cu *self, + const Dwarf_Off id) +{ + struct tag *pos; + + list_for_each_entry(pos, &self->tags, node) + if (pos->id == id) + return tag__parameter(pos); + + 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 tag__parameter(tag); + } + + return NULL; +} + int tag__is_struct(const struct tag *self, struct tag **typedef_alias, const struct cu *cu) { @@ -1052,12 +1073,46 @@ static struct parameter *parameter__new(Dwarf_Die *die) if (self != NULL) { tag__init(&self->tag, die); - self->name = strings__add(attr_string(die, DW_AT_name)); + self->name = strings__add(attr_string(die, + DW_AT_name)); + self->abstract_origin = attr_numeric(die, + DW_AT_abstract_origin); } return self; } +const char *parameter__name(struct parameter *self, const struct cu *cu) +{ + /* Check if the tag doesn't comes with a DW_AT_name attribute... */ + if (self->name == NULL && self->abstract_origin != 0) { + /* No? Does it have a DW_AT_abstract_origin? */ + struct parameter *alias = + cu__find_parameter_by_id(cu, self->abstract_origin); + assert(alias != NULL); + /* Now cache the result in this tag ->name field */ + self->name = alias->name; + } + + return self->name; +} + +Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu) +{ + /* 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 parameter *alias = + cu__find_parameter_by_id(cu, self->abstract_origin); + assert(alias != NULL); + /* Now cache the result in this tag ->name and type fields */ + self->name = alias->name; + self->tag.type = alias->tag.type; + } + + return self->tag.type; +} + static struct inline_expansion *inline_expansion__new(Dwarf_Die *die) { struct inline_expansion *self = zalloc(sizeof(*self)); @@ -1240,7 +1295,8 @@ int ftype__has_parm_of_type(const struct ftype *self, const struct tag *target, struct parameter *pos; list_for_each_entry(pos, &self->parms, tag.node) { - struct tag *type = cu__find_tag_by_id(cu, pos->tag.type); + struct tag *type = + cu__find_tag_by_id(cu, parameter__type(pos, cu)); if (type != NULL && type->tag == DW_TAG_pointer_type) { type = cu__find_tag_by_id(cu, type->type); @@ -1528,12 +1584,15 @@ size_t ftype__snprintf(const struct ftype *self, const struct cu *cu, s += n; l -= n; list_for_each_entry(pos, &self->parms, tag.node) { + const char *name; + if (!first_parm) { n = snprintf(s, l, ", "); s += n; l -= n; } else first_parm = 0; - type = cu__find_tag_by_id(cu, pos->tag.type); + type = cu__find_tag_by_id(cu, parameter__type(pos, cu)); + name = parameter__name(pos, cu); if (type->tag == DW_TAG_pointer_type) { if (type->type != 0) { struct tag *ptype = @@ -1541,18 +1600,18 @@ size_t ftype__snprintf(const struct ftype *self, const struct cu *cu, if (ptype->tag == DW_TAG_subroutine_type) { n = ftype__snprintf(tag__ftype(ptype), cu, s, l, - pos->name, 0, 1, 0); + name, 0, 1, 0); goto next; } } } else if (type->tag == DW_TAG_subroutine_type) { n = ftype__snprintf(tag__ftype(type), cu, s, l, - pos->name, 0, 0, 0); + name, 0, 0, 0); goto next; } stype = tag__name(type, cu, sbf, sizeof(sbf)); n = snprintf(s, l, "%s%s%s", stype, - pos->name ? " " : "", pos->name ?: ""); + name ? " " : "", name ?: ""); next: s += n; l -= n; } @@ -1942,14 +2001,18 @@ static void cu__create_new_array(Dwarf_Die *die, struct cu *cu) cu__add_tag(cu, &array->tag); } -static void cu__create_new_parameter(Dwarf_Die *die, struct ftype *ftype) +static void cu__create_new_parameter(Dwarf_Die *die, struct ftype *ftype, + struct cu *cu) { struct parameter *parm = parameter__new(die); if (parm == NULL) oom("parameter__new"); - ftype__add_parameter(ftype, parm); + if (ftype != NULL) + ftype__add_parameter(ftype, parm); + else + cu__add_tag(cu, &parm->tag); } static void cu__create_new_label(Dwarf_Die *die, struct lexblock *lexblock) @@ -1989,7 +2052,7 @@ static void cu__create_new_subroutine_type(Dwarf_Die *die, struct cu *cu) switch (tag) { case DW_TAG_formal_parameter: - cu__create_new_parameter(die, ftype); + cu__create_new_parameter(die, ftype, cu); break; case DW_TAG_unspecified_parameters: ftype->unspec_parms = 1; @@ -2120,8 +2183,7 @@ static void cu__process_function(Dwarf_Die *die, switch (tag) { case DW_TAG_formal_parameter: - if (ftype != NULL) - cu__create_new_parameter(die, ftype); + cu__create_new_parameter(die, ftype, cu); break; case DW_TAG_variable: cu__create_new_variable(cu, die, lexblock); diff --git a/classes.h b/classes.h index 5273a68..87ad9df 100644 --- a/classes.h +++ b/classes.h @@ -187,8 +187,14 @@ static inline struct function *tag__function(const struct tag *self) struct parameter { struct tag tag; char *name; + Dwarf_Off abstract_origin; }; +static inline struct parameter *tag__parameter(const struct tag *self) +{ + return (struct parameter *)self; +} + struct variable { struct tag tag; char *name; diff --git a/pfunct.c b/pfunct.c index 66b2230..d844296 100644 --- a/pfunct.c +++ b/pfunct.c @@ -156,7 +156,7 @@ static void fn_stats__dupmsg(struct function *self, printf("function: %s\nfirst: %s\ncurrent: %s\n", function__name(self, self_cu), self_cu->name, - function__name(dup, dup_cu)); + dup_cu->name); va_start(args, fmt); vprintf(fmt, args); @@ -200,10 +200,14 @@ static struct tag *function__filter(struct tag *tag, struct cu *cu, return NULL; function = tag__function(tag); - name = function__name(function, cu); - if (name == NULL) + /* + * FIXME: remove this check and try to fix the parameter abstract + * origin code someday... + */ + if (function->name == NULL) return NULL; + name = function__name(function, cu); if (show_externals && !function->external) return NULL;