dwarves/classes.h

173 lines
4.5 KiB
C
Raw Normal View History

#ifndef _PAHOLE_CLASSES_H_
#define _PAHOLE_CLASSES_H_ 1
/*
Copyright (C) 2006 Mandriva Conectiva S.A.
Copyright (C) 2006 Arnaldo Carvalho de Melo <acme@mandriva.com>
This program is free software; you can redistribute it and/or modify it
under the terms of version 2 of the GNU General Public License as
published by the Free Software Foundation.
*/
#include <stdint.h>
#include "list.h"
struct cus {
struct list_head cus;
const char *filename;
};
struct cu {
struct list_head node;
struct list_head classes;
struct list_head functions;
struct list_head variables;
const char *name;
unsigned int id;
unsigned long nr_inline_expansions;
unsigned long size_inline_expansions;
unsigned int nr_functions_changed;
unsigned int nr_structures_changed;
size_t max_len_changed_item;
size_t function_bytes_added;
size_t function_bytes_removed;
};
struct tag {
struct list_head node;
uint64_t type;
uint64_t id;
uint16_t tag;
uint16_t decl_line;
const char *decl_file;
};
struct class {
struct tag tag;
struct cu *cu;
struct list_head members;
const char *name;
uint64_t size;
uint64_t nr_entries; /* For arrays */
unsigned short nr_members;
unsigned short nr_holes;
unsigned short padding;
unsigned int refcnt;
signed int diff;
struct class *class_to_diff;
};
struct class_member {
struct tag tag;
char *name;
struct class *class;
uint64_t offset;
unsigned int bit_size;
unsigned int bit_offset;
unsigned char visited:1;
unsigned short hole; /* If there is a hole before the next
one (or the end of the struct) */
};
struct function {
struct tag tag;
struct cu *cu;
struct list_head parameters;
struct list_head inline_expansions;
struct list_head variables;
const char *name;
uint64_t low_pc;
uint64_t high_pc;
unsigned short nr_parameters;
unsigned short nr_labels;
unsigned short nr_variables;
unsigned short inlined;
unsigned short nr_inline_expansions;
unsigned char external:1;
unsigned int refcnt;
unsigned int size_inline_expansions;
signed int diff;
unsigned int cu_total_nr_inline_expansions;
unsigned long cu_total_size_inline_expansions;
struct class *class_to_diff;
};
struct parameter {
struct tag tag;
char *name;
struct function *function;
};
struct variable {
struct tag tag;
struct cu *cu;
struct list_head cu_node;
char *name;
uint64_t abstract_origin;
};
[CLASSES]: Add support for DW_TAG_inlined_subroutine Output of pfunct using this information (all for a make allyesconfig build): Top 5 functions by size of inlined functions in net/ipv4: [acme@newtoy guinea_pig-2.6]$ pfunct -I net/ipv4/built-in.o | sort -k3 -nr | head -5 ip_route_input: 19 7086 tcp_ack: 33 6415 do_ip_vs_set_ctl: 23 4193 q931_help: 8 3822 ip_defrag: 19 3318 [acme@newtoy guinea_pig-2.6]$ And by number of inline expansions: [acme@newtoy guinea_pig-2.6]$ pfunct -I net/ipv4/built-in.o | sort -k2 -nr | head -5 dump_packet: 35 905 tcp_v4_rcv: 34 1773 tcp_recvmsg: 34 928 tcp_ack: 33 6415 tcp_rcv_established: 31 1195 [acme@newtoy guinea_pig-2.6]$ And the list of expansions on a specific function: [acme@newtoy guinea_pig-2.6]$ pfunct -i net/ipv4/built-in.o tcp_v4_rcv /* net/ipv4/tcp_ipv4.c:1054 */ int tcp_v4_rcv(struct sk_buff * skb); /* size: 2189, variables: 8, goto labels: 6, inline expansions: 34 (1773 bytes) */ /* inline expansions in tcp_v4_rcv: current_thread_info: 8 pskb_may_pull: 36 pskb_may_pull: 29 tcp_v4_checksum_init: 139 __fswab32: 2 __fswab32: 2 inet_iif: 12 __inet_lookup: 292 __fswab16: 20 inet_ehashfn: 25 inet_ehash_bucket: 18 prefetch: 4 prefetch: 4 prefetch: 4 sock_hold: 4 xfrm4_policy_check: 59 nf_reset: 66 sk_filter: 135 __skb_trim: 20 get_softnet_dma: 68 tcp_prequeue: 257 sk_add_backlog: 40 sock_put: 27 xfrm4_policy_check: 46 tcp_checksum_complete: 29 current_thread_info: 8 sock_put: 20 xfrm4_policy_check: 50 tcp_checksum_complete: 29 current_thread_info: 8 inet_iif: 9 inet_lookup_listener: 36 inet_twsk_put: 114 tcp_v4_timewait_ack: 153 */ [acme@newtoy guinea_pig-2.6]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 16:41:19 +01:00
struct inline_expansion {
struct tag tag;
struct function *function;
uint32_t size;
[CLASSES]: Add support for DW_TAG_inlined_subroutine Output of pfunct using this information (all for a make allyesconfig build): Top 5 functions by size of inlined functions in net/ipv4: [acme@newtoy guinea_pig-2.6]$ pfunct -I net/ipv4/built-in.o | sort -k3 -nr | head -5 ip_route_input: 19 7086 tcp_ack: 33 6415 do_ip_vs_set_ctl: 23 4193 q931_help: 8 3822 ip_defrag: 19 3318 [acme@newtoy guinea_pig-2.6]$ And by number of inline expansions: [acme@newtoy guinea_pig-2.6]$ pfunct -I net/ipv4/built-in.o | sort -k2 -nr | head -5 dump_packet: 35 905 tcp_v4_rcv: 34 1773 tcp_recvmsg: 34 928 tcp_ack: 33 6415 tcp_rcv_established: 31 1195 [acme@newtoy guinea_pig-2.6]$ And the list of expansions on a specific function: [acme@newtoy guinea_pig-2.6]$ pfunct -i net/ipv4/built-in.o tcp_v4_rcv /* net/ipv4/tcp_ipv4.c:1054 */ int tcp_v4_rcv(struct sk_buff * skb); /* size: 2189, variables: 8, goto labels: 6, inline expansions: 34 (1773 bytes) */ /* inline expansions in tcp_v4_rcv: current_thread_info: 8 pskb_may_pull: 36 pskb_may_pull: 29 tcp_v4_checksum_init: 139 __fswab32: 2 __fswab32: 2 inet_iif: 12 __inet_lookup: 292 __fswab16: 20 inet_ehashfn: 25 inet_ehash_bucket: 18 prefetch: 4 prefetch: 4 prefetch: 4 sock_hold: 4 xfrm4_policy_check: 59 nf_reset: 66 sk_filter: 135 __skb_trim: 20 get_softnet_dma: 68 tcp_prequeue: 257 sk_add_backlog: 40 sock_put: 27 xfrm4_policy_check: 46 tcp_checksum_complete: 29 current_thread_info: 8 sock_put: 20 xfrm4_policy_check: 50 tcp_checksum_complete: 29 current_thread_info: 8 inet_iif: 9 inet_lookup_listener: 36 inet_twsk_put: 114 tcp_v4_timewait_ack: 153 */ [acme@newtoy guinea_pig-2.6]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 16:41:19 +01:00
};
[PAHOLE]: Print cacheline boundaries Cacheline size defaults to 32, sample output changing the default to 64 bytes: pahole --cacheline=64 ../../acme/OUTPUT/qemu/net-2.6/net/ipv4/tcp.o inode /* /pub/scm/linux/kernel/git/acme/net-2.6/include/linux/dcache.h:86 */ struct inode { struct hlist_node i_hash; /* 0 8 */ struct list_head i_list; /* 8 8 */ struct list_head i_sb_list; /* 16 8 */ struct list_head i_dentry; /* 24 8 */ long unsigned int i_ino; /* 32 4 */ atomic_t i_count; /* 36 4 */ umode_t i_mode; /* 40 2 */ /* XXX 2 bytes hole, try to pack */ unsigned int i_nlink; /* 44 4 */ uid_t i_uid; /* 48 4 */ gid_t i_gid; /* 52 4 */ dev_t i_rdev; /* 56 4 */ loff_t i_size; /* 60 8 */ struct timespec i_atime; /* 68 8 */ struct timespec i_mtime; /* 76 8 */ struct timespec i_ctime; /* 84 8 */ unsigned int i_blkbits; /* 92 4 */ long unsigned int i_version; /* 96 4 */ blkcnt_t i_blocks; /* 100 4 */ short unsigned int i_bytes; /* 104 2 */ spinlock_t i_lock; /* 106 0 */ /* XXX 2 bytes hole, try to pack */ struct mutex i_mutex; /* 108 24 */ /* ---------- cacheline 2 boundary ---------- */ struct rw_semaphore i_alloc_sem; /* 132 12 */ struct inode_operations * i_op; /* 144 4 */ const struct file_operations * i_fop; /* 148 4 */ struct super_block * i_sb; /* 152 4 */ struct file_lock * i_flock; /* 156 4 */ struct address_space * i_mapping; /* 160 4 */ struct address_space i_data; /* 164 72 */ struct list_head i_devices; /* 236 8 */ union ; /* 244 4 */ int i_cindex; /* 248 4 */ __u32 i_generation; /* 252 4 */ long unsigned int i_dnotify_mask; /* 256 4 */ /* ---------- cacheline 4 boundary ---------- */ struct dnotify_struct * i_dnotify; /* 260 4 */ struct list_head inotify_watches; /* 264 8 */ struct mutex inotify_mutex; /* 272 24 */ long unsigned int i_state; /* 296 4 */ long unsigned int dirtied_when; /* 300 4 */ unsigned int i_flags; /* 304 4 */ atomic_t i_writecount; /* 308 4 */ void * i_private; /* 312 4 */ }; /* size: 316, sum members: 312, holes: 2, sum holes: 4 */ Has to be improved to show the other cacheline boundaries, that may be buried into a included struct or union. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-05 18:34:54 +01:00
#define DEFAULT_CACHELINE_SIZE 32
extern void class__find_holes(struct class *self);
extern void class__print(struct class *self);
extern void function__print(struct function *self);
extern struct cus *cus__new(const char *filename);
extern int cus__load(struct cus *self);
extern struct cu *cus__find_cu_by_name(const struct cus *self,
const char *name);
extern struct class *cu__find_class_by_id(const struct cu *cu,
const uint64_t type);
extern struct class *cu__find_class_by_name(const struct cu *cu,
const char *name);
extern int class__is_struct(const struct class *self,
struct class **typedef_alias);
extern void cus__print_classes(struct cus *cus,
const unsigned int tag);
extern void cus__print_functions(struct cus *cus);
extern void function__print_inline_expansions(struct function *self);
extern void function__print_variables(struct function *self);
extern struct class *cus__find_class_by_name(const struct cus *self,
const char *name);
extern void cu__account_inline_expansions(struct cu *self);
extern int cu__for_each_class(struct cu *cu,
int (*iterator)(struct class *class,
void *cookie),
void *cookie);
extern int cu__for_each_function(struct cu *cu,
int (*iterator)(struct function *func,
void *cookie),
void *cookie);
extern void cus__for_each_cu(struct cus *self,
int (*iterator)(struct cu *cu,
void *cookie),
void *cookie);
extern struct function *cu__find_function_by_name(const struct cu *cu,
const char *name);
static inline uint32_t function__size(const struct function *self)
{
return self->high_pc - self->low_pc;
}
[CODIFF]: Detect and print all sorts of changes in structs [acme@newtoy examples]$ cat struct.c static struct foo { char a:2; unsigned int b; unsigned long c; unsigned long d; unsigned long e; } bar; int main(int argc, char *argv[]) { printf("%d", bar.a); } [acme@newtoy examples]$ Then change "a:2" to "a:4": [acme@newtoy examples]$ codiff -V old_struct new_struct struct.c: struct foo | +0 a:2; from: char /* 0(6) 1(2) */ to: char /* 0(4) 1(4) */ 1 struct changed Now, on top of that move a after b: [acme@newtoy examples]$ codiff -V old_struct new_struct struct.c: struct foo | +0 a:2; from: char /* 0(6) 1(2) */ to: char /* 4(4) 1(4) */ b; from: unsigned int /* 4(0) 4(0) */ to: unsigned int /* 0(0) 4(0) */ 1 struct changed [acme@newtoy examples]$ Move it back a to before b and change the type of e without changing its size, i.e. from unsigned long to long: [acme@newtoy examples]$ codiff -V old_struct new_struct struct.c: struct foo | +0 a:2; from: char /* 0(6) 1(2) */ to: char /* 0(4) 1(4) */ e; from: long unsigned int /* 16(0) 4(0) */ to: long int /* 16(0) 4(0) */ 1 struct changed [acme@newtoy examples]$ Now on top of this lets delete the c member: [acme@newtoy examples]$ codiff -V old_struct new_struct struct.c: struct foo | -4 nr_members: -1 -long unsigned int c; /* 8 4 */ a:2; from: char /* 0(6) 1(2) */ to: char /* 0(4) 1(4) */ d; from: long unsigned int /* 12(0) 4(0) */ to: long unsigned int /* 8(0) 4(0) */ e; from: long unsigned int /* 16(0) 4(0) */ to: long int /* 12(0) 4(0) */ 1 struct changed [acme@newtoy examples]$ WOW, many changes, what an ABI breakage, no? :-) It started as: [acme@newtoy examples]$ pahole old_struct foo /* /home/acme/pahole/examples/struct.c:3 */ struct foo { char a:2; /* 0 1 */ /* XXX 3 bytes hole, try to pack */ unsigned int b; /* 4 4 */ long unsigned int c; /* 8 4 */ long unsigned int d; /* 12 4 */ long unsigned int e; /* 16 4 */ }; /* size: 20, sum members: 17, holes: 1, sum holes: 3 */ And ended up as: [acme@newtoy examples]$ pahole new_struct foo /* /home/acme/pahole/examples/struct.c:3 */ struct foo { char a:4; /* 0 1 */ /* XXX 3 bytes hole, try to pack */ unsigned int b; /* 4 4 */ long unsigned int d; /* 8 4 */ long int e; /* 12 4 */ }; /* size: 16, sum members: 13, holes: 1, sum holes: 3 */ [acme@newtoy examples]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-12 18:07:21 +01:00
extern struct class_member *class__find_member_by_name(const struct class *self,
const char *name);
extern uint64_t class_member__names(const struct class_member *self,
char *class_name,
size_t class_name_size,
char *member_name,
size_t member_name_size);
[PAHOLE]: Print cacheline boundaries Cacheline size defaults to 32, sample output changing the default to 64 bytes: pahole --cacheline=64 ../../acme/OUTPUT/qemu/net-2.6/net/ipv4/tcp.o inode /* /pub/scm/linux/kernel/git/acme/net-2.6/include/linux/dcache.h:86 */ struct inode { struct hlist_node i_hash; /* 0 8 */ struct list_head i_list; /* 8 8 */ struct list_head i_sb_list; /* 16 8 */ struct list_head i_dentry; /* 24 8 */ long unsigned int i_ino; /* 32 4 */ atomic_t i_count; /* 36 4 */ umode_t i_mode; /* 40 2 */ /* XXX 2 bytes hole, try to pack */ unsigned int i_nlink; /* 44 4 */ uid_t i_uid; /* 48 4 */ gid_t i_gid; /* 52 4 */ dev_t i_rdev; /* 56 4 */ loff_t i_size; /* 60 8 */ struct timespec i_atime; /* 68 8 */ struct timespec i_mtime; /* 76 8 */ struct timespec i_ctime; /* 84 8 */ unsigned int i_blkbits; /* 92 4 */ long unsigned int i_version; /* 96 4 */ blkcnt_t i_blocks; /* 100 4 */ short unsigned int i_bytes; /* 104 2 */ spinlock_t i_lock; /* 106 0 */ /* XXX 2 bytes hole, try to pack */ struct mutex i_mutex; /* 108 24 */ /* ---------- cacheline 2 boundary ---------- */ struct rw_semaphore i_alloc_sem; /* 132 12 */ struct inode_operations * i_op; /* 144 4 */ const struct file_operations * i_fop; /* 148 4 */ struct super_block * i_sb; /* 152 4 */ struct file_lock * i_flock; /* 156 4 */ struct address_space * i_mapping; /* 160 4 */ struct address_space i_data; /* 164 72 */ struct list_head i_devices; /* 236 8 */ union ; /* 244 4 */ int i_cindex; /* 248 4 */ __u32 i_generation; /* 252 4 */ long unsigned int i_dnotify_mask; /* 256 4 */ /* ---------- cacheline 4 boundary ---------- */ struct dnotify_struct * i_dnotify; /* 260 4 */ struct list_head inotify_watches; /* 264 8 */ struct mutex inotify_mutex; /* 272 24 */ long unsigned int i_state; /* 296 4 */ long unsigned int dirtied_when; /* 300 4 */ unsigned int i_flags; /* 304 4 */ atomic_t i_writecount; /* 308 4 */ void * i_private; /* 312 4 */ }; /* size: 316, sum members: 312, holes: 2, sum holes: 4 */ Has to be improved to show the other cacheline boundaries, that may be buried into a included struct or union. Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-05 18:34:54 +01:00
extern unsigned int cacheline_size;
#endif /* _PAHOLE_CLASSES_H_ */