[PAHOLE]: Allow changing the architecture word-size
Using a x86_64 binary: [acme@doppio pahole]$ build/pahole -C restart_block /usr/lib/debug/lib/modules/2.6.21-65.el5rt/kernel/drivers/net/e1000/e1000.ko.debug struct restart_block { long int (*fn)(struct restart_block *); /* 0 8 */ union { struct { long unsigned int arg0; /* 8 8 */ long unsigned int arg1; /* 16 8 */ long unsigned int arg2; /* 24 8 */ long unsigned int arg3; /* 32 8 */ }; /* 32 */ struct { u32 * uaddr; /* 8 8 */ u32 val; /* 16 4 */ u32 flags; /* 20 4 */ u64 time; /* 24 8 */ } fu; /* 24 */ }; /* 8 32 */ /* size: 40, cachelines: 1 */ /* last cacheline: 40 bytes */ }; Changing the word-size from 8 to 4 bytes: [acme@doppio pahole]$ build/pahole -w 4 -C restart_block /usr/lib/debug/lib/modules/2.6.21-65.el5rt/kernel/drivers/net/e1000/e1000.ko.debug struct restart_block { long int (*fn)(struct restart_block *); /* 0 4 */ union { struct { long unsigned int arg0; /* 4 4 */ long unsigned int arg1; /* 8 4 */ long unsigned int arg2; /* 12 4 */ long unsigned int arg3; /* 16 4 */ }; /* 16 */ struct { u32 * uaddr; /* 4 4 */ u32 val; /* 8 4 */ u32 flags; /* 12 4 */ u64 time; /* 16 8 */ } fu; /* 20 */ }; /* 4 20 */ /* size: 24, cachelines: 1 */ /* last cacheline: 24 bytes */ }; And from 8 to 16: [acme@doppio pahole]$ build/pahole -w 16 -C restart_block /usr/lib/debug/lib/modules/2.6.21-65.el5rt/kernel/drivers/net/e1000/e1000.ko.debug struct restart_block { long int (*fn)(struct restart_block *); /* 0 16 */ union { struct { long unsigned int arg0; /* 16 16 */ long unsigned int arg1; /* 32 16 */ long unsigned int arg2; /* 48 16 */ long unsigned int arg3; /* 64 16 */ /* --- cacheline 1 boundary (64 bytes) --- */ }; /* 64 */ struct { u32 * uaddr; /* 16 16 */ u32 val; /* 32 4 */ u32 flags; /* 36 4 */ u64 time; /* 40 8 */ } fu; /* 32 */ }; /* 16 64 */ /* --- cacheline 1 boundary (64 bytes) was 16 bytes ago --- */ /* size: 80, cachelines: 2 */ /* last cacheline: 16 bytes */ }; More work is required to specify different alignment rules. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
c383a868ca
commit
f6eb9ed92d
|
@ -107,6 +107,7 @@ struct type {
|
|||
struct list_head node;
|
||||
Dwarf_Off specification;
|
||||
size_t size;
|
||||
size_t size_diff;
|
||||
uint16_t nr_members;
|
||||
uint8_t declaration; /* only one bit used */
|
||||
uint8_t definition_emitted:1;
|
||||
|
|
138
pahole.c
138
pahole.c
|
@ -21,6 +21,7 @@
|
|||
|
||||
static uint8_t class__include_anonymous;
|
||||
static uint8_t class__include_nested_anonymous;
|
||||
static uint8_t word_size, original_word_size;
|
||||
|
||||
static char *class__exclude_prefix;
|
||||
static size_t class__exclude_prefix_len;
|
||||
|
@ -387,6 +388,133 @@ static int cu_unique_iterator(struct cu *cu, void *cookie)
|
|||
return cu__for_each_tag(cu, unique_iterator, cookie, tag__filter);
|
||||
}
|
||||
|
||||
static void class__resize_LP(struct tag *tag, struct cu *cu)
|
||||
{
|
||||
struct tag *tag_pos;
|
||||
struct class *self = tag__class(tag);
|
||||
size_t word_size_diff;
|
||||
size_t orig_size = self->type.size;
|
||||
|
||||
if (original_word_size > word_size)
|
||||
word_size_diff = original_word_size - word_size;
|
||||
else
|
||||
word_size_diff = word_size - original_word_size;
|
||||
|
||||
type__for_each_tag(tag__type(tag), tag_pos) {
|
||||
struct tag *type;
|
||||
size_t diff = 0;
|
||||
|
||||
/* we want only data members, i.e. with byte_offset attr */
|
||||
if (tag_pos->tag != DW_TAG_member &&
|
||||
tag_pos->tag != DW_TAG_inheritance)
|
||||
continue;
|
||||
|
||||
type = cu__find_tag_by_id(cu, tag_pos->type);
|
||||
switch (type->tag) {
|
||||
case DW_TAG_base_type: {
|
||||
struct base_type *bt = tag__base_type(type);
|
||||
|
||||
if (strcmp(bt->name, "long int") != 0 &&
|
||||
strcmp(bt->name, "long unsigned int") != 0)
|
||||
break;
|
||||
/* fallthru */
|
||||
}
|
||||
case DW_TAG_pointer_type:
|
||||
diff = word_size_diff;
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
case DW_TAG_union_type:
|
||||
diff = tag__type(type)->size_diff;
|
||||
break;
|
||||
}
|
||||
|
||||
if (diff != 0) {
|
||||
struct class_member *m = tag__class_member(tag_pos);
|
||||
if (original_word_size > word_size) {
|
||||
self->type.size -= diff;
|
||||
class__subtract_offsets_from(self, cu, m, diff);
|
||||
} else {
|
||||
self->type.size += diff;
|
||||
class__add_offsets_from(self, m, diff);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (original_word_size > word_size)
|
||||
tag__type(tag)->size_diff = orig_size - self->type.size;
|
||||
else
|
||||
tag__type(tag)->size_diff = self->type.size - orig_size;
|
||||
|
||||
class__fixup_alignment(self, cu);
|
||||
}
|
||||
|
||||
static void union__find_new_size(struct tag *tag, struct cu *cu)
|
||||
{
|
||||
struct tag *tag_pos;
|
||||
struct type *self = tag__type(tag);
|
||||
size_t max_size = 0;
|
||||
|
||||
type__for_each_tag(self, tag_pos) {
|
||||
struct tag *type;
|
||||
size_t size;
|
||||
|
||||
/* we want only data members, i.e. with byte_offset attr */
|
||||
if (tag_pos->tag != DW_TAG_member &&
|
||||
tag_pos->tag != DW_TAG_inheritance)
|
||||
continue;
|
||||
|
||||
type = cu__find_tag_by_id(cu, tag_pos->type);
|
||||
size = tag__size(type, cu);
|
||||
if (size > max_size)
|
||||
max_size = size;
|
||||
}
|
||||
|
||||
if (max_size > self->size)
|
||||
self->size_diff = max_size - self->size;
|
||||
else
|
||||
self->size_diff = self->size - max_size;
|
||||
|
||||
self->size = max_size;
|
||||
}
|
||||
|
||||
static int tag_fixup_word_size_iterator(struct tag *tag, struct cu *cu,
|
||||
void *cookie)
|
||||
{
|
||||
if (tag->tag == DW_TAG_structure_type ||
|
||||
tag->tag == DW_TAG_union_type) {
|
||||
struct tag *pos;
|
||||
|
||||
namespace__for_each_tag(tag__namespace(tag), pos)
|
||||
tag_fixup_word_size_iterator(pos, cu, cookie);
|
||||
}
|
||||
|
||||
switch (tag->tag) {
|
||||
case DW_TAG_base_type: {
|
||||
struct base_type *bt = tag__base_type(tag);
|
||||
|
||||
if (strcmp(bt->name, "long int") == 0 ||
|
||||
strcmp(bt->name, "long unsigned int") == 0)
|
||||
bt->size = word_size;
|
||||
}
|
||||
break;
|
||||
case DW_TAG_structure_type:
|
||||
class__resize_LP(tag, cu);
|
||||
break;
|
||||
case DW_TAG_union_type:
|
||||
union__find_new_size(tag, cu);
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cu_fixup_word_size_iterator(struct cu *cu, void *cookie)
|
||||
{
|
||||
original_word_size = cu->addr_size;
|
||||
cu->addr_size = word_size;
|
||||
return cu__for_each_tag(cu, tag_fixup_word_size_iterator, cookie, NULL);
|
||||
}
|
||||
|
||||
static struct tag *nr_methods__filter(struct tag *tag, struct cu *cu __unused,
|
||||
void *cookie __unused)
|
||||
{
|
||||
|
@ -651,6 +779,12 @@ static const struct argp_option pahole__options[] = {
|
|||
.key = 'V',
|
||||
.doc = "be verbose",
|
||||
},
|
||||
{
|
||||
.name = "word_size",
|
||||
.key = 'w',
|
||||
.arg = "WORD_SIZE",
|
||||
.doc = "change the arch word size to WORD_SIZE"
|
||||
},
|
||||
{
|
||||
.name = NULL,
|
||||
}
|
||||
|
@ -696,6 +830,7 @@ static error_t pahole__options_parser(int key, char *arg,
|
|||
case 'T': formatter = nr_definitions_formatter; break;
|
||||
case 't': separator = arg[0]; break;
|
||||
case 'V': global_verbose = 1; break;
|
||||
case 'w': word_size = atoi(arg); break;
|
||||
case 'X': cu__exclude_prefix = arg;
|
||||
cu__exclude_prefix_len = strlen(cu__exclude_prefix);
|
||||
break;
|
||||
|
@ -738,6 +873,9 @@ int main(int argc, char *argv[])
|
|||
|
||||
dwarves__init(cacheline_size);
|
||||
|
||||
if (word_size != 0)
|
||||
cus__for_each_cu(cus, cu_fixup_word_size_iterator, NULL, NULL);
|
||||
|
||||
if (class_dwarf_offset != 0) {
|
||||
struct cu *cu;
|
||||
struct tag *tag = cus__find_tag_by_id(cus, &cu,
|
||||
|
|
Loading…
Reference in New Issue