dwarves/dwarves.h

407 lines
11 KiB
C
Raw Normal View History

#ifndef _DWARVES_H_
#define _DWARVES_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 <stdio.h>
#include <dwarf.h>
#include <elfutils/libdw.h>
#include "list.h"
struct argp;
#ifndef __unused
#define __unused __attribute__ ((unused))
#endif
struct cus {
struct list_head cus;
struct list_head priv_definitions; /* struct type entries */
struct list_head priv_fwd_decls; /* struct class entries */
struct list_head *definitions;
struct list_head *fwd_decls;
};
struct cu {
struct list_head node;
struct list_head tags;
struct list_head tool_list; /* To be used by tools such as ctracer */
const char *name;
uint8_t addr_size;
uint16_t language;
unsigned long nr_inline_expansions;
size_t size_inline_expansions;
uint32_t nr_functions_changed;
uint32_t 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;
Dwarf_Off type;
Dwarf_Off id;
const char *decl_file;
[LIB]: Reorganize struct tag Erm, eating my dog food now that I have access to a 64bit machine here at home: [acme@mica pahole]$ pahole build/libdwarves.so.1.0.0 tag /* <b7e> /home/acme/git/pahole/dwarves.h:48 */ struct tag { struct list_head node; /* 0 16 */ Dwarf_Off type; /* 16 8 */ Dwarf_Off id; /* 24 8 */ uint16_t tag; /* 32 2 */ uint16_t decl_line; /* 34 2 */ /* XXX 4 bytes hole, try to pack */ const char * decl_file; /* 40 8 */ uint32_t refcnt; /* 48 4 */ }; /* size: 56, cachelines: 1 */ /* sum members: 48, holes: 1, sum holes: 4 */ /* padding: 4 */ /* last cacheline: 56 bytes */ [acme@mica pahole]$ [acme@mica pahole]$ pahole --reorganize build/libdwarves.so.1.0.0 tag /* <b7e> /home/acme/git/pahole/dwarves.h:48 */ struct tag { struct list_head node; /* 0 16 */ Dwarf_Off type; /* 16 8 */ Dwarf_Off id; /* 24 8 */ uint16_t tag; /* 32 2 */ uint16_t decl_line; /* 34 2 */ uint32_t refcnt; /* 36 4 */ const char * decl_file; /* 40 8 */ }; /* size: 48, cachelines: 1 */ /* last cacheline: 48 bytes */ /* saved 8 bytes! */ [acme@mica pahole]$ [acme@mica pahole]$ codiff build/libdwarves.so.1.0.0.before build/libdwarves.so.1.0.0 /home/acme/git/pahole/dwarves.c: struct tag | -8 struct type | -8 struct class | -8 struct base_type | -8 struct array_type | -8 struct class_member | -8 struct lexblock | -8 struct ftype | -8 struct function | -16 struct parameter | -8 struct variable | -8 struct inline_expansion | -8 struct label | -8 struct enumerator | -8 14 structs changed class_member__clone | -8 class__clone | -8 2 functions changed, 16 bytes removed [acme@mica pahole]$ Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
2007-03-07 16:10:56 +01:00
uint16_t decl_line;
uint16_t tag;
uint32_t refcnt;
};
struct type {
struct tag tag;
struct list_head node;
const char *name;
size_t size;
struct list_head members;
uint16_t nr_members;
uint8_t declaration; /* only one bit used */
uint8_t definition_emitted:1;
uint8_t fwd_decl_emitted:1;
};
static inline struct type *tag__type(const struct tag *self)
{
return (struct type *)self;
}
struct class {
struct type type;
uint8_t nr_holes;
uint8_t nr_bit_holes;
uint16_t padding;
uint8_t bit_padding;
void *priv;
};
static inline struct class *tag__class(const struct tag *self)
{
return (struct class *)self;
}
static inline struct tag *class__tag(const struct class *self)
{
return (struct tag *)self;
}
extern struct class *class__clone(const struct class *from,
const char *new_class_name);
extern void class__delete(struct class *self);
static inline const char *class__name(const struct class *self)
{
return self->type.name;
}
static inline uint16_t class__tag_type(const struct class *self)
{
return self->type.tag.tag;
}
struct base_type {
struct tag tag;
const char *name;
size_t size;
};
static inline struct base_type *tag__base_type(const struct tag *self)
{
return (struct base_type *)self;
}
struct array_type {
struct tag tag;
uint32_t *nr_entries;
uint8_t dimensions;
};
static inline struct array_type *tag__array_type(const struct tag *self)
{
return (struct array_type *)self;
}
struct class_member {
struct tag tag;
char *name;
uint32_t offset;
uint8_t bit_offset;
uint8_t bit_size;
uint8_t bit_hole; /* If there is a bit hole before the next
one (or the end of the struct) */
uint8_t visited:1;
uint16_t hole; /* If there is a hole before the next
[CLASSES]: Find bit holes An example is worth a thousand words, look for "XXX ... bit hole, try to pack" and the stats at the bottom: [acme@newtoy net-2.6]$ pahole ../OUTPUT/qemu/net-2.6/fs/inode.o task_struct /* include2/asm/system.h:11 */ struct task_struct { volatile long int state; /* 0 4 */ struct thread_info * thread_info; /* 4 4 */ atomic_t usage; /* 8 4 */ long unsigned int flags; /* 12 4 */ long unsigned int ptrace; /* 16 4 */ int lock_depth; /* 20 4 */ int load_weight; /* 24 4 */ int prio; /* 28 4 */ /* --- cacheline 1 boundary (32 bytes) --- */ int static_prio; /* 32 4 */ int normal_prio; /* 36 4 */ struct list_head run_list; /* 40 8 */ struct prio_array * array; /* 48 4 */ short unsigned int ioprio; /* 52 2 */ /* XXX 2 bytes hole, try to pack */ long unsigned int sleep_avg; /* 56 4 */ long long unsigned int timestamp; /* 60 8 */ /* --- cacheline 2 boundary (64 bytes) was 4 bytes ago --- */ long long unsigned int last_ran; /* 68 8 */ long long unsigned int sched_time; /* 76 8 */ enum sleep_type sleep_type; /* 84 4 */ long unsigned int policy; /* 88 4 */ cpumask_t cpus_allowed; /* 92 4 */ /* --- cacheline 3 boundary (96 bytes) --- */ unsigned int time_slice; /* 96 4 */ unsigned int first_time_slice; /* 100 4 */ struct list_head tasks; /* 104 8 */ struct list_head ptrace_children; /* 112 8 */ struct list_head ptrace_list; /* 120 8 */ /* --- cacheline 4 boundary (128 bytes) --- */ struct mm_struct * mm; /* 128 4 */ struct mm_struct * active_mm; /* 132 4 */ struct linux_binfmt * binfmt; /* 136 4 */ long int exit_state; /* 140 4 */ int exit_code; /* 144 4 */ int exit_signal; /* 148 4 */ int pdeath_signal; /* 152 4 */ long unsigned int personality; /* 156 4 */ /* --- cacheline 5 boundary (160 bytes) --- */ unsigned int did_exec:1; /* 160 4 */ /* XXX 31 bits hole, try to pack */ pid_t pid; /* 164 4 */ pid_t tgid; /* 168 4 */ struct task_struct * real_parent; /* 172 4 */ struct task_struct * parent; /* 176 4 */ struct list_head children; /* 180 8 */ struct list_head sibling; /* 188 8 */ /* --- cacheline 6 boundary (192 bytes) was 4 bytes ago --- */ struct task_struct * group_leader; /* 196 4 */ struct pid_link pids[3]; /* 200 36 */ /* --- cacheline 7 boundary (224 bytes) was 12 bytes ago --- */ struct list_head thread_group; /* 236 8 */ struct completion * vfork_done; /* 244 4 */ int * set_child_tid; /* 248 4 */ int * clear_child_tid; /* 252 4 */ /* --- cacheline 8 boundary (256 bytes) --- */ long unsigned int rt_priority; /* 256 4 */ cputime_t utime; /* 260 4 */ cputime_t stime; /* 264 4 */ long unsigned int nvcsw; /* 268 4 */ long unsigned int nivcsw; /* 272 4 */ struct timespec start_time; /* 276 8 */ long unsigned int min_flt; /* 284 4 */ /* --- cacheline 9 boundary (288 bytes) --- */ long unsigned int maj_flt; /* 288 4 */ cputime_t it_prof_expires; /* 292 4 */ cputime_t it_virt_expires; /* 296 4 */ long long unsigned int it_sched_expires; /* 300 8 */ struct list_head cpu_timers[3]; /* 308 24 */ /* --- cacheline 10 boundary (320 bytes) was 12 bytes ago --- */ uid_t uid; /* 332 4 */ uid_t euid; /* 336 4 */ uid_t suid; /* 340 4 */ uid_t fsuid; /* 344 4 */ gid_t gid; /* 348 4 */ /* --- cacheline 11 boundary (352 bytes) --- */ gid_t egid; /* 352 4 */ gid_t sgid; /* 356 4 */ gid_t fsgid; /* 360 4 */ struct group_info * group_info; /* 364 4 */ kernel_cap_t cap_effective; /* 368 4 */ kernel_cap_t cap_inheritable; /* 372 4 */ kernel_cap_t cap_permitted; /* 376 4 */ unsigned int keep_capabilities:1; /* 380 4 */ /* XXX 31 bits hole, try to pack */ /* --- cacheline 12 boundary (384 bytes) --- */ struct user_struct * user; /* 384 4 */ struct key * request_key_auth; /* 388 4 */ struct key * thread_keyring; /* 392 4 */ unsigned char jit_keyring; /* 396 1 */ unsigned char fpu_counter; /* 397 1 */ /* XXX 2 bytes hole, try to pack */ int oomkilladj; /* 400 4 */ char comm[16]; /* 404 16 */ /* --- cacheline 13 boundary (416 bytes) was 4 bytes ago --- */ int link_count; /* 420 4 */ int total_link_count; /* 424 4 */ struct sysv_sem sysvsem; /* 428 4 */ struct thread_struct thread; /* 432 656 */ /* --- cacheline 34 boundary (1088 bytes) --- */ struct fs_struct * fs; /* 1088 4 */ struct files_struct * files; /* 1092 4 */ struct nsproxy * nsproxy; /* 1096 4 */ struct signal_struct * signal; /* 1100 4 */ struct sighand_struct * sighand; /* 1104 4 */ sigset_t blocked; /* 1108 8 */ sigset_t real_blocked; /* 1116 8 */ /* --- cacheline 35 boundary (1120 bytes) was 4 bytes ago --- */ sigset_t saved_sigmask; /* 1124 8 */ struct sigpending pending; /* 1132 16 */ long unsigned int sas_ss_sp; /* 1148 4 */ /* --- cacheline 36 boundary (1152 bytes) --- */ size_t sas_ss_size; /* 1152 4 */ int (*notifier)(); /* 1156 4 */ void * notifier_data; /* 1160 4 */ sigset_t * notifier_mask; /* 1164 4 */ void * security; /* 1168 4 */ struct audit_context * audit_context; /* 1172 4 */ seccomp_t seccomp; /* 1176 0 */ u32 parent_exec_id; /* 1176 4 */ u32 self_exec_id; /* 1180 4 */ /* --- cacheline 37 boundary (1184 bytes) --- */ spinlock_t alloc_lock; /* 1184 40 */ /* --- cacheline 38 boundary (1216 bytes) was 8 bytes ago --- */ spinlock_t pi_lock; /* 1224 40 */ /* --- cacheline 39 boundary (1248 bytes) was 16 bytes ago --- */ struct plist_head pi_waiters; /* 1264 20 */ /* --- cacheline 40 boundary (1280 bytes) was 4 bytes ago --- */ struct rt_mutex_waiter * pi_blocked_on; /* 1284 4 */ struct mutex_waiter * blocked_on; /* 1288 4 */ unsigned int irq_events; /* 1292 4 */ int hardirqs_enabled; /* 1296 4 */ long unsigned int hardirq_enable_ip; /* 1300 4 */ unsigned int hardirq_enable_event; /* 1304 4 */ long unsigned int hardirq_disable_ip; /* 1308 4 */ /* --- cacheline 41 boundary (1312 bytes) --- */ unsigned int hardirq_disable_event; /* 1312 4 */ int softirqs_enabled; /* 1316 4 */ long unsigned int softirq_disable_ip; /* 1320 4 */ unsigned int softirq_disable_event; /* 1324 4 */ long unsigned int softirq_enable_ip; /* 1328 4 */ unsigned int softirq_enable_event; /* 1332 4 */ int hardirq_context; /* 1336 4 */ int softirq_context; /* 1340 4 */ /* --- cacheline 42 boundary (1344 bytes) --- */ u64 curr_chain_key; /* 1344 8 */ int lockdep_depth; /* 1352 4 */ struct held_lock held_locks[30]; /* 1356 1200 */ /* --- cacheline 79 boundary (2528 bytes) was 28 bytes ago --- */ unsigned int lockdep_recursion; /* 2556 4 */ /* --- cacheline 80 boundary (2560 bytes) --- */ void * journal_info; /* 2560 4 */ struct reclaim_state * reclaim_state; /* 2564 4 */ struct backing_dev_info * backing_dev_info; /* 2568 4 */ struct io_context * io_context; /* 2572 4 */ long unsigned int ptrace_message; /* 2576 4 */ siginfo_t * last_siginfo; /* 2580 4 */ wait_queue_t * io_wait; /* 2584 4 */ u64 rchar; /* 2588 8 */ /* --- cacheline 81 boundary (2592 bytes) was 4 bytes ago --- */ u64 wchar; /* 2596 8 */ u64 syscr; /* 2604 8 */ u64 syscw; /* 2612 8 */ struct robust_list_head * robust_list; /* 2620 4 */ /* --- cacheline 82 boundary (2624 bytes) --- */ struct list_head pi_state_list; /* 2624 8 */ struct futex_pi_state * pi_state_cache; /* 2632 4 */ atomic_t fs_excl; /* 2636 4 */ struct rcu_head rcu; /* 2640 8 */ struct pipe_inode_info * splice_pipe; /* 2648 4 */ }; /* size: 2656, cachelines: 83 */ /* sum members: 2648, holes: 2, sum holes: 4 */ /* bit holes: 2, sum bit holes: 62 bits */ /* padding: 4 */ Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 15:26:50 +01:00
one (or the end of the struct) */
};
extern size_t class_member__size(const struct class_member *self,
const struct cu *cu);
extern void class_member__delete(struct class_member *self);
struct lexblock {
struct tag tag;
struct list_head tags;
Dwarf_Addr low_pc;
Dwarf_Addr high_pc;
uint16_t nr_inline_expansions;
uint16_t nr_labels;
uint16_t nr_variables;
uint16_t nr_lexblocks;
size_t size_inline_expansions;
};
static inline struct lexblock *tag__lexblock(const struct tag *self)
{
return (struct lexblock *)self;
}
/*
* tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
*/
struct ftype {
struct tag tag;
struct list_head parms;
uint16_t nr_parms;
uint8_t unspec_parms; /* just one bit is needed */
};
static inline struct ftype *tag__ftype(const struct tag *self)
{
return (struct ftype *)self;
}
struct function {
struct ftype proto;
struct lexblock lexblock;
const char *name;
Dwarf_Off abstract_origin;
Dwarf_Off specification;
size_t cu_total_size_inline_expansions;
uint16_t cu_total_nr_inline_expansions;
uint8_t inlined; /* two bits used */
uint8_t external; /* one bit used */
/* fields used by tools */
struct list_head tool_node;
void *priv;
};
static inline struct function *tag__function(const struct tag *self)
{
return (struct function *)self;
}
struct parameter {
struct tag tag;
char *name;
Dwarf_Off abstract_origin;
};
static inline struct parameter *tag__parameter(const struct tag *self)
{
return (struct parameter *)self;
}
extern Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu);
enum vlocation {
LOCATION_UNKNOWN,
LOCATION_LOCAL,
LOCATION_GLOBAL,
LOCATION_REGISTER,
LOCATION_OPTIMIZED
};
struct variable {
struct tag tag;
char *name;
Dwarf_Off abstract_origin;
uint8_t external:1;
uint8_t declaration:1;
enum vlocation location;
};
static inline struct variable *tag__variable(const struct tag *self)
{
return (struct variable *)self;
}
[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;
size_t size;
Dwarf_Addr low_pc;
Dwarf_Addr high_pc;
[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
};
static inline struct inline_expansion *
tag__inline_expansion(const struct tag *self)
{
return (struct inline_expansion *)self;
}
struct label {
struct tag tag;
char *name;
Dwarf_Addr low_pc;
};
struct enumerator {
struct tag tag;
const char *name;
uint32_t value;
};
extern void dwarves__init(size_t user_cacheline_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 void class__find_holes(struct class *self, const struct cu *cu);
extern void class__subtract_offsets_from(struct class *self,
const struct cu *cu,
struct class_member *from,
const uint16_t size);
extern struct class *class__reorganize(struct class *self,
const struct cu *cu,
const int verbose, FILE *fp);
extern size_t class__fprintf(const struct class *self, const struct cu *cu,
const char *prefix, const char *suffix,
[LIB]: Use a base_offset when printing inner structs That way we can have the offsets from the top level struct. If the user wants to focus some inner struct, just call the tool again specifying the inner struct name. Perhaps this is not so clear, shoot me, erm, no, an example should help. Look at the member offsets (first column in the comment after each member), before and after: before: acme@filo pahole]$ pahole -C tcp_sock --expand_types examples/net /* <12a> examples/expand.c:18 */ struct tcp_sock { struct inet_sock { struct sock { int protocol; /* 0 4 */ struct spinlock { int magic; /* 0 4 */ int counter; /* 4 4 */ } sklock; /* 4 8 */ int b; /* 12 4 */ int c; /* 16 4 */ } sk; /* 0 20 */ long int daddr; /* 20 4 */ } inet; /* 0 24 */ long int cwnd; /* 24 4 */ struct spinlock { int magic; /* 0 4 */ int counter; /* 4 4 */ } lock; /* 28 8 */ }; /* size: 36, cachelines: 1 */ /* last cacheline: 36 bytes */ After: acme@filo pahole]$ pahole -C tcp_sock --expand_types examples/net /* <12a> examples/expand.c:18 */ struct tcp_sock { struct inet_sock { struct sock { int protocol; /* 0 4 */ struct spinlock { int magic; /* 4 4 */ int counter; /* 8 4 */ } sklock; /* 4 8 */ int b; /* 12 4 */ int c; /* 16 4 */ } sk; /* 0 20 */ long int daddr; /* 20 4 */ } inet; /* 0 24 */ long int cwnd; /* 24 4 */ struct spinlock { int magic; /* 28 4 */ int counter; /* 32 4 */ } lock; /* 28 8 */ }; /* size: 36, cachelines: 1 */ /* last cacheline: 36 bytes */ Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
2007-04-28 15:01:54 +02:00
uint32_t base_offset, uint8_t expand_types,
uint8_t indent, int type_spacing,
int name_spacing, int emit_stats, FILE *fp);
extern size_t tag__fprintf(const struct tag *self, const struct cu *cu,
const char *prefix, const char *suffix,
[LIB]: Use a base_offset when printing inner structs That way we can have the offsets from the top level struct. If the user wants to focus some inner struct, just call the tool again specifying the inner struct name. Perhaps this is not so clear, shoot me, erm, no, an example should help. Look at the member offsets (first column in the comment after each member), before and after: before: acme@filo pahole]$ pahole -C tcp_sock --expand_types examples/net /* <12a> examples/expand.c:18 */ struct tcp_sock { struct inet_sock { struct sock { int protocol; /* 0 4 */ struct spinlock { int magic; /* 0 4 */ int counter; /* 4 4 */ } sklock; /* 4 8 */ int b; /* 12 4 */ int c; /* 16 4 */ } sk; /* 0 20 */ long int daddr; /* 20 4 */ } inet; /* 0 24 */ long int cwnd; /* 24 4 */ struct spinlock { int magic; /* 0 4 */ int counter; /* 4 4 */ } lock; /* 28 8 */ }; /* size: 36, cachelines: 1 */ /* last cacheline: 36 bytes */ After: acme@filo pahole]$ pahole -C tcp_sock --expand_types examples/net /* <12a> examples/expand.c:18 */ struct tcp_sock { struct inet_sock { struct sock { int protocol; /* 0 4 */ struct spinlock { int magic; /* 4 4 */ int counter; /* 8 4 */ } sklock; /* 4 8 */ int b; /* 12 4 */ int c; /* 16 4 */ } sk; /* 0 20 */ long int daddr; /* 20 4 */ } inet; /* 0 24 */ long int cwnd; /* 24 4 */ struct spinlock { int magic; /* 28 4 */ int counter; /* 32 4 */ } lock; /* 28 8 */ }; /* size: 36, cachelines: 1 */ /* last cacheline: 36 bytes */ Signed-off-by: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
2007-04-28 15:01:54 +02:00
uint32_t base_offset, uint8_t expand_types,
FILE *fp);
extern const char *function__name(struct function *self, const struct cu *cu);
extern size_t function__fprintf_stats(const struct tag *tag_self,
const struct cu *cu, FILE *fp);
extern size_t lexblock__fprintf(const struct lexblock *self,
const struct cu *cu,
uint16_t indent, FILE *fp);
extern struct cus *cus__new(struct list_head *definitions,
struct list_head *fwd_decls);
extern int cus__loadfl(struct cus *self, struct argp *argp,
int argc, char *argv[]);
extern int cus__load(struct cus *self, const char *filename);
extern int cus__load_dir(struct cus *self, const char *dirname,
const char *filename_mask, const int recursive);
extern void cus__print_error_msg(const char *progname, const char *filename,
const int err);
extern struct cu *cus__find_cu_by_name(const struct cus *self,
const char *name);
extern struct tag *cu__find_base_type_by_name(const struct cu *self,
const char *name);
extern struct tag *cus__find_struct_by_name(const struct cus *self,
struct cu **cu,
const char *name);
extern struct tag *cus__find_function_by_name(const struct cus *self,
struct cu **cu,
const char *name);
extern int cus__emit_ftype_definitions(struct cus *self, struct cu *cu,
struct ftype *ftype, FILE *fp);
extern int cus__emit_type_definitions(struct cus *self, struct cu *cu,
struct tag *tag, FILE *fp);
extern int cus__emit_fwd_decl(struct cus *self, struct type *ctype, FILE *fp);
extern void type__emit(struct tag *tag_self, struct cu *cu,
const char *prefix, const char *suffix, FILE *fp);
extern struct tag *cu__find_tag_by_id(const struct cu *self,
const Dwarf_Off id);
extern struct tag *cu__find_first_typedef_of_type(const struct cu *self,
const Dwarf_Off type);
extern struct tag *cu__find_struct_by_name(const struct cu *cu,
const char *name);
extern void cu__account_inline_expansions(struct cu *self);
extern int cu__for_each_tag(struct cu *self,
int (*iterator)(struct tag *tag,
struct cu *cu,
void *cookie),
void *cookie,
struct tag *(*filter)(struct tag *tag,
struct cu *cu,
void *cookie));
extern void cus__for_each_cu(struct cus *self,
int (*iterator)(struct cu *cu,
void *cookie),
void *cookie,
struct cu *(*filter)(struct cu *cu));
extern const struct class_member *
class__find_bit_hole(const struct class *self,
const struct class_member *trailer,
const size_t bit_hole_size);
extern struct tag *cu__find_function_by_name(const struct cu *cu,
const char *name);
static inline size_t function__size(const struct function *self)
{
return self->lexblock.high_pc - self->lexblock.low_pc;
}
static inline int function__declared_inline(const struct function *self)
{
return (self->inlined == DW_INL_declared_inlined ||
self->inlined == DW_INL_declared_not_inlined);
}
static inline int function__inlined(const struct function *self)
{
return (self->inlined == DW_INL_inlined ||
self->inlined == DW_INL_declared_inlined);
}
extern size_t ftype__fprintf(const struct ftype *self, const struct cu *cu,
const char *name, const int inlined,
const int is_pointer, const int type_spacing,
FILE *fp);
extern int ftype__has_parm_of_type(const struct ftype *self,
const struct tag *target,
const struct cu *cu);
extern const char *tag__name(const struct tag *self, const struct cu *cu,
char *bf, size_t len);
extern size_t tag__size(const struct tag *self, const struct cu *cu);
extern size_t tag__nr_cachelines(const struct tag *self, const struct cu *cu);
extern struct class_member *type__find_member_by_name(const struct type *self,
const char *name);
static inline struct class_member *
class__find_member_by_name(const struct class *self, const char *name)
{
return type__find_member_by_name(&self->type, name);
}
static inline uint16_t class__nr_members(const struct class *self)
{
return self->type.nr_members;
}
static inline size_t class__size(const struct class *self)
{
return self->type.size;
}
static inline int class__is_declaration(const struct class *self)
{
return self->type.declaration;
}
[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 const char *variable__name(const struct variable *self,
const struct cu *cu);
extern const char *variable__type_name(const struct variable *self,
const struct cu *cu,
char *bf, size_t len);
extern const char *dwarf_tag_name(const uint32_t tag);
#endif /* _DWARVES_H_ */