2007-01-29 13:42:03 +01:00
|
|
|
#ifndef _DWARVES_H_
|
|
|
|
#define _DWARVES_H_ 1
|
2006-10-28 18:45:59 +02:00
|
|
|
/*
|
|
|
|
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>
|
2007-02-01 16:50:28 +01:00
|
|
|
#include <stdio.h>
|
2006-11-18 22:02:55 +01:00
|
|
|
#include <dwarf.h>
|
2006-12-24 15:07:41 +01:00
|
|
|
#include <elfutils/libdw.h>
|
2006-10-28 18:45:59 +02:00
|
|
|
|
|
|
|
#include "list.h"
|
|
|
|
|
2007-03-30 18:54:14 +02:00
|
|
|
struct argp;
|
|
|
|
|
2007-01-29 13:42:03 +01:00
|
|
|
#ifndef __unused
|
|
|
|
#define __unused __attribute__ ((unused))
|
|
|
|
#endif
|
|
|
|
|
2006-11-11 19:31:04 +01:00
|
|
|
struct cus {
|
|
|
|
struct list_head cus;
|
2007-01-07 15:30:58 +01:00
|
|
|
struct list_head priv_definitions; /* struct type entries */
|
|
|
|
struct list_head priv_fwd_decls; /* struct class entries */
|
2006-12-27 17:39:37 +01:00
|
|
|
struct list_head *definitions;
|
|
|
|
struct list_head *fwd_decls;
|
2006-11-11 19:31:04 +01:00
|
|
|
};
|
|
|
|
|
2006-10-31 20:12:42 +01:00
|
|
|
struct cu {
|
|
|
|
struct list_head node;
|
2007-01-04 00:29:24 +01:00
|
|
|
struct list_head tags;
|
2006-12-20 15:07:09 +01:00
|
|
|
struct list_head tool_list; /* To be used by tools such as ctracer */
|
2006-11-03 18:38:43 +01:00
|
|
|
const char *name;
|
2006-12-29 19:34:11 +01:00
|
|
|
uint8_t addr_size;
|
2006-12-28 14:18:43 +01:00
|
|
|
uint16_t language;
|
2006-11-03 18:38:43 +01:00
|
|
|
unsigned long nr_inline_expansions;
|
2006-12-25 01:27:22 +01:00
|
|
|
size_t size_inline_expansions;
|
2006-12-28 14:18:43 +01:00
|
|
|
uint32_t nr_functions_changed;
|
|
|
|
uint32_t nr_structures_changed;
|
2006-11-12 15:29:33 +01:00
|
|
|
size_t max_len_changed_item;
|
2006-11-11 19:31:04 +01:00
|
|
|
size_t function_bytes_added;
|
|
|
|
size_t function_bytes_removed;
|
2006-10-28 18:45:59 +02:00
|
|
|
};
|
|
|
|
|
2006-11-18 14:54:02 +01:00
|
|
|
struct tag {
|
2006-10-28 18:45:59 +02:00
|
|
|
struct list_head node;
|
2006-12-24 15:18:14 +01:00
|
|
|
Dwarf_Off type;
|
2006-12-24 15:07:41 +01:00
|
|
|
Dwarf_Off id;
|
2006-11-18 14:54:02 +01:00
|
|
|
const char *decl_file;
|
2007-03-07 16:10:56 +01:00
|
|
|
uint16_t decl_line;
|
|
|
|
uint16_t tag;
|
2006-12-29 18:28:58 +01:00
|
|
|
uint32_t refcnt;
|
2006-11-18 14:54:02 +01:00
|
|
|
};
|
|
|
|
|
2007-01-07 15:30:58 +01:00
|
|
|
struct type {
|
2006-11-18 14:54:02 +01:00
|
|
|
struct tag tag;
|
2006-12-23 21:30:48 +01:00
|
|
|
struct list_head node;
|
2006-11-02 17:48:35 +01:00
|
|
|
const char *name;
|
2007-01-09 13:00:47 +01:00
|
|
|
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;
|
2007-01-07 15:30:58 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline struct type *tag__type(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct type *)self;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct class {
|
|
|
|
struct type type;
|
2006-12-28 15:00:21 +01:00
|
|
|
uint8_t nr_holes;
|
|
|
|
uint8_t nr_bit_holes;
|
2006-12-28 14:18:43 +01:00
|
|
|
uint16_t padding;
|
2006-12-28 15:00:21 +01:00
|
|
|
uint8_t bit_padding;
|
2007-01-04 04:41:11 +01:00
|
|
|
void *priv;
|
2006-10-28 18:45:59 +02:00
|
|
|
};
|
|
|
|
|
2007-01-02 05:11:38 +01:00
|
|
|
static inline struct class *tag__class(const struct tag *self)
|
2006-12-29 18:28:58 +01:00
|
|
|
{
|
|
|
|
return (struct class *)self;
|
|
|
|
}
|
|
|
|
|
2007-01-07 15:30:58 +01:00
|
|
|
static inline struct tag *class__tag(const struct class *self)
|
|
|
|
{
|
|
|
|
return (struct tag *)self;
|
|
|
|
}
|
|
|
|
|
2007-02-01 17:09:48 +01:00
|
|
|
extern struct class *class__clone(const struct class *from,
|
|
|
|
const char *new_class_name);
|
|
|
|
extern void class__delete(struct class *self);
|
2007-01-30 16:32:55 +01:00
|
|
|
|
2007-01-07 15:30:58 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2006-12-29 23:58:03 +01:00
|
|
|
struct base_type {
|
|
|
|
struct tag tag;
|
|
|
|
const char *name;
|
|
|
|
size_t size;
|
|
|
|
};
|
|
|
|
|
2007-01-02 05:11:38 +01:00
|
|
|
static inline struct base_type *tag__base_type(const struct tag *self)
|
2006-12-29 23:58:03 +01:00
|
|
|
{
|
|
|
|
return (struct base_type *)self;
|
|
|
|
}
|
|
|
|
|
2006-12-29 18:28:58 +01:00
|
|
|
struct array_type {
|
|
|
|
struct tag tag;
|
|
|
|
uint32_t *nr_entries;
|
|
|
|
uint8_t dimensions;
|
|
|
|
};
|
|
|
|
|
2007-01-02 05:11:38 +01:00
|
|
|
static inline struct array_type *tag__array_type(const struct tag *self)
|
2006-12-29 18:28:58 +01:00
|
|
|
{
|
|
|
|
return (struct array_type *)self;
|
|
|
|
}
|
|
|
|
|
2006-10-28 18:45:59 +02:00
|
|
|
struct class_member {
|
2006-11-18 14:54:02 +01:00
|
|
|
struct tag tag;
|
2006-11-02 17:48:35 +01:00
|
|
|
char *name;
|
2007-04-02 03:08:21 +02:00
|
|
|
uint32_t offset;
|
2006-12-28 13:09:18 +01:00
|
|
|
uint8_t bit_offset;
|
|
|
|
uint8_t bit_size;
|
|
|
|
uint8_t bit_hole; /* If there is a bit hole before the next
|
2006-10-28 23:10:47 +02:00
|
|
|
one (or the end of the struct) */
|
2006-12-28 13:09:18 +01:00
|
|
|
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) */
|
2006-10-28 18:45:59 +02:00
|
|
|
};
|
|
|
|
|
2007-01-30 16:32:55 +01:00
|
|
|
extern size_t class_member__size(const struct class_member *self,
|
|
|
|
const struct cu *cu);
|
2007-02-01 16:17:41 +01:00
|
|
|
extern void class_member__delete(struct class_member *self);
|
2007-01-30 16:32:55 +01:00
|
|
|
|
2006-11-20 19:38:47 +01:00
|
|
|
struct lexblock {
|
2007-01-02 16:25:56 +01:00
|
|
|
struct tag tag;
|
2007-01-03 01:26:01 +01:00
|
|
|
struct list_head tags;
|
2007-01-02 16:25:56 +01:00
|
|
|
Dwarf_Addr low_pc;
|
|
|
|
Dwarf_Addr high_pc;
|
2006-12-28 14:18:43 +01:00
|
|
|
uint16_t nr_inline_expansions;
|
|
|
|
uint16_t nr_labels;
|
|
|
|
uint16_t nr_variables;
|
2007-01-02 16:25:56 +01:00
|
|
|
uint16_t nr_lexblocks;
|
2006-12-25 01:27:22 +01:00
|
|
|
size_t size_inline_expansions;
|
2006-11-20 19:38:47 +01:00
|
|
|
};
|
|
|
|
|
2007-01-03 01:26:01 +01:00
|
|
|
static inline struct lexblock *tag__lexblock(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct lexblock *)self;
|
|
|
|
}
|
|
|
|
|
2006-12-30 19:34:20 +01:00
|
|
|
/*
|
|
|
|
* tag.tag can be DW_TAG_subprogram_type or DW_TAG_subroutine_type.
|
|
|
|
*/
|
|
|
|
struct ftype {
|
2006-11-18 17:33:48 +01:00
|
|
|
struct tag tag;
|
2006-12-30 19:34:20 +01:00
|
|
|
struct list_head parms;
|
|
|
|
uint16_t nr_parms;
|
[CLASSES]: Introduce DW_TAG_subroutine_type specific parser
So that we handle DW_TAG_formal_parameters in this tag, fixing
these cases:
--- /tmp/ctracer.c.before 2006-12-29 13:27:24.000000000 -0200
+++ /tmp/ctracer.c 2007-01-02 02:34:18.000000000 -0200
<SNIP>
@@ -62,7 +62,7 @@
}; /* size: 68, cachelines: 3 */
/* last cacheline: 4 bytes */
-typedef int (*kretprobe_handler_t)(void /* FIXME: add parm list */);
+typedef int (*kretprobe_handler_t)(struct kretprobe_instance *, struct pt_regs *);
/* /pub/scm/linux/kernel/git/acme/linux-2.6/include/linux/list.h:607 */
struct hlist_head {
struct hlist_node * first; /* 0 4 */
[acme@newtoy ctracer_example]$
--- /tmp/pfunct.before 2006-12-30 16:18:25.000000000 -0200
+++ /tmp/pfunct.after 2007-01-02 02:08:50.000000000 -0200
@@ -249,7 +249,7 @@
/* definitions: 1 */
/* /pub/scm/linux/kernel/git/acme/linux-2.6/lib/klist.c:57 */
-void klist_init(struct klist * k, * get, * put);
+void klist_init(struct klist * k, void (*get)(struct klist_node *), void (*put)(struct klist_node *));
/* size: 12, inline expansions: 1 (5 bytes) */
/* definitions: 1 */
The struct/union case still needs fixing, but we're getting there...
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2007-01-02 05:42:33 +01:00
|
|
|
uint8_t unspec_parms; /* just one bit is needed */
|
2006-12-30 19:34:20 +01:00
|
|
|
};
|
|
|
|
|
[CLASSES]: Introduce DW_TAG_subroutine_type specific parser
So that we handle DW_TAG_formal_parameters in this tag, fixing
these cases:
--- /tmp/ctracer.c.before 2006-12-29 13:27:24.000000000 -0200
+++ /tmp/ctracer.c 2007-01-02 02:34:18.000000000 -0200
<SNIP>
@@ -62,7 +62,7 @@
}; /* size: 68, cachelines: 3 */
/* last cacheline: 4 bytes */
-typedef int (*kretprobe_handler_t)(void /* FIXME: add parm list */);
+typedef int (*kretprobe_handler_t)(struct kretprobe_instance *, struct pt_regs *);
/* /pub/scm/linux/kernel/git/acme/linux-2.6/include/linux/list.h:607 */
struct hlist_head {
struct hlist_node * first; /* 0 4 */
[acme@newtoy ctracer_example]$
--- /tmp/pfunct.before 2006-12-30 16:18:25.000000000 -0200
+++ /tmp/pfunct.after 2007-01-02 02:08:50.000000000 -0200
@@ -249,7 +249,7 @@
/* definitions: 1 */
/* /pub/scm/linux/kernel/git/acme/linux-2.6/lib/klist.c:57 */
-void klist_init(struct klist * k, * get, * put);
+void klist_init(struct klist * k, void (*get)(struct klist_node *), void (*put)(struct klist_node *));
/* size: 12, inline expansions: 1 (5 bytes) */
/* definitions: 1 */
The struct/union case still needs fixing, but we're getting there...
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2007-01-02 05:42:33 +01:00
|
|
|
static inline struct ftype *tag__ftype(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct ftype *)self;
|
|
|
|
}
|
|
|
|
|
2006-12-30 19:34:20 +01:00
|
|
|
struct function {
|
|
|
|
struct ftype proto;
|
2006-11-20 19:38:47 +01:00
|
|
|
struct lexblock lexblock;
|
2006-11-18 17:33:48 +01:00
|
|
|
const char *name;
|
2007-01-07 20:13:39 +01:00
|
|
|
Dwarf_Off abstract_origin;
|
2007-01-13 14:37:41 +01:00
|
|
|
Dwarf_Off specification;
|
2006-12-28 15:27:12 +01:00
|
|
|
size_t cu_total_size_inline_expansions;
|
2006-12-30 19:34:20 +01:00
|
|
|
uint16_t cu_total_nr_inline_expansions;
|
2007-01-07 18:13:50 +01:00
|
|
|
uint8_t inlined; /* two bits used */
|
|
|
|
uint8_t external; /* one bit used */
|
2006-12-28 15:27:12 +01:00
|
|
|
/* fields used by tools */
|
|
|
|
struct list_head tool_node;
|
2007-01-04 04:41:11 +01:00
|
|
|
void *priv;
|
2006-11-18 17:33:48 +01:00
|
|
|
};
|
|
|
|
|
2007-01-04 00:29:24 +01:00
|
|
|
static inline struct function *tag__function(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct function *)self;
|
|
|
|
}
|
|
|
|
|
2006-11-18 17:33:48 +01:00
|
|
|
struct parameter {
|
|
|
|
struct tag tag;
|
|
|
|
char *name;
|
2007-01-07 20:57:00 +01:00
|
|
|
Dwarf_Off abstract_origin;
|
2006-11-18 17:33:48 +01:00
|
|
|
};
|
|
|
|
|
2007-01-07 20:57:00 +01:00
|
|
|
static inline struct parameter *tag__parameter(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct parameter *)self;
|
|
|
|
}
|
|
|
|
|
2007-01-29 13:42:03 +01:00
|
|
|
extern Dwarf_Off parameter__type(struct parameter *self, const struct cu *cu);
|
|
|
|
|
2007-02-02 14:56:53 +01:00
|
|
|
enum vlocation {
|
|
|
|
LOCATION_UNKNOWN,
|
|
|
|
LOCATION_LOCAL,
|
|
|
|
LOCATION_GLOBAL,
|
|
|
|
LOCATION_REGISTER,
|
|
|
|
LOCATION_OPTIMIZED
|
|
|
|
};
|
|
|
|
|
[CLASSES]: Introduce struct variable
To represent DW_TAG_variable, for now all the variables in all the lexical
blocks, in addition to the top level function variables are in this list, next
step is to add support for DW_TAG_lexical_block, with support for nesting, and
to associate variables to the right place, be it the function itself (first,
implicit lexical block) or to the lexical blocks they belong too, this will be
useful for calculating stack usage.
So, with what we have now pfunct can do this:
[acme@newtoy guinea_pig-2.6]$ pfunct --variables net/ipv4/built-in.o tcp_v4_remember_stamp
/* net/ipv4/tcp_ipv4.c:1197 */
int tcp_v4_remember_stamp(struct sock * sk);
{
/* variables in tcp_v4_remember_stamp: */
struct inet_sock * inet;
struct tcp_sock * tp;
struct rtable * rt;
struct inet_peer * peer;
int release_it;
}
[acme@newtoy guinea_pig-2.6]$
That is already useful when you don't have the sources, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-05 04:31:41 +01:00
|
|
|
struct variable {
|
2006-11-18 14:54:02 +01:00
|
|
|
struct tag tag;
|
[CLASSES]: Introduce struct variable
To represent DW_TAG_variable, for now all the variables in all the lexical
blocks, in addition to the top level function variables are in this list, next
step is to add support for DW_TAG_lexical_block, with support for nesting, and
to associate variables to the right place, be it the function itself (first,
implicit lexical block) or to the lexical blocks they belong too, this will be
useful for calculating stack usage.
So, with what we have now pfunct can do this:
[acme@newtoy guinea_pig-2.6]$ pfunct --variables net/ipv4/built-in.o tcp_v4_remember_stamp
/* net/ipv4/tcp_ipv4.c:1197 */
int tcp_v4_remember_stamp(struct sock * sk);
{
/* variables in tcp_v4_remember_stamp: */
struct inet_sock * inet;
struct tcp_sock * tp;
struct rtable * rt;
struct inet_peer * peer;
int release_it;
}
[acme@newtoy guinea_pig-2.6]$
That is already useful when you don't have the sources, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-05 04:31:41 +01:00
|
|
|
char *name;
|
2006-12-28 12:38:40 +01:00
|
|
|
Dwarf_Off abstract_origin;
|
2007-02-02 14:56:53 +01:00
|
|
|
uint8_t external:1;
|
|
|
|
uint8_t declaration:1;
|
|
|
|
enum vlocation location;
|
[CLASSES]: Introduce struct variable
To represent DW_TAG_variable, for now all the variables in all the lexical
blocks, in addition to the top level function variables are in this list, next
step is to add support for DW_TAG_lexical_block, with support for nesting, and
to associate variables to the right place, be it the function itself (first,
implicit lexical block) or to the lexical blocks they belong too, this will be
useful for calculating stack usage.
So, with what we have now pfunct can do this:
[acme@newtoy guinea_pig-2.6]$ pfunct --variables net/ipv4/built-in.o tcp_v4_remember_stamp
/* net/ipv4/tcp_ipv4.c:1197 */
int tcp_v4_remember_stamp(struct sock * sk);
{
/* variables in tcp_v4_remember_stamp: */
struct inet_sock * inet;
struct tcp_sock * tp;
struct rtable * rt;
struct inet_peer * peer;
int release_it;
}
[acme@newtoy guinea_pig-2.6]$
That is already useful when you don't have the sources, huh? :-)
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-05 04:31:41 +01:00
|
|
|
};
|
|
|
|
|
2007-01-03 01:26:01 +01:00
|
|
|
static inline struct variable *tag__variable(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct variable *)self;
|
|
|
|
}
|
|
|
|
|
2006-11-03 16:41:19 +01:00
|
|
|
struct inline_expansion {
|
2006-11-18 14:54:02 +01:00
|
|
|
struct tag tag;
|
2006-12-25 01:27:22 +01:00
|
|
|
size_t size;
|
2006-12-26 14:44:05 +01:00
|
|
|
Dwarf_Addr low_pc;
|
|
|
|
Dwarf_Addr high_pc;
|
2006-11-03 16:41:19 +01:00
|
|
|
};
|
|
|
|
|
2007-01-03 01:26:01 +01:00
|
|
|
static inline struct inline_expansion *
|
|
|
|
tag__inline_expansion(const struct tag *self)
|
|
|
|
{
|
|
|
|
return (struct inline_expansion *)self;
|
|
|
|
}
|
|
|
|
|
2006-11-20 19:17:42 +01:00
|
|
|
struct label {
|
|
|
|
struct tag tag;
|
|
|
|
char *name;
|
2006-12-28 12:36:39 +01:00
|
|
|
Dwarf_Addr low_pc;
|
2006-11-20 19:17:42 +01:00
|
|
|
};
|
|
|
|
|
[CLASSES]: Add support for enums
Be it named enums such as:
/* include/linux/pid.h:7 */
enum pid_type {
PIDTYPE_PID = 0,
PIDTYPE_PGID = 1,
PIDTYPE_SID = 2,
PIDTYPE_MAX = 3,
};
Or nameless enums inside structs:
/* include/linux/journal-head.h:14 */
typedef struct transaction_s {
journal_t * t_journal; /* 0 4 */
tid_t t_tid; /* 4 4 */
enum {
T_RUNNING = 0,
T_LOCKED = 1,
T_RUNDOWN = 2,
T_FLUSH = 3,
T_COMMIT = 4,
T_FINISHED = 5,
} t_state; /* 8 4 */
long unsigned int t_log_start; /* 12 4 */
<SNIP>
} transaction_t; /* size: 84, cachelines: 3 */
/* last cacheline: 20 bytes */
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-12-24 14:56:59 +01:00
|
|
|
struct enumerator {
|
|
|
|
struct tag tag;
|
|
|
|
const char *name;
|
|
|
|
uint32_t value;
|
|
|
|
};
|
|
|
|
|
2007-04-28 21:13:35 +02:00
|
|
|
struct conf_fprintf {
|
|
|
|
const char *prefix;
|
|
|
|
const char *suffix;
|
|
|
|
uint32_t base_offset;
|
|
|
|
uint8_t expand_types;
|
2007-05-02 21:14:20 +02:00
|
|
|
uint8_t rel_offset;
|
2007-04-28 21:13:35 +02:00
|
|
|
uint8_t emit_stats;
|
|
|
|
uint8_t indent;
|
|
|
|
int32_t type_spacing;
|
|
|
|
int32_t name_spacing;
|
|
|
|
};
|
|
|
|
|
2007-01-19 00:41:25 +01:00
|
|
|
extern void dwarves__init(size_t user_cacheline_size);
|
2006-11-05 18:34:54 +01:00
|
|
|
|
2007-01-04 04:41:11 +01:00
|
|
|
extern void class__find_holes(struct class *self, const struct cu *cu);
|
2007-02-15 14:36:49 +01:00
|
|
|
extern size_t class__fprintf(const struct class *self, const struct cu *cu,
|
2007-04-28 21:13:35 +02:00
|
|
|
const struct conf_fprintf *conf, FILE *fp);
|
2007-05-06 19:50:28 +02:00
|
|
|
extern size_t enumeration__fprintf(const struct tag *tag_self,
|
|
|
|
const struct conf_fprintf *conf, FILE *fp);
|
|
|
|
extern size_t typedef__fprintf(const struct tag *tag_self, const struct cu *cu,
|
|
|
|
FILE *fp);
|
|
|
|
extern size_t tag__fprintf_decl_info(const struct tag *self, FILE *fp);
|
2007-02-15 15:03:47 +01:00
|
|
|
extern size_t tag__fprintf(const struct tag *self, const struct cu *cu,
|
2007-04-28 21:13:35 +02:00
|
|
|
const struct conf_fprintf *conf, FILE *fp);
|
2007-01-07 20:13:39 +01:00
|
|
|
|
|
|
|
extern const char *function__name(struct function *self, const struct cu *cu);
|
2007-02-15 15:01:01 +01:00
|
|
|
extern size_t function__fprintf_stats(const struct tag *tag_self,
|
|
|
|
const struct cu *cu, FILE *fp);
|
2006-10-28 23:22:42 +02:00
|
|
|
|
2007-02-15 14:56:16 +01:00
|
|
|
extern size_t lexblock__fprintf(const struct lexblock *self,
|
|
|
|
const struct cu *cu,
|
|
|
|
uint16_t indent, FILE *fp);
|
2007-01-13 13:57:19 +01:00
|
|
|
|
2006-12-27 17:39:37 +01:00
|
|
|
extern struct cus *cus__new(struct list_head *definitions,
|
|
|
|
struct list_head *fwd_decls);
|
2007-03-30 18:54:14 +02:00
|
|
|
extern int cus__loadfl(struct cus *self, struct argp *argp,
|
2007-04-24 21:09:34 +02:00
|
|
|
int argc, char *argv[]);
|
2006-12-27 17:39:37 +01:00
|
|
|
extern int cus__load(struct cus *self, const char *filename);
|
2006-12-27 17:57:19 +01:00
|
|
|
extern int cus__load_dir(struct cus *self, const char *dirname,
|
|
|
|
const char *filename_mask, const int recursive);
|
2007-03-28 17:54:46 +02:00
|
|
|
extern void cus__print_error_msg(const char *progname, const char *filename,
|
|
|
|
const int err);
|
2006-12-27 17:39:37 +01:00
|
|
|
extern struct cu *cus__find_cu_by_name(const struct cus *self,
|
|
|
|
const char *name);
|
2007-01-30 19:53:01 +01:00
|
|
|
extern struct tag *cu__find_base_type_by_name(const struct cu *self,
|
|
|
|
const char *name);
|
2007-01-07 16:11:20 +01:00
|
|
|
extern struct tag *cus__find_struct_by_name(const struct cus *self,
|
|
|
|
struct cu **cu,
|
|
|
|
const char *name);
|
2007-01-12 18:47:26 +01:00
|
|
|
extern struct tag *cus__find_function_by_name(const struct cus *self,
|
|
|
|
struct cu **cu,
|
|
|
|
const char *name);
|
2006-12-23 22:29:27 +01:00
|
|
|
|
2006-12-29 18:28:58 +01:00
|
|
|
extern struct tag *cu__find_tag_by_id(const struct cu *self,
|
|
|
|
const Dwarf_Off id);
|
2007-01-28 14:07:22 +01:00
|
|
|
extern struct tag *cu__find_first_typedef_of_type(const struct cu *self,
|
|
|
|
const Dwarf_Off type);
|
2007-01-07 16:11:20 +01:00
|
|
|
extern struct tag *cu__find_struct_by_name(const struct cu *cu,
|
|
|
|
const char *name);
|
2006-11-03 18:38:43 +01:00
|
|
|
extern void cu__account_inline_expansions(struct cu *self);
|
2006-12-29 18:28:58 +01:00
|
|
|
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,
|
2007-01-04 00:29:24 +01:00
|
|
|
struct cu *cu,
|
|
|
|
void *cookie));
|
2006-11-11 19:31:04 +01:00
|
|
|
extern void cus__for_each_cu(struct cus *self,
|
|
|
|
int (*iterator)(struct cu *cu,
|
2006-10-31 21:23:16 +01:00
|
|
|
void *cookie),
|
2006-12-01 02:48:34 +01:00
|
|
|
void *cookie,
|
|
|
|
struct cu *(*filter)(struct cu *cu));
|
2006-10-28 23:22:42 +02:00
|
|
|
|
2006-12-07 19:11:47 +01:00
|
|
|
extern const struct class_member *
|
|
|
|
class__find_bit_hole(const struct class *self,
|
|
|
|
const struct class_member *trailer,
|
|
|
|
const size_t bit_hole_size);
|
|
|
|
|
2007-01-12 18:47:26 +01:00
|
|
|
extern struct tag *cu__find_function_by_name(const struct cu *cu,
|
|
|
|
const char *name);
|
2006-11-18 17:33:48 +01:00
|
|
|
|
2006-12-25 01:27:22 +01:00
|
|
|
static inline size_t function__size(const struct function *self)
|
2006-11-11 19:31:04 +01:00
|
|
|
{
|
2007-01-02 16:25:56 +01:00
|
|
|
return self->lexblock.high_pc - self->lexblock.low_pc;
|
2006-11-11 19:31:04 +01:00
|
|
|
}
|
|
|
|
|
2006-11-18 22:02:55 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2007-02-15 14:36:49 +01:00
|
|
|
extern size_t ftype__fprintf(const struct ftype *self, const struct cu *cu,
|
|
|
|
const char *name, const int inlined,
|
2007-03-28 16:38:32 +02:00
|
|
|
const int is_pointer, const int type_spacing,
|
2007-02-15 14:36:49 +01:00
|
|
|
FILE *fp);
|
2007-01-02 05:37:24 +01:00
|
|
|
extern int ftype__has_parm_of_type(const struct ftype *self,
|
|
|
|
const struct tag *target,
|
|
|
|
const struct cu *cu);
|
2006-12-20 15:03:12 +01:00
|
|
|
|
2006-12-29 18:28:58 +01:00
|
|
|
extern const char *tag__name(const struct tag *self, const struct cu *cu,
|
|
|
|
char *bf, size_t len);
|
2007-01-09 18:10:31 +01:00
|
|
|
extern size_t tag__size(const struct tag *self, const struct cu *cu);
|
2007-01-30 16:32:55 +01:00
|
|
|
extern size_t tag__nr_cachelines(const struct tag *self, const struct cu *cu);
|
2006-12-19 12:11:17 +01:00
|
|
|
|
2007-01-09 13:00:47 +01:00
|
|
|
extern struct class_member *type__find_member_by_name(const struct type *self,
|
|
|
|
const char *name);
|
2007-05-10 20:28:00 +02:00
|
|
|
extern uint32_t type__nr_members_of_type(const struct type *self,
|
|
|
|
const Dwarf_Off type);
|
2007-01-09 13:00:47 +01:00
|
|
|
|
|
|
|
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
|
|
|
|
2007-01-03 01:26:01 +01:00
|
|
|
extern const char *variable__name(const struct variable *self,
|
|
|
|
const struct cu *cu);
|
2006-11-20 18:43:39 +01:00
|
|
|
extern const char *variable__type_name(const struct variable *self,
|
2007-01-03 01:26:01 +01:00
|
|
|
const struct cu *cu,
|
2006-11-20 18:43:39 +01:00
|
|
|
char *bf, size_t len);
|
|
|
|
|
2006-12-28 14:18:43 +01:00
|
|
|
extern const char *dwarf_tag_name(const uint32_t tag);
|
2007-01-29 13:42:03 +01:00
|
|
|
#endif /* _DWARVES_H_ */
|