[CLASSES]: Handle DW_AT_abstract_origin in DW_TAG_subprogram

We have to check for a possible alias (abstract origin attribute) and handle
that when we want the function name, if it is an alias, do the lookup and cache
the result in ->name, that after all doesn't have a value in the first place.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
Arnaldo Carvalho de Melo 2007-01-07 17:13:39 -02:00
parent fddb3f4e15
commit 29103e42be
5 changed files with 86 additions and 51 deletions

View File

@ -745,6 +745,8 @@ const char *tag__name(const struct tag *self, const struct cu *cu,
strncpy(bf, "void", len);
else if (self->tag == DW_TAG_base_type)
strncpy(bf, tag__base_type(self)->name, len);
else if (self->tag == DW_TAG_subprogram)
strncpy(bf, function__name(tag__function(self), cu), len);
else if (self->tag == DW_TAG_pointer_type) {
if (self->type == 0) /* No type == void */
strncpy(bf, "void *", len);
@ -1210,11 +1212,28 @@ static struct function *function__new(Dwarf_Die *die)
self->name = strings__add(attr_string(die, DW_AT_name));
self->inlined = attr_numeric(die, DW_AT_inline);
self->external = dwarf_hasattr(die, DW_AT_external);
self->abstract_origin = attr_numeric(die,
DW_AT_abstract_origin);
}
return self;
}
const char *function__name(struct function *self, const struct cu *cu)
{
/* Check if the tag doesn't comes with a DW_AT_name attribute... */
if (self->name == NULL) {
/* No? So it must have a DW_AT_abstract_origin... */
struct tag *tag = cu__find_tag_by_id(cu,
self->abstract_origin);
assert(tag != NULL);
/* ... and now we cache the result in this tag ->name field */
self->name = tag__function(tag)->name;
}
return self->name;
}
int ftype__has_parm_of_type(const struct ftype *self, const struct tag *target,
const struct cu *cu)
{
@ -1444,12 +1463,12 @@ static void function__tag_print(const struct tag *tag, const struct cu *cu,
const struct inline_expansion *exp = vtag;
const struct tag *talias =
cu__find_tag_by_id(cu, exp->tag.type);
const struct function *alias = tag__function(talias);
struct function *alias = tag__function(talias);
assert(alias != NULL);
printf("%.*s", indent, tabs);
c += printf("%s(); /* low_pc=%#llx */",
alias->name, exp->low_pc);
function__name(alias, cu), exp->low_pc);
}
break;
case DW_TAG_variable:
@ -1548,7 +1567,7 @@ size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
return len - (l - n);
}
void function__print(const struct function *self, const struct cu *cu,
void function__print(struct function *self, const struct cu *cu,
int show_stats, const int show_variables,
const int show_inline_expansions)
{
@ -1560,7 +1579,8 @@ void function__print(const struct function *self, const struct cu *cu,
self->proto.tag.decl_line);
ftype__snprintf(&self->proto, cu, bf, sizeof(bf),
self->name, function__declared_inline(self), 0, 0);
function__name(self, cu),
function__declared_inline(self), 0, 0);
fputs(bf, stdout);
if (show_variables || show_inline_expansions) {

View File

@ -169,6 +169,7 @@ struct function {
struct ftype proto;
struct lexblock lexblock;
const char *name;
Dwarf_Off abstract_origin;
size_t cu_total_size_inline_expansions;
uint16_t cu_total_nr_inline_expansions;
uint8_t inlined; /* two bits used */
@ -241,7 +242,9 @@ struct enumerator {
extern void class__find_holes(struct class *self, const struct cu *cu);
extern void tag__print(const struct tag *self, const struct cu *cu,
const char *prefix, const char *suffix);
extern void function__print(const struct function *self, const struct cu *cu,
extern const char *function__name(struct function *self, const struct cu *cu);
extern void function__print(struct function *self, const struct cu *cu,
const int show_stats,
const int show_variables,
const int show_inline_expansions);

View File

@ -83,18 +83,20 @@ static void diff_function(const struct cu *new_cu, struct function *function,
struct cu *cu)
{
struct function *new_function;
const char *name;
assert(function->proto.tag.tag == DW_TAG_subprogram);
if (function->inlined)
return;
new_function = cu__find_function_by_name(new_cu, function->name);
name = function__name(function, cu);
new_function = cu__find_function_by_name(new_cu, name);
if (new_function != NULL) {
int32_t diff = (function__size(new_function) -
function__size(function));
if (diff != 0) {
const size_t len = strlen(function->name);
const size_t len = strlen(name);
function->priv = diff_info__new(&new_function->proto.tag, new_cu,
diff);
@ -108,7 +110,7 @@ static void diff_function(const struct cu *new_cu, struct function *function,
cu->function_bytes_removed += -diff;
}
} else {
const size_t len = strlen(function->name);
const size_t len = strlen(name);
const uint32_t diff = -function__size(function);
if (len > cu->max_len_changed_item)
@ -269,15 +271,17 @@ static int find_new_functions_iterator(struct tag *tfunction, struct cu *cu,
{
struct function *function = tag__function(tfunction);
struct function *old_function;
const char *name;
assert(function->proto.tag.tag == DW_TAG_subprogram);
if (function->inlined)
return 0;
old_function = cu__find_function_by_name(old_cu, function->name);
name = function__name(function, cu);
old_function = cu__find_function_by_name(old_cu, name);
if (old_function == NULL) {
const size_t len = strlen(function->name);
const size_t len = strlen(name);
const int32_t diff = function__size(function);
if (len > cu->max_len_changed_item)
@ -345,14 +349,13 @@ static int cu_diff_iterator(struct cu *cu, void *new_cus)
return 0;
}
static void show_diffs_function(const struct function *function,
const struct cu *cu)
static void show_diffs_function(struct function *function, const struct cu *cu)
{
const struct diff_info *di = function->priv;
printf(" %-*.*s | %+4d\n",
cu->max_len_changed_item, cu->max_len_changed_item,
function->name, di->diff);
function__name(function, cu), di->diff);
}
static void show_changed_member(char change, const struct class_member *member,

View File

@ -60,8 +60,7 @@ static int cu_find_methods_iterator(struct cu *cu, void *cookie)
return cu__for_each_tag(cu, find_methods_iterator, target, function__filter);
}
static int function__emit_kprobes(const struct function *self,
const struct cu *cu,
static int function__emit_kprobes(struct function *self, const struct cu *cu,
const struct tag *target)
{
char bf[128];
@ -71,11 +70,12 @@ static int function__emit_kprobes(const struct function *self,
struct parameter *pos;
struct tag *type = cu__find_tag_by_id(cu, self->proto.tag.type);
const char *stype = tag__name(type, cu, bf, sizeof(bf));
const char *name = function__name(self, cu);
int first = 1;
body[0] = '\0';
printf("static %s jprobe_entry__%s(", stype, self->name);
printf("static %s jprobe_entry__%s(", stype, name);
list_for_each_entry(pos, &self->proto.parms, tag.node) {
type = cu__find_tag_by_id(cu, pos->tag.type);
@ -98,7 +98,7 @@ static int function__emit_kprobes(const struct function *self,
printed = snprintf(bodyp, bodyl,
"\tprintk(\"-> %s: %s=%%p\\n\", %s);\n",
self->name, pos->name, pos->name);
name, pos->name, pos->name);
bodyp += printed;
bodyl -= printed;
}
@ -107,7 +107,7 @@ static int function__emit_kprobes(const struct function *self,
printf("static struct jprobe jprobe__%s = {\n"
"\t.kp = { .symbol_name = \"%s\", },\n"
"\t.entry = (kprobe_opcode_t *)jprobe_entry__%s,\n"
"};\n\n", self->name, self->name, self->name);
"};\n\n", name, name, name);
return 0;
}
@ -129,24 +129,27 @@ static int cu_emit_kprobes_table_iterator(struct cu *cu, void *cookie)
struct function *pos;
list_for_each_entry(pos, &cu->tool_list, tool_node)
printf("\t&jprobe__%s,\n", pos->name);
printf("\t&jprobe__%s,\n", function__name(pos, cu));
return 0;
}
static int function__emit_kretprobes(const struct function *self)
static int function__emit_kretprobes(struct function *self,
const struct cu *cu)
{
const char *name = function__name(self, cu);
printf("static int kretprobe_handler__%s(struct kretprobe_instance *ri, "
"struct pt_regs *regs)\n"
"{\n"
"\tprintk(\"<- %s\\n\");\n"
"\treturn 0;\n"
"}\n\n", self->name, self->name);
"}\n\n", name, name);
printf("static struct kretprobe kretprobe__%s = {\n"
"\t.kp = { .symbol_name = \"%s\", },\n"
"\t.handler = (kretprobe_handler_t)kretprobe_handler__%s,\n"
"\t.maxactive = -1,\n\n"
"};\n\n", self->name, self->name, self->name);
"};\n\n", name, name, name);
}
static int cu_emit_kretprobes_iterator(struct cu *cu, void *cookie)
@ -154,7 +157,7 @@ static int cu_emit_kretprobes_iterator(struct cu *cu, void *cookie)
struct function *pos;
list_for_each_entry(pos, &cu->tool_list, tool_node)
function__emit_kretprobes(pos);
function__emit_kretprobes(pos, cu);
return 0;
}
@ -164,7 +167,7 @@ static int cu_emit_kretprobes_table_iterator(struct cu *cu, void *cookie)
struct function *pos;
list_for_each_entry(pos, &cu->tool_list, tool_node)
printf("\t&kretprobe__%s,\n", pos->name);
printf("\t&kretprobe__%s,\n", function__name(pos, cu));
return 0;
}

View File

@ -23,15 +23,15 @@ static int show_cc_inlined;
static int show_cc_uninlined;
struct fn_stats {
struct list_head node;
const struct function *function;
const struct cu *cu;
uint32_t nr_expansions;
uint32_t size_expansions;
uint32_t nr_files;
struct list_head node;
struct function *function;
const struct cu *cu;
uint32_t nr_expansions;
uint32_t size_expansions;
uint32_t nr_files;
};
static struct fn_stats *fn_stats__new(const struct function *function,
static struct fn_stats *fn_stats__new(struct function *function,
const struct cu *cu)
{
struct fn_stats *self = malloc(sizeof(*self));
@ -54,12 +54,12 @@ static struct fn_stats *fn_stats__find(const char *name)
struct fn_stats *pos;
list_for_each_entry(pos, &fn_stats__list, node)
if (strcmp(pos->function->name, name) == 0)
if (strcmp(function__name(pos->function, pos->cu), name) == 0)
return pos;
return NULL;
}
static void fn_stats__add(const struct function *function, const struct cu *cu)
static void fn_stats__add(struct function *function, const struct cu *cu)
{
struct fn_stats *inl = fn_stats__new(function, cu);
if (inl != NULL)
@ -69,7 +69,7 @@ static void fn_stats__add(const struct function *function, const struct cu *cu)
static void fn_stats_inline_exps_fmtr(const struct fn_stats *self)
{
if (self->function->lexblock.nr_inline_expansions > 0)
printf("%s: %u %u\n", self->function->name,
printf("%s: %u %u\n", function__name(self->function, self->cu),
self->function->lexblock.nr_inline_expansions,
self->function->lexblock.size_inline_expansions);
}
@ -77,33 +77,35 @@ static void fn_stats_inline_exps_fmtr(const struct fn_stats *self)
static void fn_stats_labels_fmtr(const struct fn_stats *self)
{
if (self->function->lexblock.nr_labels > 0)
printf("%s: %u\n", self->function->name,
printf("%s: %u\n", function__name(self->function, self->cu),
self->function->lexblock.nr_labels);
}
static void fn_stats_variables_fmtr(const struct fn_stats *self)
{
if (self->function->lexblock.nr_variables > 0)
printf("%s: %u\n", self->function->name,
printf("%s: %u\n", function__name(self->function, self->cu),
self->function->lexblock.nr_variables);
}
static void fn_stats_nr_parms_fmtr(const struct fn_stats *self)
{
printf("%s: %u\n", self->function->name,
printf("%s: %u\n", function__name(self->function, self->cu),
self->function->proto.nr_parms);
}
static void fn_stats_name_len_fmtr(const struct fn_stats *self)
{
printf("%s: %u\n", self->function->name, strlen(self->function->name));
const char *name = function__name(self->function, self->cu);
printf("%s: %u\n", name, strlen(name));
}
static void fn_stats_size_fmtr(const struct fn_stats *self)
{
const size_t size = function__size(self->function);
if (size != 0)
printf("%s: %u\n", self->function->name, size);
printf("%s: %u\n", function__name(self->function, self->cu),
size);
}
static void fn_stats_fmtr(const struct fn_stats *self)
@ -114,7 +116,7 @@ static void fn_stats_fmtr(const struct fn_stats *self)
printf("/* definitions: %u */\n", self->nr_files);
putchar('\n');
} else
puts(self->function->name);
puts(function__name(self->function, self->cu));
}
static void print_fn_stats(void (*formatter)(const struct fn_stats *f))
@ -128,7 +130,8 @@ static void print_fn_stats(void (*formatter)(const struct fn_stats *f))
static void fn_stats_inline_stats_fmtr(const struct fn_stats *self)
{
if (self->nr_expansions > 1)
printf("%-31.31s %6lu %7lu %6lu %6u\n", self->function->name,
printf("%-31.31s %6lu %7lu %6lu %6u\n",
function__name(self->function, self->cu),
self->size_expansions, self->nr_expansions,
self->size_expansions / self->nr_expansions,
self->nr_files);
@ -141,9 +144,9 @@ static void print_total_inline_stats(void)
print_fn_stats(fn_stats_inline_stats_fmtr);
}
static void fn_stats__dupmsg(const struct function *self,
static void fn_stats__dupmsg(struct function *self,
const struct cu *self_cu,
const struct function *dup,
struct function *dup,
const struct cu *dup_cu,
char *hdr, const char *fmt, ...)
{
@ -151,7 +154,9 @@ static void fn_stats__dupmsg(const struct function *self,
if (!*hdr)
printf("function: %s\nfirst: %s\ncurrent: %s\n",
self->name, self_cu->name, dup_cu->name);
function__name(self, self_cu),
self_cu->name,
function__name(dup, dup_cu));
va_start(args, fmt);
vprintf(fmt, args);
@ -159,9 +164,9 @@ static void fn_stats__dupmsg(const struct function *self,
*hdr = 1;
}
static void fn_stats__chkdupdef(const struct function *self,
static void fn_stats__chkdupdef(struct function *self,
const struct cu *self_cu,
const struct function *dup,
struct function *dup,
const struct cu *dup_cu)
{
char hdr = 0;
@ -189,12 +194,14 @@ static struct tag *function__filter(struct tag *tag, struct cu *cu,
{
struct function *function;
struct fn_stats *fstats;
const char *name;
if (tag->tag != DW_TAG_subprogram)
return NULL;
function = tag__function(tag);
if (function->name == NULL)
name = function__name(function, cu);
if (name == NULL)
return NULL;
if (show_externals && !function->external)
@ -207,7 +214,7 @@ static struct tag *function__filter(struct tag *tag, struct cu *cu,
if (show_cc_inlined && function->inlined != DW_INL_inlined)
return NULL;
fstats = fn_stats__find(function->name);
fstats = fn_stats__find(name);
if (fstats != NULL && fstats->function->external) {
fn_stats__chkdupdef(fstats->function, fstats->cu, function, cu);
fstats->nr_expansions += function->cu_total_nr_inline_expansions;
@ -247,7 +254,7 @@ static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
if (verbose)
function__print(function, cu, 1, 0, 0);
else
printf("%s\n", function->name ?: "");
printf("%s\n", function__name(function, cu));
}
return 0;
}
@ -270,8 +277,7 @@ static int function_iterator(struct tag *tag, struct cu *cu, void *cookie)
return 0;
function = tag__function(tag);
if (function->name != NULL &&
strcmp(function->name, cookie) == 0) {
if (strcmp(function__name(function, cu), cookie) == 0) {
function__print(function, cu, 1, show_variables,
show_inline_expansions);
return 1;