[PAHOLE]: Implement type expansion
What is in a struct... [acme@filo pahole]$ pahole net/ipv6/tcp_ipv6.o delayed_work /* <2bc9> /home/acme/git/linux-2.6/include/linux/workqueue.h:37 */ struct delayed_work { struct work_struct work; /* 0 16 */ struct timer_list timer; /* 16 24 */ }; /* size: 40, cachelines: 1 */ /* last cacheline: 40 bytes */ [acme@filo pahole]$ Oh, but what if we want to unfold all the structs? lo pahole]$ pahole --expand_types /home/acme/git/OUTPUT/qemu/linux-2.6/net/ipv6/tcp_ipv6.o delayed_work /* <2bc9> /home/acme/git/linux-2.6/include/linux/workqueue.h:37 */ struct delayed_work { struct work_struct { atomic_long_t data; /* 0 4 */ struct list_head { struct list_head * next; /* 0 4 */ struct list_head * prev; /* 4 4 */ } entry; /* 4 8 */ work_func_t func; /* 12 4 */ } work; /* 0 16 */ struct timer_list { struct list_head { struct list_head * next; /* 0 4 */ struct list_head * prev; /* 4 4 */ } entry; /* 0 8 */ long unsigned int expires; /* 8 4 */ void (*function)(long unsigned int); /* 12 4 */ long unsigned int data; /* 16 4 */ struct tvec_t_base_s * base; /* 20 4 */ } timer; /* 16 24 */ }; /* size: 40, cachelines: 1 */ /* last cacheline: 40 bytes */ [acme@filo pahole]$ Quick hack, as we already had all the needed infrastructure due to anonymous struct printing inside structs/unions, now for the curious, if you have the kernel-debuginfo package installed in your FC6 machine: [acme@filo pahole]$ pahole --expand_types /usr/lib/debug/lib/modules/2.6.19-1.2895.fc6/kernel/net/ipv6/ipv6.ko.debug tcp6_sock Try struct task_struct too 8-) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
f426dc12f2
commit
2de67fcaf4
|
@ -301,7 +301,7 @@ static void emit_function_defs(const char *fn)
|
|||
if (f != NULL) {
|
||||
cus__emit_ftype_definitions(kprobes_cus, cu,
|
||||
&tag__function(f)->proto);
|
||||
tag__print(f, cu, NULL, NULL);
|
||||
tag__print(f, cu, NULL, NULL, 0);
|
||||
puts(";\n");
|
||||
}
|
||||
}
|
||||
|
|
64
dwarves.c
64
dwarves.c
|
@ -1054,17 +1054,20 @@ static struct label *label__new(Dwarf_Die *die)
|
|||
|
||||
static size_t union__snprintf(const struct type *self, const struct cu *cu,
|
||||
char *bf, size_t len, const char *prefix,
|
||||
const char *suffix, uint8_t indent,
|
||||
size_t type_spacing, size_t name_spacing);
|
||||
const char *suffix, uint8_t expand_types,
|
||||
uint8_t indent, size_t type_spacing,
|
||||
size_t name_spacing);
|
||||
static size_t class__snprintf(const struct class *self, const struct cu *cu,
|
||||
char *bf, size_t len,
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types,
|
||||
uint8_t indent, size_t type_spacing,
|
||||
size_t name_spacing, int emit_stats);
|
||||
|
||||
static size_t class_member__snprintf(struct class_member *self,
|
||||
struct tag *type, const struct cu *cu,
|
||||
char *bf, size_t len, size_t indent,
|
||||
char *bf, size_t len,
|
||||
uint8_t expand_types, size_t indent,
|
||||
size_t type_spacing, size_t name_spacing)
|
||||
{
|
||||
char tbf[128];
|
||||
|
@ -1094,24 +1097,25 @@ static size_t class_member__snprintf(struct class_member *self,
|
|||
case DW_TAG_structure_type:
|
||||
ctype = tag__type(type);
|
||||
|
||||
if (ctype->name != NULL)
|
||||
if (ctype->name != NULL && !expand_types)
|
||||
return snprintf(bf, len, "struct %-*s %s",
|
||||
type_spacing - 7, ctype->name,
|
||||
self->name);
|
||||
|
||||
return class__snprintf(tag__class(type), cu, bf, len,
|
||||
NULL, self->name, indent,
|
||||
NULL, self->name, expand_types, indent,
|
||||
type_spacing - 8, name_spacing, 0);
|
||||
case DW_TAG_union_type:
|
||||
ctype = tag__type(type);
|
||||
|
||||
if (ctype->name != NULL)
|
||||
if (ctype->name != NULL && !expand_types)
|
||||
return snprintf(bf, len, "union %-*s %s",
|
||||
type_spacing - 6, ctype->name,
|
||||
self->name);
|
||||
|
||||
return union__snprintf(ctype, cu, bf, len, NULL, self->name,
|
||||
indent, type_spacing - 8, name_spacing);
|
||||
expand_types, indent, type_spacing - 8,
|
||||
name_spacing);
|
||||
case DW_TAG_enumeration_type:
|
||||
ctype = tag__type(type);
|
||||
|
||||
|
@ -1131,14 +1135,15 @@ static size_t class_member__snprintf(struct class_member *self,
|
|||
|
||||
static size_t struct_member__snprintf(struct class_member *self,
|
||||
struct tag *type, const struct cu *cu,
|
||||
char *bf, size_t len, size_t indent,
|
||||
char *bf, size_t len,
|
||||
uint8_t expand_types, size_t indent,
|
||||
size_t type_spacing, size_t name_spacing)
|
||||
{
|
||||
size_t l = len;
|
||||
ssize_t spacing;
|
||||
const size_t size = tag__size(type, cu);
|
||||
size_t n = class_member__snprintf(self, type, cu, bf, l, indent,
|
||||
type_spacing, name_spacing);
|
||||
size_t n = class_member__snprintf(self, type, cu, bf, l, expand_types,
|
||||
indent, type_spacing, name_spacing);
|
||||
|
||||
bf += n; l -= n;
|
||||
if (self->bit_size != 0)
|
||||
|
@ -1168,14 +1173,15 @@ static size_t struct_member__snprintf(struct class_member *self,
|
|||
|
||||
static size_t union_member__snprintf(struct class_member *self,
|
||||
struct tag *type, const struct cu *cu,
|
||||
char *bf, size_t len, size_t indent,
|
||||
char *bf, size_t len,
|
||||
uint8_t expand_types, size_t indent,
|
||||
size_t type_spacing, size_t name_spacing)
|
||||
{
|
||||
size_t l = len;
|
||||
ssize_t spacing;
|
||||
const size_t size = tag__size(type, cu);
|
||||
size_t n = class_member__snprintf(self, type, cu, bf, l, indent,
|
||||
type_spacing, name_spacing);
|
||||
size_t n = class_member__snprintf(self, type, cu, bf, l, expand_types,
|
||||
indent, type_spacing, name_spacing);
|
||||
|
||||
bf += n; l -= n;
|
||||
if ((type->tag == DW_TAG_union_type ||
|
||||
|
@ -1197,8 +1203,9 @@ static size_t union_member__snprintf(struct class_member *self,
|
|||
|
||||
static size_t union__snprintf(const struct type *self, const struct cu *cu,
|
||||
char *bf, size_t len, const char *prefix,
|
||||
const char *suffix, uint8_t indent,
|
||||
size_t type_spacing, size_t name_spacing)
|
||||
const char *suffix, uint8_t expand_types,
|
||||
uint8_t indent, size_t type_spacing,
|
||||
size_t name_spacing)
|
||||
{
|
||||
struct class_member *pos;
|
||||
char *s = bf;
|
||||
|
@ -1220,7 +1227,8 @@ static size_t union__snprintf(const struct type *self, const struct cu *cu,
|
|||
|
||||
n = snprintf(s, l, "%.*s", indent + 1, tabs);
|
||||
s += n; l -= n;
|
||||
n = union_member__snprintf(pos, type, cu, s, l, indent + 1,
|
||||
n = union_member__snprintf(pos, type, cu, s, l, expand_types,
|
||||
indent + 1,
|
||||
type_spacing, name_spacing);
|
||||
s += n; l -= n;
|
||||
n = snprintf(s, l, "\n");
|
||||
|
@ -1234,12 +1242,14 @@ static size_t union__snprintf(const struct type *self, const struct cu *cu,
|
|||
}
|
||||
|
||||
static void union__print(const struct tag *tag, const struct cu *cu,
|
||||
const char *prefix, const char *suffix)
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types)
|
||||
{
|
||||
const struct type *utype = tag__type(tag);
|
||||
char bf[32768];
|
||||
|
||||
union__snprintf(utype, cu, bf, sizeof(bf), prefix, suffix, 0, 26, 23);
|
||||
union__snprintf(utype, cu, bf, sizeof(bf), prefix, suffix,
|
||||
expand_types, 0, 26, 23);
|
||||
fputs(bf, stdout);
|
||||
}
|
||||
|
||||
|
@ -1762,6 +1772,7 @@ static size_t class__snprintf_cacheline_boundary(char *bf, size_t len,
|
|||
static size_t class__snprintf(const struct class *self, const struct cu *cu,
|
||||
char *bf, size_t len,
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types,
|
||||
uint8_t indent, size_t type_spacing,
|
||||
size_t name_spacing, int emit_stats)
|
||||
{
|
||||
|
@ -1855,7 +1866,8 @@ static size_t class__snprintf(const struct class *self, const struct cu *cu,
|
|||
size = tag__size(type, cu);
|
||||
n = snprintf(bf, l, "%.*s", indent + 1, tabs);
|
||||
bf += n; l -= n;
|
||||
n = struct_member__snprintf(pos, type, cu, bf, l, indent + 1,
|
||||
n = struct_member__snprintf(pos, type, cu, bf, l,
|
||||
expand_types, indent + 1,
|
||||
type_spacing, name_spacing);
|
||||
bf += n; l -= n;
|
||||
|
||||
|
@ -1983,17 +1995,19 @@ out:
|
|||
}
|
||||
|
||||
static void class__print(const struct tag *tag, const struct cu *cu,
|
||||
const char *prefix, const char *suffix)
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types)
|
||||
{
|
||||
char bf[32768];
|
||||
|
||||
class__snprintf(tag__class(tag), cu, bf, sizeof(bf),
|
||||
prefix, suffix, 0, 26, 23, 1);
|
||||
prefix, suffix, expand_types, 0, 26, 23, 1);
|
||||
fputs(bf, stdout);
|
||||
}
|
||||
|
||||
void tag__print(const struct tag *self, const struct cu *cu,
|
||||
const char *prefix, const char *suffix)
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types)
|
||||
{
|
||||
tag__print_decl_info(self);
|
||||
|
||||
|
@ -2005,13 +2019,13 @@ void tag__print(const struct tag *self, const struct cu *cu,
|
|||
typedef__print(self, cu);
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
class__print(self, cu, prefix, suffix);
|
||||
class__print(self, cu, prefix, suffix, expand_types);
|
||||
break;
|
||||
case DW_TAG_subprogram:
|
||||
function__print(self, cu);
|
||||
break;
|
||||
case DW_TAG_union_type:
|
||||
union__print(self, cu, prefix, suffix);
|
||||
union__print(self, cu, prefix, suffix, expand_types);
|
||||
break;
|
||||
default:
|
||||
printf("%s: %s tag not supported!\n", __FUNCTION__,
|
||||
|
@ -2813,7 +2827,7 @@ void type__emit(struct tag *tag_self, struct cu *cu,
|
|||
class__find_holes(tag__class(tag_self), cu);
|
||||
|
||||
if (ctype->name != NULL || suffix != NULL || prefix != NULL) {
|
||||
tag__print(tag_self, cu, prefix, suffix);
|
||||
tag__print(tag_self, cu, prefix, suffix, 0);
|
||||
|
||||
if (tag_self->tag != DW_TAG_structure_type)
|
||||
putchar(';');
|
||||
|
|
|
@ -240,7 +240,8 @@ extern void dwarves__init(size_t user_cacheline_size);
|
|||
|
||||
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);
|
||||
const char *prefix, const char *suffix,
|
||||
uint8_t expand_types);
|
||||
|
||||
extern const char *function__name(struct function *self, const struct cu *cu);
|
||||
extern void function__print_stats(const struct tag *tag_self,
|
||||
|
|
13
pahole.c
13
pahole.c
|
@ -33,6 +33,7 @@ static uint16_t nr_holes;
|
|||
static uint16_t nr_bit_holes;
|
||||
static uint8_t show_packable;
|
||||
static uint8_t verbose;
|
||||
static uint8_t expand_types;
|
||||
|
||||
struct structure {
|
||||
struct list_head node;
|
||||
|
@ -140,9 +141,9 @@ static void class_formatter(const struct structure *self)
|
|||
|
||||
if (typedef_alias != NULL) {
|
||||
const struct type *tdef = tag__type(typedef_alias);
|
||||
tag__print(tag, self->cu, "typedef", tdef->name);
|
||||
tag__print(tag, self->cu, "typedef", tdef->name, expand_types);
|
||||
} else
|
||||
tag__print(tag, self->cu, NULL, NULL);
|
||||
tag__print(tag, self->cu, NULL, NULL, expand_types);
|
||||
|
||||
printf(" /* definitions: %u */\n", self->nr_files);
|
||||
putchar('\n');
|
||||
|
@ -359,6 +360,7 @@ static struct option long_options[] = {
|
|||
{ "nr_definitions", no_argument, NULL, 't' },
|
||||
{ "nr_methods", no_argument, NULL, 'm' },
|
||||
{ "exclude", required_argument, NULL, 'x' },
|
||||
{ "expand_types", no_argument, NULL, 'e' },
|
||||
{ "cu_exclude", required_argument, NULL, 'X' },
|
||||
{ "decl_exclude", required_argument, NULL, 'D' },
|
||||
{ "anon_include", no_argument, NULL, 'a' },
|
||||
|
@ -381,6 +383,7 @@ static void usage(void)
|
|||
" -p, --packable show only structs that has "
|
||||
"holes that can be packed\n"
|
||||
" -c, --cacheline_size <size> set cacheline size\n"
|
||||
" -e, --expand_types expand class members\n"
|
||||
" -n, --nr_members show number of members\n"
|
||||
" -N, --class_name_len show size of classes\n"
|
||||
" -m, --nr_methods show number of methods\n"
|
||||
|
@ -408,12 +411,13 @@ int main(int argc, char *argv[])
|
|||
size_t cacheline_size = 0;
|
||||
void (*formatter)(const struct structure *s) = class_formatter;
|
||||
|
||||
while ((option = getopt_long(argc, argv, "AaB:c:D:hH:mnNpstVx:X:",
|
||||
while ((option = getopt_long(argc, argv, "AaB:c:D:ehH:mnNpstVx:X:",
|
||||
long_options, &option_index)) >= 0)
|
||||
switch (option) {
|
||||
case 'c': cacheline_size = atoi(optarg); break;
|
||||
case 'H': nr_holes = atoi(optarg); break;
|
||||
case 'B': nr_bit_holes = atoi(optarg); break;
|
||||
case 'e': expand_types = 1; break;
|
||||
case 's': formatter = size_formatter; break;
|
||||
case 'n': formatter = nr_members_formatter; break;
|
||||
case 'N': formatter = class_name_len_formatter; break;
|
||||
|
@ -473,7 +477,8 @@ int main(int argc, char *argv[])
|
|||
printf("struct %s not found!\n", class_name);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
tag__print(class__tag(s->class), s->cu, NULL, NULL);
|
||||
tag__print(class__tag(s->class), s->cu, NULL, NULL,
|
||||
expand_types);
|
||||
} else
|
||||
print_classes(formatter);
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ static int emit_tag(struct tag *self, struct cu *cu, void *cookie __unused)
|
|||
if (self->tag == DW_TAG_structure_type)
|
||||
class__find_holes(tag__class(self), cu);
|
||||
|
||||
tag__print(self, cu, NULL, NULL);
|
||||
tag__print(self, cu, NULL, NULL, 0);
|
||||
|
||||
if (self->tag == DW_TAG_subprogram) {
|
||||
const struct function *fn = tag__function(self);
|
||||
|
|
6
pfunct.c
6
pfunct.c
|
@ -120,7 +120,7 @@ static void fn_stats_size_fmtr(const struct fn_stats *self)
|
|||
static void fn_stats_fmtr(const struct fn_stats *self)
|
||||
{
|
||||
if (verbose) {
|
||||
tag__print(self->tag, self->cu, NULL, NULL);
|
||||
tag__print(self->tag, self->cu, NULL, NULL, 0);
|
||||
putchar('\n');
|
||||
if (show_variables || show_inline_expansions)
|
||||
function__print_stats(self->tag, self->cu);
|
||||
|
@ -276,7 +276,7 @@ static int class_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
|||
|
||||
if (ftype__has_parm_of_type(&function->proto, cookie, cu)) {
|
||||
if (verbose)
|
||||
tag__print(tag, cu, NULL, NULL);
|
||||
tag__print(tag, cu, NULL, NULL, 0);
|
||||
else
|
||||
fputs(function__name(function, cu), stdout);
|
||||
putchar('\n');
|
||||
|
@ -303,7 +303,7 @@ static int function_iterator(struct tag *tag, struct cu *cu, void *cookie)
|
|||
|
||||
function = tag__function(tag);
|
||||
if (strcmp(function__name(function, cu), cookie) == 0) {
|
||||
tag__print(tag, cu, NULL, NULL);
|
||||
tag__print(tag, cu, NULL, NULL, 0);
|
||||
putchar('\n');
|
||||
if (show_variables || show_inline_expansions)
|
||||
function__print_stats(tag, cu);
|
||||
|
|
Loading…
Reference in New Issue