Commit Graph

2001 Commits

Author SHA1 Message Date
Arnaldo Carvalho de Melo cb883f6a8f [PAHOLE]: First stab at implementing --packable
That is to find structs that have combinable holes, trying to pack the struct
by suggesting a move, for now it just prints structs that have holes that can
be combined, but these hints are not guaranteed to generate struct size
reductions, more has to be done and that involves understanding the alignment
rules that depend on the arch being 32 or 64 bits, but it at least reduces the
number of packing candidates.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 16:14:15 -02:00
Arnaldo Carvalho de Melo 82892cd9dd [CLASSES]: First stab at implementing class__find_bit_hole
This new function searches the first member before the one being traversed that
has a bit hole (or byte_hole, I've just normalised it on bits to make it
generic) that can be used to combine with the class_member at hand to possibly
kill a hole, possibly because for now it doesn't guarantees that moving the
member being traversed to just after the hole after the member returned by
class__find_bit_hole will indeed reduce the struct size, but its a good first
stab, next csets should provide a member to start from so that we can try to
find other holes after the one that proved not enough to reduce the struct
size.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 16:11:47 -02:00
Arnaldo Carvalho de Melo ff0dc936d7 [CLASSES]: Tidy up holes printing, plural form
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 13:24:18 -02:00
Arnaldo Carvalho de Melo c5a4d29825 [PAHOLE]: Introduce --bit_holes
So that we can see only the structs that have more than the specified number of
bit holes.

Can be combined with --holes to see structs that have bit and byte holes.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 13:08:20 -02:00
Arnaldo Carvalho de Melo 2ac0afbf8e [CLASSES]: Tidy up holes annotations
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 13:07:22 -02:00
Arnaldo Carvalho de Melo a373c28ba9 [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 12:26:50 -02:00
Arnaldo Carvalho de Melo fb4fed3164 [CLASSES]: Fix cacheline boundary crossings
I not taking into account the sum of holes, so the math drifted when holes were
present.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 11:26:48 -02:00
Arnaldo Carvalho de Melo 8d19574248 [CLASSES]: Improve cacheline boundary printing
Now we show more cacheline boundaries by looking at when we cross cachelines,
not just when there is a exact cacheline boundary, an (long) example to
clarify:

[acme@newtoy net-2.6]$ pahole ../OUTPUT/qemu/net-2.6/fs/built-in.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 ----- */
        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 was 2 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 */
        unsigned int               time_slice;           /*    96     4 */
        /* ----- cacheline 3 boundary was 2 bytes ago ----- */
        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 */
        struct mm_struct *         mm;                   /*   128     4 */
        /* ----- cacheline 4 boundary was 2 bytes ago ----- */
        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 */
        unsigned int               did_exec:1;           /*   160     4 */
        /* ----- cacheline 5 boundary was 2 bytes ago ----- */
        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 was 2 bytes ago ----- */
        struct task_struct *       group_leader;         /*   196     4 */
        struct pid_link            pids[3];              /*   200    36 */
        /* ----- cacheline 7 boundary was 10 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 */
        long unsigned int          rt_priority;          /*   256     4 */
        /* ----- cacheline 8 boundary was 2 bytes ago ----- */
        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 */
        long unsigned int          maj_flt;              /*   288     4 */
        /* ----- cacheline 9 boundary was 2 bytes ago ----- */
        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 was 10 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 */
        gid_t                      egid;                 /*   352     4 */
        /* ----- cacheline 11 boundary was 2 bytes ago ----- */
        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 */
        struct user_struct *       user;                 /*   384     4 */
        /* ----- cacheline 12 boundary was 2 bytes ago ----- */
        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 ----- */
        int                        link_count;           /*   420     4 */
        int                        total_link_count;     /*   424     4 */
        struct sysv_sem            sysvsem;              /*   428     4 */
        struct thread_struct       thread;               /*   432   656 */
        /* ----- cacheline 33 boundary was 28 bytes ago ----- */
        struct fs_struct *         fs;                   /*  1088     4 */
        /* ----- cacheline 34 boundary ----- */
        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 ----- */
        sigset_t                   saved_sigmask;        /*  1124     8 */
        struct sigpending          pending;              /*  1132    16 */
        long unsigned int          sas_ss_sp;            /*  1148     4 */
        size_t                     sas_ss_size;          /*  1152     4 */
        /* ----- cacheline 36 boundary ----- */
        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 */
        spinlock_t                 alloc_lock;           /*  1184    40 */
        /* ----- cacheline 38 boundary was 4 bytes ago ----- */
        spinlock_t                 pi_lock;              /*  1224    40 */
        /* ----- cacheline 39 boundary was 12 bytes ago ----- */
        struct plist_head          pi_waiters;           /*  1264    20 */
        /* ----- cacheline 40 boundary ----- */
        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 */
        unsigned int               hardirq_disable_event; /*  1312     4 */
        /* ----- cacheline 41 boundary ----- */
        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 */
        u64                        curr_chain_key;       /*  1344     8 */
        /* ----- cacheline 42 boundary was 4 bytes ago ----- */
        int                        lockdep_depth;        /*  1352     4 */
        struct held_lock           held_locks[30];       /*  1356  1200 */
        /* ----- cacheline 79 boundary was 24 bytes ago ----- */
        unsigned int               lockdep_recursion;    /*  2556     4 */
        void *                     journal_info;         /*  2560     4 */
        /* ----- cacheline 80 boundary ----- */
        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 ----- */
        u64                        wchar;                /*  2596     8 */
        u64                        syscr;                /*  2604     8 */
        u64                        syscw;                /*  2612     8 */
        struct robust_list_head *  robust_list;          /*  2620     4 */
        struct list_head           pi_state_list;        /*  2624     8 */
        /* ----- cacheline 82 boundary was 4 bytes ago ----- */
        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, sum members: 2648, holes: 2, sum holes: 4, padding: 4, cachelines: 83 */

[acme@newtoy net-2.6]$

See the "cacheline 82 boundary was 4 bytes ago" type comments? They show cases
where members cross cachelines (in this case a 32 bytes cacheline was used, the
default when one doesn't specify one with --cacheline in the pahole cmd line).

This should help in reorganizing struct layouts to avoid bringing two
cachelines when, say, a 'int' member is accessed, i.e. better aligning the
members to avoid cacheline trashing.

One seemingly interesting idea now that we have this infrastructure is to write
code to suggest reorganizing a struct to avoid these cacheline boundary
crossings, kill holes, etc, this together with static analysis on binaries or
using sparse to look member usage patterns, i.e. if io_wait is almost always
used after wchar in task_struct, we would move them to be on the same
cacheline, of course there are cases where data dependency may be an obstacle,
we'd need blacklists to help the tool avoid moving these cases.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-07 04:20:42 -02:00
Arnaldo Carvalho de Melo 91c91fc822 [CLASSES]: Fix class__print_struct identation
No code changes

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-06 15:09:36 -02:00
Arnaldo Carvalho de Melo 441d9e0d5c [CLASSES]: Make class_member__print just print the member
Not printing the identation neither the newline, so that in the next csets
it'll be possible to show members that cross cacheline boundaries and also do
multiple levels of identation when we start supporting classes within classes
printing, to properly support C++.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-06 15:00:48 -02:00
Arnaldo Carvalho de Melo 2e0b628f16 [CLASSES]: Default to create classes for non structs too in class context
Supporting the C++ a bit more, enums, etc are basically handled inside
cu__process_class.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-06 14:23:54 -02:00
Arnaldo Carvalho de Melo c6ad98fc08 [CLASSES]: First bits of C++ support
Now we support classes within classes, i.e. DW_TAG_structure_type entries
within DW_TAG_structure_type, a C++ feature, see the FIXME in the new code.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-06 11:35:21 -02:00
Arnaldo Carvalho de Melo 314d8f65bb [MAKEFILE]: Use -fPIC in CFLAGS
To fix this on parisc:

acme@parisc:~/pahole$ make
gcc -g -O2 -Wall -I. -I/usr/include/elfutils  -c -o pahole.o pahole.c
gcc -g -O2 -Wall -I. -I/usr/include/elfutils  -c -o classes.o classes.c
gcc -shared \
          -o libclasses.so.1.0.0 classes.o
/usr/bin/ld: classes.o: relocation R_PARISC_DPREL21L can not be used when making a shared object; recompile with -fPIC
classes.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
make: *** [libclasses.so] Error 1
acme@parisc:~/pahole$

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 22:05:54 -02:00
Bernhard Fischer c9be4684fe [PAHOLE]: make some functions static
These are currently only used by pahole and would live in classes otherwise.

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 14:58:27 -02:00
Bernhard Fischer a35aa33be8 [PAHOLE]: trim some superfluous whitespace
No object-code changes.

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 14:56:47 -02:00
Bernhard Fischer 10b1299dea [PAHOLE]: save a few bytes on-disk
Merge option parsing variables into one opts variable.

   text    data     bss     dec     hex filename
  25006     660      44   25710    646e pahole.orig
  24974     660      44   25678    644e pahole

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 14:55:31 -02:00
Bernhard Fischer 76bf0ada17 [CLASSES]: avoid mixing declarations and code
avoid mixing declarations and code to please ISO C90.

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 14:53:50 -02:00
Bernhard Fischer 88343b7460 [CLASSES]: build classes as a library
Build classes.c as a library. If STATIC=1, then link against the static lib,
else use a shared libclasses.

For the lazy, specify an rpath when linking dynamically (for now).

Set initial libclasses version to 1.0.0, don't use any fancy ld flags for now.

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-05 14:48:50 -02:00
Arnaldo Carvalho de Melo 1347cff6d9 [PAHOLE]: Make --holes require an argument
The minimum number of holes that a struct must have for it to be
reported, to help in combining holes.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-02 12:51:59 -02:00
Arnaldo Carvalho de Melo b73c5c8d0f [CLASSES]: Print info about cacheline use
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-01 12:22:30 -02:00
Arnaldo Carvalho de Melo d5620cc7fd [PAHOLE]: Implement --decl_exclude
pahole -D /pub/scm/linux/kernel/git/acme/net-2.6.20/include/net/ \
	  ../OUTPUT/qemu/net-2.6.20/net/ipv4/tcp.o

Will exclude all the classes that were defined in files in the
/pub/scm/linux/kernel/git/acme/net-2.6.20/include/net/ directory, note that its
a prefix, not a directory, so one could as well pass
/pub/scm/linux/kernel/git/acme/net-2.6.20/include/net/tcp_ to exclude just the
files in the include/net directory and that start with 'tcp_'.

Now I think I implemented what Bernard wanted, and that is useful for me
as well, of course :-)

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-01 00:08:10 -02:00
Arnaldo Carvalho de Melo 5c777371cd [CLASSES]: Make cu__for_each_class receive a filter
Same semantic as in the cus__for_each_cu filter.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-01 00:00:24 -02:00
Arnaldo Carvalho de Melo e5a400d01f [CLASSES]: Make cus__for_each_cu receive an optional filter
To simplify the callsites and make implementing the same thing on the other
dwarves (prefcnt, pfunct, etc) easy.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 23:48:34 -02:00
Arnaldo Carvalho de Melo 512cb6fce5 [PAHOLE]: Implement --cu_exclude
Doesn't make that much sense for structs, because of the usual includes hell in
most projects, but makes sense for pfunct, so implement it now and later move
it to classes.c.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 23:36:55 -02:00
Arnaldo Carvalho de Melo a9adcc2349 [PAHOLE]: Add 'class__' prefix to exclude_prefix{_len}
As we'll have cu__exclude_prefix{_len} too.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 23:23:41 -02:00
Arnaldo Carvalho de Melo 5631a94760 [PAHOLE]: Introduce class__filter()
That checks for constraints, the first one being a exclude prefix, and is used
by all the iterators.

Additional constraints can be things like specifying prefixes for compilation
unit names, i.e. "show me only the object files which name starts with
net/ipv4/", etc.

Initial patch provided by Bernhard Fischer, who also had the --exclude idea.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 23:12:21 -02:00
Arnaldo Carvalho de Melo f428efa335 [pahole]: reimplement --class_name_len
I somehow deleted this functionality at some point, spotted by Bernhard
Fischer.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 19:35:29 -02:00
Bernhard Fischer 23785f65b7 [pahole]: typo in help text
Correct short option for nr_members in help text.

Signed-off-by: Bernhard Fischer <rep.nop@aon.at>
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-30 19:03:59 -02:00
Arnaldo Carvalho de Melo 71cdd0f588 [CLASSES]: Follow const types to get to the real type
Fixes a bug where 'const char name[29]' was being printed as
'const char name;'.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-29 18:33:22 -02:00
Arnaldo Carvalho de Melo fceec841ca [PAHOLE]: Implement --holes to show only the structs with holes
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-27 15:54:02 -02:00
Arnaldo Carvalho de Melo 674d99e8fa [CLASSES]: Make cu__process_function receive a lexblock pointer
That starts with the root lexblock (&struct function->lexblock), next step will
be to create child lexblocks when finding DW_TAG_lexical_block tags.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 16:59:51 -02:00
Arnaldo Carvalho de Melo 2600c462c2 [CLASSES]: Move the lexblock initialization to lexblock__init
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 16:54:39 -02:00
Arnaldo Carvalho de Melo b31090f722 [CLASSES]: Move more stuff to the lexblock namespace
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 16:51:42 -02:00
Arnaldo Carvalho de Melo 6a3cc448d1 [CLASSES]: Introduce struct lexblock
To represent DW_TAG_lexical_block, for now just group the lists of
labels, inline expansions and variables, struct function now has
the root of the tree as ->lexblock.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 16:38:47 -02:00
Arnaldo Carvalho de Melo 460c5d91f4 [CLASSES]: Implement DW_TAG_label full support
And use it in function__print:

[acme@newtoy net-2.6.20]$ pfunct -Ti net/ipv4/tcp_ipv4.o tcp_v4_err

/* net/ipv4/tcp_ipv4.c:352 */
void tcp_v4_err(struct sk_buff * skb, u32 info);
{
        struct iphdr * iph;                                           //   353
        struct tcphdr * th;                                           //   354
        struct tcp_sock * tp;                                         //   355
        struct inet_sock * inet;                                      //   356
        int type;                                                     //   357
        int code;                                                     //   358
        struct sock * sk;                                             //   359
        __u32 seq;                                                    //   360
        int err;                                                      //   361
        inet_lookup();                                                //   368
        inet_iif();                                                   //   368
        inet_twsk_put();                                              //   375
        __fswab32();                                                  //   390
        do_pmtu_discovery();                                          //   410
        struct request_sock * req;                                    //   424
        struct request_sock * * prev;                                 //   424
        inet_csk_reqsk_queue_drop();                                  //   450
        tcp_done();                                                   //   462

out:                                                                  //   493
        sock_put();                                                   //   495
}

/* size: 1538, variables: 11, goto labels: 1, inline expansions: 10 (1066 bytes) */

Now to support DW_TAG_lexical_block, then to study libelf to fill in the
missing parts with assembly (or C snippets automagically rebuilt from the
assembly ;) ).

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 16:17:42 -02:00
Arnaldo Carvalho de Melo 139cfd3318 [CLASSES]: Enhance function__print
Introducing function__print_body, that orders the tags in a function by the
souce code line where it was declared or inlined.

This finally takes advantage of the struct tag "superclass", more to come in
the form of lexical blocks and goto labels.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 15:43:39 -02:00
Arnaldo Carvalho de Melo 78313d93e7 [CLASSES]: DW_TAG_inlined_subroutines doesn't have DW_AT_decl_{file,line}
It has DW_AT_call_{file,line}, fixed.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 00:36:11 -02:00
Arnaldo Carvalho de Melo bcc85784fe [CLASSES]: Remove stray ; in function__print
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-20 00:26:04 -02:00
Arnaldo Carvalho de Melo a1c8aefe4e [CLASSES]: Support DW_TAG_unspecified_parameters
aka "..."

[acme@newtoy net-2.6.20]$ pfunct kernel/panic.o panic
/* kernel/panic.c:61 */
void panic(const char  * fmt, ...);
/* size: 241, variables: 3, inline expansions: 1 (3 bytes) */

[acme@newtoy net-2.6.20]$

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 21:15:36 -02:00
Arnaldo Carvalho de Melo 7150a7295e [CLASSES]: Rewrite cu__process_die
To get rid of the global variables and make it more clear.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 21:06:03 -02:00
Arnaldo Carvalho de Melo 1bd837749f [CLASSES]: function__print_inline_expansion has to use cu__find_function_by_id
Now that types and functions are in different lists.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 20:30:45 -02:00
Arnaldo Carvalho de Melo 2d4c37208f [PFUNCT]: Introduce --cc_uninlined
I.e. the functions declared as inline but not inlined by the compiler
DW_AT_inline with DW_INL_declared_not_inlined value.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 19:08:37 -02:00
Arnaldo Carvalho de Melo 179e15d553 [PFUNCT]: Differentiate inlining cases
Following what is in the DWARF2 specs:

Name                          Meaning
-----------------------------------------------------------------------------
DW_INL_not_inlined            Not declared inline nor inlined by the compiler
DW_INL_inlined                Not declared inline but inlined by the compiler
DW_INL_declared_not_inlined   Declared inline but not inlined by the compiler
DW_INL_declared_inlined       Declared inline and inlined by the compiler

Take advantae of this and use it in a new pfunct option: --cc_inlined, to
show which functions were of the DW_INL_inlined type.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 19:02:55 -02:00
Arnaldo Carvalho de Melo c9e858a4d1 [CLASSES]: Check if current_function is null
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 16:54:25 -02:00
Arnaldo Carvalho de Melo 46158e90a6 [CLASSES]: Debugging helpers
Commented, not used when not debugging, so far.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 16:32:05 -02:00
Arnaldo Carvalho de Melo bff3938037 [CLASSES]: Introduce struct function & struct parameter
And helper routines, so as to separate DW_TAG_subprogram from
the type tags (DW_TAG_structure_type, basic_type, etc).

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 14:33:48 -02:00
Arnaldo Carvalho de Melo 5afa478d8d [CLASSES]: Introduce struct tag
This should have been done from the start: all DW_TAG_s will be represented by
structs that has as its first member a struct tag, so that we can fully
represent the DWARF information, following csets will take continue the
restructuring.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-18 11:54:02 -02:00
Arnaldo Carvalho de Melo 47845f0f9b [PFUNCT]: Implement --externals
That uses the DW_AT_external attribute, that tells if the DW_TAG_subprogram
(a function) is visible externally.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-17 23:43:08 -02:00
Arnaldo Carvalho de Melo 84a05e88e1 [PREFCNT]: Handle inlined functions too
At least GCC only emits DW_TAG_subprogram for inline functions if they were
used somewhere in the CU, even if no DW_TAG_inlined_subroutine tag is emitted
due to optimizations reducing inline functions to nothing.

Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-17 21:54:34 -02:00
Arnaldo Carvalho de Melo 7ebee113cc [PAHOLE]: Check if we found the struct before calling class__is_struct
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-14 13:30:15 -02:00