[CLASSES]: Rework the find_by routines
So that we can find all the cus for some specific class (cus__find_class_by_name), or traverse all the CUs (cus__for_each_cu), etc. Now we don't look at just the first CU in multi-CU files (vmlinux, etc). Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
This commit is contained in:
parent
0ca9826e36
commit
5aaca80de6
75
classes.c
75
classes.c
@ -61,7 +61,7 @@ static const char *tag_name(const unsigned int tag)
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
struct class *cu__find_by_name(struct cu *self, const char *name)
|
struct class *cu__find_class_by_name(struct cu *self, const char *name)
|
||||||
{
|
{
|
||||||
struct class *pos;
|
struct class *pos;
|
||||||
|
|
||||||
@ -72,22 +72,27 @@ struct class *cu__find_by_name(struct cu *self, const char *name)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct class *cu__find_by_id(const struct cu *self, const unsigned int id)
|
struct class *cus__find_class_by_name(struct cu **cu, const char *name)
|
||||||
{
|
{
|
||||||
struct class *pos;
|
struct cu *cu_pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->classes, node)
|
list_for_each_entry(cu_pos, &cus__list, node) {
|
||||||
if (pos->id == id)
|
struct class *class = cu__find_class_by_name(cu_pos, name);
|
||||||
return pos;
|
|
||||||
|
if (class != NULL) {
|
||||||
|
*cu = cu_pos;
|
||||||
|
return class;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cu *cus__find_by_id(const unsigned int id)
|
struct class *cu__find_class_by_id(const struct cu *self, const unsigned int id)
|
||||||
{
|
{
|
||||||
struct cu *pos;
|
struct class *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &cus__list, node)
|
list_for_each_entry(pos, &self->classes, node)
|
||||||
if (pos->id == id)
|
if (pos->id == id)
|
||||||
return pos;
|
return pos;
|
||||||
|
|
||||||
@ -100,7 +105,7 @@ static const unsigned long class__size(const struct class *self,
|
|||||||
unsigned long size = self->size;
|
unsigned long size = self->size;
|
||||||
|
|
||||||
if (self->tag != DW_TAG_pointer_type && self->type != 0) {
|
if (self->tag != DW_TAG_pointer_type && self->type != 0) {
|
||||||
struct class *class = cu__find_by_id(cu, self->type);
|
struct class *class = cu__find_class_by_id(cu, self->type);
|
||||||
|
|
||||||
if (class != NULL)
|
if (class != NULL)
|
||||||
size = class__size(class, cu);
|
size = class__size(class, cu);
|
||||||
@ -119,7 +124,8 @@ static const char *class__name(struct class *self, const struct cu *cu,
|
|||||||
if (self->type == 0) /* No type == void */
|
if (self->type == 0) /* No type == void */
|
||||||
strncpy(bf, "void *", len);
|
strncpy(bf, "void *", len);
|
||||||
else {
|
else {
|
||||||
struct class *ptr_class = cu__find_by_id(cu, self->type);
|
struct class *ptr_class =
|
||||||
|
cu__find_class_by_id(cu, self->type);
|
||||||
|
|
||||||
if (ptr_class != NULL) {
|
if (ptr_class != NULL) {
|
||||||
char ptr_class_name[128];
|
char ptr_class_name[128];
|
||||||
@ -131,7 +137,7 @@ static const char *class__name(struct class *self, const struct cu *cu,
|
|||||||
}
|
}
|
||||||
} else if (self->tag == DW_TAG_volatile_type ||
|
} else if (self->tag == DW_TAG_volatile_type ||
|
||||||
self->tag == DW_TAG_const_type) {
|
self->tag == DW_TAG_const_type) {
|
||||||
struct class *vol_class = cu__find_by_id(cu, self->type);
|
struct class *vol_class = cu__find_class_by_id(cu, self->type);
|
||||||
|
|
||||||
if (vol_class != NULL) {
|
if (vol_class != NULL) {
|
||||||
char vol_class_name[128];
|
char vol_class_name[128];
|
||||||
@ -143,7 +149,7 @@ static const char *class__name(struct class *self, const struct cu *cu,
|
|||||||
sizeof(vol_class_name)));
|
sizeof(vol_class_name)));
|
||||||
}
|
}
|
||||||
} else if (self->tag == DW_TAG_array_type) {
|
} else if (self->tag == DW_TAG_array_type) {
|
||||||
struct class *ptr_class = cu__find_by_id(cu, self->type);
|
struct class *ptr_class = cu__find_class_by_id(cu, self->type);
|
||||||
|
|
||||||
if (ptr_class != NULL)
|
if (ptr_class != NULL)
|
||||||
return class__name(ptr_class, cu, bf, len);
|
return class__name(ptr_class, cu, bf, len);
|
||||||
@ -176,14 +182,14 @@ static struct class_member *class_member__new(uintmax_t type,
|
|||||||
static int class_member__size(const struct class_member *self,
|
static int class_member__size(const struct class_member *self,
|
||||||
const struct cu *cu)
|
const struct cu *cu)
|
||||||
{
|
{
|
||||||
struct class *class = cu__find_by_id(cu, self->type);
|
struct class *class = cu__find_class_by_id(cu, self->type);
|
||||||
return class != NULL ? class__size(class, cu) : -1;
|
return class != NULL ? class__size(class, cu) : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long class_member__print(struct class_member *self,
|
static unsigned long class_member__print(struct class_member *self,
|
||||||
const struct cu *cu)
|
const struct cu *cu)
|
||||||
{
|
{
|
||||||
struct class *class = cu__find_by_id(cu, self->type);
|
struct class *class = cu__find_class_by_id(cu, self->type);
|
||||||
char class_name_bf[128];
|
char class_name_bf[128];
|
||||||
char member_name_bf[128];
|
char member_name_bf[128];
|
||||||
char bf[512];
|
char bf[512];
|
||||||
@ -200,7 +206,8 @@ static unsigned long class_member__print(struct class_member *self,
|
|||||||
|
|
||||||
/* Is it a function pointer? */
|
/* Is it a function pointer? */
|
||||||
if (class->tag == DW_TAG_pointer_type) {
|
if (class->tag == DW_TAG_pointer_type) {
|
||||||
struct class *ptr_class = cu__find_by_id(cu, class->type);
|
struct class *ptr_class =
|
||||||
|
cu__find_class_by_id(cu, class->type);
|
||||||
|
|
||||||
if (ptr_class != NULL &&
|
if (ptr_class != NULL &&
|
||||||
ptr_class->tag == DW_TAG_subroutine_type) {
|
ptr_class->tag == DW_TAG_subroutine_type) {
|
||||||
@ -209,7 +216,8 @@ static unsigned long class_member__print(struct class_member *self,
|
|||||||
strcpy(bf, "void");
|
strcpy(bf, "void");
|
||||||
else {
|
else {
|
||||||
struct class *ret_class =
|
struct class *ret_class =
|
||||||
cu__find_by_id(cu, ptr_class->type);
|
cu__find_class_by_id(cu,
|
||||||
|
ptr_class->type);
|
||||||
|
|
||||||
if (ret_class != NULL)
|
if (ret_class != NULL)
|
||||||
class_name = class__name(ret_class, cu,
|
class_name = class__name(ret_class, cu,
|
||||||
@ -324,7 +332,7 @@ static void class__print_function(struct class *self, const struct cu *cu)
|
|||||||
if (self->type == 0)
|
if (self->type == 0)
|
||||||
type = "void";
|
type = "void";
|
||||||
else {
|
else {
|
||||||
class_type = cu__find_by_id(cu, self->type);
|
class_type = cu__find_class_by_id(cu, self->type);
|
||||||
if (class_type != NULL)
|
if (class_type != NULL)
|
||||||
type = class__name(class_type, cu, bf, sizeof(bf));
|
type = class__name(class_type, cu, bf, sizeof(bf));
|
||||||
}
|
}
|
||||||
@ -336,7 +344,7 @@ static void class__print_function(struct class *self, const struct cu *cu)
|
|||||||
else
|
else
|
||||||
first_parameter = 0;
|
first_parameter = 0;
|
||||||
type = "<ERROR>";
|
type = "<ERROR>";
|
||||||
class_type = cu__find_by_id(cu, pos->type);
|
class_type = cu__find_class_by_id(cu, pos->type);
|
||||||
if (class_type != NULL)
|
if (class_type != NULL)
|
||||||
type = class__name(class_type, cu, bf, sizeof(bf));
|
type = class__name(class_type, cu, bf, sizeof(bf));
|
||||||
printf("%s %s", type, pos->name);
|
printf("%s %s", type, pos->name);
|
||||||
@ -417,18 +425,29 @@ void class__print(struct class *self, const struct cu *cu)
|
|||||||
putchar('\n');
|
putchar('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
void classes__for_each(int (*iterator)(struct class *class, void *cookie),
|
int cu__for_each_class(struct cu *cu,
|
||||||
void *cookie)
|
int (*iterator)(struct cu *cu,
|
||||||
|
struct class *class,
|
||||||
|
void *cookie),
|
||||||
|
void *cookie)
|
||||||
{
|
{
|
||||||
struct cu *cu_pos;
|
|
||||||
|
|
||||||
list_for_each_entry(cu_pos, &cus__list, node) {
|
struct class *pos;
|
||||||
struct class *class_pos;
|
|
||||||
|
|
||||||
list_for_each_entry(class_pos, &cu_pos->classes, node)
|
list_for_each_entry(pos, &cu->classes, node)
|
||||||
if (iterator(class_pos, cookie))
|
if (iterator(cu, pos, cookie))
|
||||||
break;
|
return 1;
|
||||||
}
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cus__for_each_cu(int (*iterator)(struct cu *cu, void *cookie),
|
||||||
|
void *cookie)
|
||||||
|
{
|
||||||
|
struct cu *pos;
|
||||||
|
|
||||||
|
list_for_each_entry(pos, &cus__list, node)
|
||||||
|
if (iterator(pos, cookie))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void classes__print(const unsigned int tag)
|
void classes__print(const unsigned int tag)
|
||||||
|
18
classes.h
18
classes.h
@ -53,13 +53,19 @@ extern void class__find_holes(struct class *self, const struct cu *cu);
|
|||||||
extern void class__print(struct class *self, const struct cu *cu);
|
extern void class__print(struct class *self, const struct cu *cu);
|
||||||
|
|
||||||
extern int classes__load(const char *filename);
|
extern int classes__load(const char *filename);
|
||||||
extern struct cu *cus__find_by_id(const unsigned int type);
|
extern struct cu *cus__find_cu_by_id(const unsigned int type);
|
||||||
extern struct class *cu__find_by_id(struct cu *cu, const unsigned int type);
|
extern struct class *cu__find_class_by_id(const struct cu *cu,
|
||||||
extern struct class *cu__find_by_name(struct cu *cu, const char *name);
|
const unsigned int type);
|
||||||
|
extern struct class *cu__find_class_by_name(struct cu *cu, const char *name);
|
||||||
extern void classes__print(const unsigned int tag);
|
extern void classes__print(const unsigned int tag);
|
||||||
extern void classes__for_each(int (*iterator)(struct class *class,
|
extern struct class *cus__find_class_by_name(struct cu **cu, const char *name);
|
||||||
struct cu *cu,
|
extern int cu__for_each_class(struct cu *cu,
|
||||||
void *cookie),
|
int (*iterator)(struct cu *cu,
|
||||||
|
struct class *class,
|
||||||
|
void *cookie),
|
||||||
|
void *cookie);
|
||||||
|
extern void cus__for_each_cu(int (*iterator)(struct cu *cu,
|
||||||
|
void *cookie),
|
||||||
void *cookie);
|
void *cookie);
|
||||||
|
|
||||||
#endif /* _PAHOLE_CLASSES_H_ */
|
#endif /* _PAHOLE_CLASSES_H_ */
|
||||||
|
16
pahole.c
16
pahole.c
@ -30,17 +30,13 @@ int main(int argc, char *argv[])
|
|||||||
if (argc == 2)
|
if (argc == 2)
|
||||||
classes__print(DW_TAG_structure_type);
|
classes__print(DW_TAG_structure_type);
|
||||||
else {
|
else {
|
||||||
struct cu *cu = cus__find_by_id(0);
|
struct cu *cu;
|
||||||
|
struct class *class = cus__find_class_by_name(&cu, argv[2]);
|
||||||
if (cu != NULL) {
|
if (class != NULL) {
|
||||||
struct class *class = cu__find_by_name(argv[2]);
|
class__find_holes(class, cu);
|
||||||
if (class != NULL) {
|
class__print(class, cu);
|
||||||
class__find_holes(class, cu);
|
|
||||||
class__print(class, cu);
|
|
||||||
} else
|
|
||||||
printf("struct %s not found!\n", argv[2]);
|
|
||||||
} else
|
} else
|
||||||
printf("cu 0 not found!\n");
|
printf("struct %s not found!\n", argv[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
76
pfunct.c
76
pfunct.c
@ -40,10 +40,10 @@ static int class__has_parameter_of_type(struct cu *cu, struct class *self,
|
|||||||
struct class_member *pos;
|
struct class_member *pos;
|
||||||
|
|
||||||
list_for_each_entry(pos, &self->members, node) {
|
list_for_each_entry(pos, &self->members, node) {
|
||||||
struct class *class = cu__find_by_id(cu, pos->type);
|
struct class *class = cu__find_class_by_id(cu, pos->type);
|
||||||
|
|
||||||
if (class != NULL && class->tag == DW_TAG_pointer_type) {
|
if (class != NULL && class->tag == DW_TAG_pointer_type) {
|
||||||
class = cu__find_by_id(cu, class->type);
|
class = cu__find_class_by_id(cu, class->type);
|
||||||
if (class != NULL &&
|
if (class != NULL &&
|
||||||
class->id == target->id)
|
class->id == target->id)
|
||||||
return 1;
|
return 1;
|
||||||
@ -52,7 +52,7 @@ static int class__has_parameter_of_type(struct cu *cu, struct class *self,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int class_iterator(struct class *class, struct cu *cu, void *cookie)
|
static int class_iterator(struct cu *cu, struct class *class, void *cookie)
|
||||||
{
|
{
|
||||||
if (class->tag != DW_TAG_subprogram || class->inlined)
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
||||||
return 0;
|
return 0;
|
||||||
@ -66,7 +66,17 @@ static int class_iterator(struct class *class, struct cu *cu, void *cookie)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sizes_iterator(struct class *class, struct cu *cu, void *cookie)
|
static int cu_class_iterator(struct cu *cu, void *cookie)
|
||||||
|
{
|
||||||
|
struct class *target = cu__find_class_by_name(cu, cookie);
|
||||||
|
|
||||||
|
if (target == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return cu__for_each_class(cu, class_iterator, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sizes_iterator(struct cu *cu, struct class *class, void *cookie)
|
||||||
{
|
{
|
||||||
if (class->tag != DW_TAG_subprogram || class->inlined)
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
||||||
return 0;
|
return 0;
|
||||||
@ -75,12 +85,34 @@ static int sizes_iterator(struct class *class, struct cu *cu, void *cookie)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cu_sizes_iterator(struct cu *cu, void *cookie)
|
||||||
|
{
|
||||||
|
return cu__for_each_class(cu, sizes_iterator, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int function_iterator(struct cu *cu, struct class *class, void *cookie)
|
||||||
|
{
|
||||||
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (strcmp(class->name, cookie) == 0) {
|
||||||
|
class__print(class, cu);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cu_function_iterator(struct cu *cu, void *cookie)
|
||||||
|
{
|
||||||
|
return cu__for_each_class(cu, function_iterator, cookie);
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
int option, option_index;
|
int option, option_index;
|
||||||
const char *file_name = NULL;
|
const char *file_name = NULL;
|
||||||
const char *class_name = NULL;
|
char *class_name = NULL;
|
||||||
const char *function_name = NULL;
|
char *function_name = NULL;
|
||||||
int show_sizes = 0;
|
int show_sizes = 0;
|
||||||
|
|
||||||
while ((option = getopt_long(argc, argv, "c:sV",
|
while ((option = getopt_long(argc, argv, "c:sV",
|
||||||
@ -108,33 +140,13 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (show_sizes)
|
if (show_sizes)
|
||||||
classes__for_each(sizes_iterator, NULL);
|
cus__for_each_cu(cu_sizes_iterator, NULL);
|
||||||
else if (class_name != NULL) {
|
else if (class_name != NULL)
|
||||||
struct cu *cu = cus__find_by_id(0);
|
cus__for_each_cu(cu_class_iterator, class_name);
|
||||||
|
else if (function_name == NULL)
|
||||||
if (cu != NULL) {
|
|
||||||
struct class *class = cu__find_by_name(cu, class_name);
|
|
||||||
|
|
||||||
if (class != NULL)
|
|
||||||
classes__for_each(class_iterator, class);
|
|
||||||
else
|
|
||||||
printf("class %s not found!\n", class_name);
|
|
||||||
} else
|
|
||||||
printf("cu 0 not found!\n");
|
|
||||||
} else if (function_name == NULL)
|
|
||||||
classes__print(DW_TAG_subprogram);
|
classes__print(DW_TAG_subprogram);
|
||||||
else {
|
else
|
||||||
struct cu *cu = cus__find_by_id(0);
|
cus__for_each_cu(cu_function_iterator, function_name);
|
||||||
|
|
||||||
if (cu != NULL) {
|
|
||||||
struct class *class = cu__find_by_name(cu, function_name);
|
|
||||||
if (class != NULL)
|
|
||||||
class__print(class, cu);
|
|
||||||
else
|
|
||||||
printf("function %s not found!\n", function_name);
|
|
||||||
} else
|
|
||||||
printf("cu 0 not found!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user