[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:
Arnaldo Carvalho de Melo 2006-10-31 17:23:16 -03:00
parent 0ca9826e36
commit 5aaca80de6
4 changed files with 109 additions and 76 deletions

View File

@ -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)

View File

@ -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_ */

View File

@ -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;

View File

@ -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;
} }