[CLASSES]: Introduce DW_TAG_subroutine_type specific parser
So that we handle DW_TAG_formal_parameters in this tag, fixing these cases: --- /tmp/ctracer.c.before 2006-12-29 13:27:24.000000000 -0200 +++ /tmp/ctracer.c 2007-01-02 02:34:18.000000000 -0200 <SNIP> @@ -62,7 +62,7 @@ }; /* size: 68, cachelines: 3 */ /* last cacheline: 4 bytes */ -typedef int (*kretprobe_handler_t)(void /* FIXME: add parm list */); +typedef int (*kretprobe_handler_t)(struct kretprobe_instance *, struct pt_regs *); /* /pub/scm/linux/kernel/git/acme/linux-2.6/include/linux/list.h:607 */ struct hlist_head { struct hlist_node * first; /* 0 4 */ [acme@newtoy ctracer_example]$ --- /tmp/pfunct.before 2006-12-30 16:18:25.000000000 -0200 +++ /tmp/pfunct.after 2007-01-02 02:08:50.000000000 -0200 @@ -249,7 +249,7 @@ /* definitions: 1 */ /* /pub/scm/linux/kernel/git/acme/linux-2.6/lib/klist.c:57 */ -void klist_init(struct klist * k, * get, * put); +void klist_init(struct klist * k, void (*get)(struct klist_node *), void (*put)(struct klist_node *)); /* size: 12, inline expansions: 1 (5 bytes) */ /* definitions: 1 */ The struct/union case still needs fixing, but we're getting there... Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
parent
0f5b2d57ce
commit
8a4df0e070
144
classes.c
144
classes.c
|
@ -678,23 +678,6 @@ static size_t class_member__size(const struct class_member *self)
|
|||
return tag__size(type, self->class->cu);
|
||||
}
|
||||
|
||||
const char *tag__subroutine_mask(const struct tag *self,
|
||||
const struct cu *cu,
|
||||
char *bf, size_t len, int is_pointer)
|
||||
{
|
||||
char ret_type_name[128];
|
||||
|
||||
if (self->type == 0)
|
||||
snprintf(ret_type_name, sizeof(ret_type_name), "void");
|
||||
else {
|
||||
struct tag *ret_type = cu__find_tag_by_id(cu, self->type);
|
||||
tag__name(ret_type, cu, ret_type_name, sizeof(ret_type_name));
|
||||
}
|
||||
snprintf(bf, len, "%s (%s%%s)(void /* FIXME: add parm list */)",
|
||||
ret_type_name, is_pointer ? "*" : "");
|
||||
return bf;
|
||||
}
|
||||
|
||||
size_t class_member__names(const struct tag *type,
|
||||
const struct class_member *self,
|
||||
char *class_name, size_t class_name_size,
|
||||
|
@ -1014,6 +997,19 @@ static ftype__init(struct ftype *self, uint16_t tag,
|
|||
|
||||
tag__init(&self->tag, tag, id, type, decl_file, decl_line);
|
||||
INIT_LIST_HEAD(&self->parms);
|
||||
self->nr_parms = 0;
|
||||
self->unspec_parms = 0;
|
||||
}
|
||||
|
||||
static struct ftype *ftype__new(uint16_t tag, Dwarf_Off id, Dwarf_Off type,
|
||||
const char *decl_file, uint32_t decl_line)
|
||||
{
|
||||
struct ftype *self = malloc(sizeof(*self));
|
||||
|
||||
if (self != NULL)
|
||||
ftype__init(self, tag, id, type, decl_file, decl_line);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static struct function *function__new(Dwarf_Off id, Dwarf_Off type,
|
||||
|
@ -1026,7 +1022,7 @@ static struct function *function__new(Dwarf_Off id, Dwarf_Off type,
|
|||
|
||||
if (self != NULL) {
|
||||
ftype__init(&self->proto, DW_TAG_subprogram, id, type,
|
||||
decl_file, decl_line);
|
||||
decl_file, decl_line);
|
||||
lexblock__init(&self->lexblock);
|
||||
self->name = strings__add(name);
|
||||
self->inlined = inlined;
|
||||
|
@ -1320,7 +1316,8 @@ static void function__print_body(const struct function *self,
|
|||
|
||||
static size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
|
||||
char *bf, const size_t len,
|
||||
const char *name, const uint8_t inlined)
|
||||
const char *name, const int inlined,
|
||||
const int is_pointer)
|
||||
{
|
||||
struct parameter *pos;
|
||||
struct tag *type = cu__find_tag_by_id(cu, self->tag.type);
|
||||
|
@ -1328,8 +1325,11 @@ static size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
|
|||
char *s = bf, sbf[128];
|
||||
size_t l = len;
|
||||
const char *stype = tag__name(type, cu, sbf, sizeof(sbf));
|
||||
size_t n = snprintf(s, l, "%s%s %s(", inlined ? "inline " : "",
|
||||
stype, name ?: "");
|
||||
size_t n = snprintf(s, l, "%s%s %s%s%s%s(", inlined ? "inline " : "",
|
||||
stype,
|
||||
self->tag.tag == DW_TAG_subroutine_type ? "(" : "",
|
||||
is_pointer ? "*" : "", name ?: "",
|
||||
self->tag.tag == DW_TAG_subroutine_type ? ")" : "");
|
||||
s += n; l -= n;
|
||||
|
||||
list_for_each_entry(pos, &self->parms, tag.node) {
|
||||
|
@ -1339,22 +1339,37 @@ static size_t ftype__snprintf(const struct ftype *self, const struct cu *cu,
|
|||
} else
|
||||
first_parm = 0;
|
||||
type = cu__find_tag_by_id(cu, pos->tag.type);
|
||||
if (type->tag == DW_TAG_pointer_type) {
|
||||
if (type->type != 0) {
|
||||
struct tag *ptype =
|
||||
cu__find_tag_by_id(cu, type->type);
|
||||
if (ptype->tag == DW_TAG_subroutine_type) {
|
||||
n = ftype__snprintf(tag__ftype(ptype),
|
||||
cu, s, l,
|
||||
pos->name, 0, 1);
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
} else if (type->tag == DW_TAG_subroutine_type) {
|
||||
n = ftype__snprintf(tag__ftype(type), cu, s, l,
|
||||
pos->name, 0, 0);
|
||||
goto next;
|
||||
}
|
||||
stype = tag__name(type, cu, sbf, sizeof(sbf));
|
||||
n = snprintf(s, l, "%s %s", stype, pos->name);
|
||||
n = snprintf(s, l, "%s%s%s", stype,
|
||||
pos->name ? " " : "", pos->name ?: "");
|
||||
next:
|
||||
s += n; l -= n;
|
||||
}
|
||||
|
||||
/* No parameters? */
|
||||
if (first_parm) {
|
||||
n = snprintf(s, l, "void");
|
||||
s += n; l -= n;
|
||||
}
|
||||
else if (self->unspec_parms) {
|
||||
n = snprintf(s, l, ", ...");
|
||||
s += n; l -= n;
|
||||
}
|
||||
n = snprintf(s, l, ");\n", stdout);
|
||||
return len - l - n;
|
||||
if (first_parm)
|
||||
n = snprintf(s, l, "void)");
|
||||
else if (self->unspec_parms)
|
||||
n = snprintf(s, l, ", ...)");
|
||||
else
|
||||
n = snprintf(s, l, ")");
|
||||
return len - (l - n);
|
||||
}
|
||||
|
||||
void function__print(const struct function *self, int show_stats,
|
||||
|
@ -1368,13 +1383,16 @@ void function__print(const struct function *self, int show_stats,
|
|||
printf("/* %s:%u */\n", self->proto.tag.decl_file,
|
||||
self->proto.tag.decl_line);
|
||||
|
||||
ftype__snprintf(&self->proto, self->cu, bf, sizeof(bf), self->name,
|
||||
function__declared_inline(self));
|
||||
ftype__snprintf(&self->proto, self->cu, bf, sizeof(bf),
|
||||
self->name, function__declared_inline(self), 0);
|
||||
fputs(bf, stdout);
|
||||
|
||||
if (show_variables || show_inline_expansions)
|
||||
if (show_variables || show_inline_expansions) {
|
||||
putchar('\n');
|
||||
function__print_body(self, show_variables,
|
||||
show_inline_expansions, 1);
|
||||
} else
|
||||
puts(";");
|
||||
|
||||
if (show_stats) {
|
||||
printf("/* size: %llu", self->high_pc - self->low_pc);
|
||||
|
@ -1857,6 +1875,51 @@ static void cu__create_new_array(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu,
|
|||
cu__add_tag(cu, &array->tag);
|
||||
}
|
||||
|
||||
static void cu__new_subroutine_type(Dwarf *dwarf, Dwarf_Die *die,
|
||||
struct cu *cu,
|
||||
Dwarf_Off cu_offset, Dwarf_Off type,
|
||||
const char *decl_file, int decl_line)
|
||||
{
|
||||
Dwarf_Die child;
|
||||
struct ftype *ftype = ftype__new(DW_TAG_subroutine_type,
|
||||
cu_offset, type,
|
||||
decl_file, decl_line);
|
||||
if (ftype == NULL)
|
||||
oom("ftype__new");
|
||||
|
||||
if (!dwarf_haschildren(die) || dwarf_child(die, &child) != 0)
|
||||
goto out;
|
||||
|
||||
die = &child;
|
||||
do {
|
||||
const uint16_t tag = dwarf_tag(die);
|
||||
Dwarf_Attribute attr_name;
|
||||
struct parameter *parm;
|
||||
uint32_t decl_line;
|
||||
|
||||
if (tag != DW_TAG_formal_parameter) {
|
||||
fprintf(stderr, "%s: DW_TAG_%s not handled!\n",
|
||||
__FUNCTION__, dwarf_tag_name(tag));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
dwarf_decl_line(die, &decl_line);
|
||||
parm = parameter__new(dwarf_cuoffset(die),
|
||||
attr_numeric(die, DW_AT_type),
|
||||
dwarf_decl_file(die),
|
||||
decl_line,
|
||||
attr_string(die, DW_AT_name,
|
||||
&attr_name));
|
||||
if (parm == NULL)
|
||||
oom("parameter__new");
|
||||
|
||||
ftype__add_parameter(ftype, parm);
|
||||
} while (dwarf_siblingof(die, die) == 0);
|
||||
out:
|
||||
cu__add_tag(cu, &ftype->tag);
|
||||
}
|
||||
|
||||
static void cu__process_class(Dwarf *dwarf, Dwarf_Die *die, struct class *class,
|
||||
struct cu *cu)
|
||||
{
|
||||
|
@ -2177,6 +2240,10 @@ static void cu__process_die(Dwarf *dwarf, Dwarf_Die *die, struct cu *cu)
|
|||
cu__create_new_array(dwarf, die, cu, cu_offset, type,
|
||||
decl_file, decl_line);
|
||||
goto next_sibling;
|
||||
case DW_TAG_subroutine_type:
|
||||
cu__new_subroutine_type(dwarf, die, cu, cu_offset, type,
|
||||
decl_file, decl_line);
|
||||
goto next_sibling;
|
||||
case DW_TAG_enumeration_type:
|
||||
cu__create_new_enumeration(dwarf, die, cu, cu_offset, type,
|
||||
decl_file, decl_line, name);
|
||||
|
@ -2340,11 +2407,10 @@ static int cus__emit_typedef_definitions(struct cus *self, struct tag *tdef)
|
|||
is_pointer = 1;
|
||||
/* Fall thru */
|
||||
case DW_TAG_subroutine_type:
|
||||
tag__subroutine_mask(type, class->cu, bf, sizeof(bf),
|
||||
is_pointer);
|
||||
ftype__snprintf(tag__ftype(type), class->cu, bf, sizeof(bf),
|
||||
class->name, 0, is_pointer);
|
||||
fputs("typedef ", stdout);
|
||||
printf(bf, class->name);
|
||||
puts(";");
|
||||
printf("%s;\n", bf);
|
||||
goto out;
|
||||
case DW_TAG_structure_type: {
|
||||
struct class *ctype = tag__class(type);
|
||||
|
|
|
@ -131,9 +131,14 @@ struct ftype {
|
|||
struct tag tag;
|
||||
struct list_head parms;
|
||||
uint16_t nr_parms;
|
||||
uint8_t unspec_parms:1;
|
||||
uint8_t unspec_parms; /* just one bit is needed */
|
||||
};
|
||||
|
||||
static inline struct ftype *tag__ftype(const struct tag *self)
|
||||
{
|
||||
return (struct ftype *)self;
|
||||
}
|
||||
|
||||
struct function {
|
||||
struct ftype proto;
|
||||
struct cu *cu;
|
||||
|
|
Loading…
Reference in New Issue