2006-10-29 00:07:45 +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 <dwarf.h>
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
#include <getopt.h>
|
|
|
|
#include <stdio.h>
|
2006-10-29 00:07:45 +02:00
|
|
|
#include <stdlib.h>
|
2006-11-01 14:42:18 +01:00
|
|
|
#include <string.h>
|
2006-10-29 00:07:45 +02:00
|
|
|
|
|
|
|
#include "classes.h"
|
|
|
|
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
static int verbose;
|
2006-11-03 16:41:19 +01:00
|
|
|
static int show_inline_expansions;
|
[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
|
|
|
static int show_variables;
|
2006-11-03 20:14:25 +01:00
|
|
|
|
|
|
|
struct inline_function {
|
|
|
|
struct list_head node;
|
|
|
|
const char *name;
|
|
|
|
unsigned long nr_expansions;
|
|
|
|
unsigned long size_expansions;
|
|
|
|
unsigned int nr_files;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct inline_function *inline_function__new(const struct class *class)
|
|
|
|
{
|
|
|
|
struct inline_function *self = malloc(sizeof(*self));
|
|
|
|
|
|
|
|
if (self != NULL) {
|
|
|
|
self->name = class->name;
|
|
|
|
self->nr_files = 1;
|
|
|
|
self->nr_expansions = class->cu_total_nr_inline_expansions;
|
|
|
|
self->size_expansions = class->cu_total_size_inline_expansions;
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
|
|
|
static LIST_HEAD(inlines__list);
|
|
|
|
|
|
|
|
static struct inline_function *inlines__find(const char *name)
|
|
|
|
{
|
|
|
|
struct inline_function *pos;
|
|
|
|
|
|
|
|
list_for_each_entry(pos, &inlines__list, node)
|
|
|
|
if (strcmp(pos->name, name) == 0)
|
|
|
|
return pos;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void inlines__add(const struct class *class)
|
|
|
|
{
|
|
|
|
struct inline_function *inl = inlines__find(class->name);
|
|
|
|
|
|
|
|
if (inl == NULL) {
|
|
|
|
inl = inline_function__new(class);
|
|
|
|
if (inl != NULL)
|
|
|
|
list_add(&inl->node, &inlines__list);
|
|
|
|
} else {
|
|
|
|
inl->nr_expansions += class->cu_total_nr_inline_expansions;
|
|
|
|
inl->size_expansions += class->cu_total_size_inline_expansions;
|
|
|
|
inl->nr_files++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void inline_function__print(struct inline_function *self)
|
|
|
|
{
|
2006-11-11 17:15:50 +01:00
|
|
|
printf("%-31.31s %6lu %7lu %6lu %6u\n", self->name,
|
2006-11-04 21:34:20 +01:00
|
|
|
self->size_expansions, self->nr_expansions,
|
|
|
|
self->size_expansions / self->nr_expansions,
|
|
|
|
self->nr_files);
|
2006-11-03 20:14:25 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void print_total_inline_stats(void)
|
|
|
|
{
|
|
|
|
struct inline_function *pos;
|
|
|
|
|
2006-11-11 00:08:42 +01:00
|
|
|
printf("%-32.32s %5.5s / %5.5s = %5.5s %s\n", "name", "totsz", "exp#", "avgsz", "src#");
|
2006-11-03 20:14:25 +01:00
|
|
|
list_for_each_entry(pos, &inlines__list, node)
|
|
|
|
if (pos->nr_expansions > 1)
|
|
|
|
inline_function__print(pos);
|
|
|
|
}
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
|
|
|
|
static struct option long_options[] = {
|
2006-11-03 16:41:19 +01:00
|
|
|
{ "class", required_argument, NULL, 'c' },
|
2006-11-18 02:43:08 +01:00
|
|
|
{ "externals", no_argument, NULL, 'e' },
|
2006-11-03 18:38:43 +01:00
|
|
|
{ "cu_inline_expansions_stats", no_argument, NULL, 'C' },
|
2006-11-03 16:41:19 +01:00
|
|
|
{ "function_name_len", no_argument, NULL, 'N' },
|
|
|
|
{ "goto_labels", no_argument, NULL, 'g' },
|
2006-11-03 20:14:25 +01:00
|
|
|
{ "inline_expansions", no_argument, NULL, 'i' },
|
2006-11-04 04:11:04 +01:00
|
|
|
{ "inline_expansions_stats", no_argument, NULL, 'I' },
|
2006-11-03 20:14:25 +01:00
|
|
|
{ "total_inline_stats", no_argument, NULL, 't' },
|
2006-11-03 16:41:19 +01:00
|
|
|
{ "help", no_argument, NULL, 'h' },
|
|
|
|
{ "nr_parameters", no_argument, NULL, 'p' },
|
|
|
|
{ "sizes", no_argument, NULL, 's' },
|
[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
|
|
|
{ "nr_variables", no_argument, NULL, 'S' },
|
|
|
|
{ "variables", no_argument, NULL, 'T' },
|
2006-11-03 16:41:19 +01:00
|
|
|
{ "verbose", no_argument, NULL, 'V' },
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
{ NULL, 0, NULL, 0, }
|
|
|
|
};
|
|
|
|
|
|
|
|
static void usage(void)
|
|
|
|
{
|
|
|
|
fprintf(stderr,
|
|
|
|
"usage: pfunct [options] <file_name> {<function_name>}\n"
|
2006-11-01 14:18:01 +01:00
|
|
|
" where: \n"
|
2006-11-03 18:38:43 +01:00
|
|
|
" -c, --class=<class> functions that have <class> "
|
|
|
|
"pointer parameters\n"
|
2006-11-18 02:43:08 +01:00
|
|
|
" -e, --externals show just external functions\n"
|
2006-11-03 18:38:43 +01:00
|
|
|
" -g, --goto_labels show number of goto labels\n"
|
2006-11-03 20:14:25 +01:00
|
|
|
" -i, --inline_expansions show inline expansions\n"
|
2006-11-04 04:11:04 +01:00
|
|
|
" -I, --inline_expansions_stats show inline expansions stats\n"
|
2006-11-03 18:38:43 +01:00
|
|
|
" -C, --cu_inline_expansions_stats show CU inline expansions stats\n"
|
2006-11-03 20:14:25 +01:00
|
|
|
" -t, --total_inline_stats show Multi-CU total inline "
|
|
|
|
"expansions stats\n"
|
2006-11-03 18:38:43 +01:00
|
|
|
" -s, --sizes show size of functions\n"
|
|
|
|
" -N, --function_name_len show size of functions\n"
|
|
|
|
" -p, --nr_parameters show number or parameters\n"
|
[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
|
|
|
" -S, --nr_variables show number of variables\n"
|
|
|
|
" -T, --variables show variables\n"
|
2006-11-03 18:38:43 +01:00
|
|
|
" -V, --verbose be verbose\n");
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
}
|
|
|
|
|
2006-11-13 03:31:48 +01:00
|
|
|
static int class__has_parameter_of_type(const struct class *self,
|
|
|
|
const struct class *target)
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
{
|
|
|
|
struct class_member *pos;
|
|
|
|
|
|
|
|
list_for_each_entry(pos, &self->members, node) {
|
2006-11-12 20:33:37 +01:00
|
|
|
struct class *class = cu__find_class_by_id(self->cu, pos->type);
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
|
|
|
|
if (class != NULL && class->tag == DW_TAG_pointer_type) {
|
2006-11-12 20:33:37 +01:00
|
|
|
class = cu__find_class_by_id(self->cu, class->type);
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
if (class != NULL &&
|
2006-10-31 20:12:42 +01:00
|
|
|
class->id == target->id)
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int class_iterator(struct class *class, void *cookie)
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
if (class__has_parameter_of_type(class, cookie)) {
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
if (verbose)
|
2006-11-12 20:33:37 +01:00
|
|
|
class__print(class);
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
else
|
2006-11-02 17:48:35 +01:00
|
|
|
printf("%s\n", class->name ?: "");
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-10-31 21:23:16 +01:00
|
|
|
static int cu_class_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
struct class *target = cu__find_class_by_name(cu, cookie);
|
|
|
|
|
|
|
|
if (target == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return cu__for_each_class(cu, class_iterator, target);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int sizes_iterator(struct class *class, void *cookie)
|
2006-10-30 19:15:09 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
2006-11-11 19:31:04 +01:00
|
|
|
printf("%s: %u\n", class->name ?: "", class__function_size(class));
|
2006-10-30 19:15:09 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-10-31 21:23:16 +01:00
|
|
|
static int cu_sizes_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, sizes_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-18 02:43:08 +01:00
|
|
|
static int externals_iterator(struct class *class, void *cookie)
|
|
|
|
{
|
|
|
|
if (class->tag == DW_TAG_subprogram && !class->inlined && class->external)
|
|
|
|
puts(class->name);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_externals_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, externals_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int variables_iterator(struct class *class, void *cookie)
|
2006-11-01 14:18:01 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (class->nr_variables > 0)
|
2006-11-02 17:48:35 +01:00
|
|
|
printf("%s: %u\n", class->name ?: "", class->nr_variables);
|
2006-11-01 14:18:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_variables_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, variables_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int goto_labels_iterator(struct class *class, void *cookie)
|
2006-11-01 14:18:01 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (class->nr_labels > 0)
|
2006-11-02 17:48:35 +01:00
|
|
|
printf("%s: %u\n", class->name ?: "", class->nr_labels);
|
2006-11-01 14:18:01 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_goto_labels_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, goto_labels_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int function_iterator(struct class *class, void *cookie)
|
2006-10-31 21:23:16 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
2006-11-03 16:41:19 +01:00
|
|
|
if (cookie == NULL) {
|
|
|
|
if (class->nr_inline_expansions > 0)
|
|
|
|
printf("%s: %u %u\n", class->name ?: "",
|
|
|
|
class->nr_inline_expansions,
|
|
|
|
class->size_inline_expansions);
|
|
|
|
} else if (class->name != NULL && strcmp(class->name, cookie) == 0) {
|
2006-11-12 20:33:37 +01:00
|
|
|
class__print(class);
|
2006-11-03 16:41:19 +01:00
|
|
|
if (show_inline_expansions)
|
2006-11-12 20:33:37 +01:00
|
|
|
class__print_inline_expansions(class);
|
[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
|
|
|
if (show_variables)
|
2006-11-12 20:33:37 +01:00
|
|
|
class__print_variables(class);
|
2006-10-31 21:23:16 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_function_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, function_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int inlines_iterator(struct class *class, void *cookie)
|
[PFUNCT]: Improve --cu_inline_expansions_stats
Now it shows the number that each of the inline functions were expanded in an
object file:
Top 10 inline functions expanded more than once in kernel/sched.o, by total
size of inline expansions:
[acme@newtoy guinea_pig-2.6]$ pfunct --cu_inline_expansions_stats kernel/sched.o | sort -k3 -nr | grep -v ': 1 ' | head -11
kernel/sched.c: 318 10217
get_current: 38 325
finish_task_switch: 2 238
normal_prio: 2 167
__cpus_and: 14 164
find_process_by_pid: 6 152
current_thread_info: 21 149
sched_find_first_bit: 2 148
update_cpu_clock: 2 140
task_rq_unlock: 14 137
variable_test_bit: 14 121
[acme@newtoy guinea_pig-2.6]$
Now we have these options:
[acme@newtoy guinea_pig-2.6]$ pfunct --help
usage: pfunct [options] <file_name> {<function_name>}
where:
-c, --class=<class> functions that have <class> pointer parameters
-g, --goto_labels show number of goto labels
-i, --show_inline_expansions show inline expansions
-C, --cu_inline_expansions_stats show CU inline expansions stats
-s, --sizes show size of functions
-N, --function_name_len show size of functions
-p, --nr_parameters show number or parameters
-S, --variables show number of variables
-V, --verbose be verbose
[acme@newtoy guinea_pig-2.6]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 19:22:12 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || !class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (class->name != NULL)
|
2006-11-11 17:15:50 +01:00
|
|
|
printf("%s: %u %lu\n", class->name,
|
[PFUNCT]: Improve --cu_inline_expansions_stats
Now it shows the number that each of the inline functions were expanded in an
object file:
Top 10 inline functions expanded more than once in kernel/sched.o, by total
size of inline expansions:
[acme@newtoy guinea_pig-2.6]$ pfunct --cu_inline_expansions_stats kernel/sched.o | sort -k3 -nr | grep -v ': 1 ' | head -11
kernel/sched.c: 318 10217
get_current: 38 325
finish_task_switch: 2 238
normal_prio: 2 167
__cpus_and: 14 164
find_process_by_pid: 6 152
current_thread_info: 21 149
sched_find_first_bit: 2 148
update_cpu_clock: 2 140
task_rq_unlock: 14 137
variable_test_bit: 14 121
[acme@newtoy guinea_pig-2.6]$
Now we have these options:
[acme@newtoy guinea_pig-2.6]$ pfunct --help
usage: pfunct [options] <file_name> {<function_name>}
where:
-c, --class=<class> functions that have <class> pointer parameters
-g, --goto_labels show number of goto labels
-i, --show_inline_expansions show inline expansions
-C, --cu_inline_expansions_stats show CU inline expansions stats
-s, --sizes show size of functions
-N, --function_name_len show size of functions
-p, --nr_parameters show number or parameters
-S, --variables show number of variables
-V, --verbose be verbose
[acme@newtoy guinea_pig-2.6]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 19:22:12 +01:00
|
|
|
class->cu_total_nr_inline_expansions,
|
|
|
|
class->cu_total_size_inline_expansions);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-11-03 18:38:43 +01:00
|
|
|
static int cu_inlines_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
cu__account_inline_expansions(cu);
|
[PFUNCT]: Improve --cu_inline_expansions_stats
Now it shows the number that each of the inline functions were expanded in an
object file:
Top 10 inline functions expanded more than once in kernel/sched.o, by total
size of inline expansions:
[acme@newtoy guinea_pig-2.6]$ pfunct --cu_inline_expansions_stats kernel/sched.o | sort -k3 -nr | grep -v ': 1 ' | head -11
kernel/sched.c: 318 10217
get_current: 38 325
finish_task_switch: 2 238
normal_prio: 2 167
__cpus_and: 14 164
find_process_by_pid: 6 152
current_thread_info: 21 149
sched_find_first_bit: 2 148
update_cpu_clock: 2 140
task_rq_unlock: 14 137
variable_test_bit: 14 121
[acme@newtoy guinea_pig-2.6]$
Now we have these options:
[acme@newtoy guinea_pig-2.6]$ pfunct --help
usage: pfunct [options] <file_name> {<function_name>}
where:
-c, --class=<class> functions that have <class> pointer parameters
-g, --goto_labels show number of goto labels
-i, --show_inline_expansions show inline expansions
-C, --cu_inline_expansions_stats show CU inline expansions stats
-s, --sizes show size of functions
-N, --function_name_len show size of functions
-p, --nr_parameters show number or parameters
-S, --variables show number of variables
-V, --verbose be verbose
[acme@newtoy guinea_pig-2.6]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 19:22:12 +01:00
|
|
|
if (cu->nr_inline_expansions > 0) {
|
2006-11-03 18:38:43 +01:00
|
|
|
printf("%s: %lu %lu\n", cu->name, cu->nr_inline_expansions,
|
|
|
|
cu->size_inline_expansions);
|
[PFUNCT]: Improve --cu_inline_expansions_stats
Now it shows the number that each of the inline functions were expanded in an
object file:
Top 10 inline functions expanded more than once in kernel/sched.o, by total
size of inline expansions:
[acme@newtoy guinea_pig-2.6]$ pfunct --cu_inline_expansions_stats kernel/sched.o | sort -k3 -nr | grep -v ': 1 ' | head -11
kernel/sched.c: 318 10217
get_current: 38 325
finish_task_switch: 2 238
normal_prio: 2 167
__cpus_and: 14 164
find_process_by_pid: 6 152
current_thread_info: 21 149
sched_find_first_bit: 2 148
update_cpu_clock: 2 140
task_rq_unlock: 14 137
variable_test_bit: 14 121
[acme@newtoy guinea_pig-2.6]$
Now we have these options:
[acme@newtoy guinea_pig-2.6]$ pfunct --help
usage: pfunct [options] <file_name> {<function_name>}
where:
-c, --class=<class> functions that have <class> pointer parameters
-g, --goto_labels show number of goto labels
-i, --show_inline_expansions show inline expansions
-C, --cu_inline_expansions_stats show CU inline expansions stats
-s, --sizes show size of functions
-N, --function_name_len show size of functions
-p, --nr_parameters show number or parameters
-S, --variables show number of variables
-V, --verbose be verbose
[acme@newtoy guinea_pig-2.6]$
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-11-03 19:22:12 +01:00
|
|
|
cu__for_each_class(cu, inlines_iterator, cookie);
|
|
|
|
}
|
2006-11-03 18:38:43 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int nr_parameters_iterator(struct class *class, void *cookie)
|
2006-11-01 14:34:42 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (class->nr_members > 0)
|
2006-11-02 17:48:35 +01:00
|
|
|
printf("%s: %u\n", class->name ?: "", class->nr_members);
|
2006-11-01 14:34:42 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_nr_parameters_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, nr_parameters_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int function_name_len_iterator(struct class *class, void *cookie)
|
2006-11-01 14:42:18 +01:00
|
|
|
{
|
|
|
|
if (class->tag != DW_TAG_subprogram || class->inlined)
|
|
|
|
return 0;
|
|
|
|
|
2006-11-02 17:48:35 +01:00
|
|
|
if (class->name != NULL)
|
|
|
|
printf("%s: %u\n", class->name, strlen(class->name));
|
2006-11-01 14:42:18 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_function_name_len_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
return cu__for_each_class(cu, function_name_len_iterator, cookie);
|
|
|
|
}
|
|
|
|
|
2006-11-12 20:33:37 +01:00
|
|
|
static int total_inlines_iterator(struct class *class, void *cookie)
|
2006-11-03 20:14:25 +01:00
|
|
|
{
|
|
|
|
if (class->tag == DW_TAG_subprogram && class->inlined)
|
|
|
|
inlines__add(class);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int cu_total_inlines_iterator(struct cu *cu, void *cookie)
|
|
|
|
{
|
|
|
|
cu__account_inline_expansions(cu);
|
|
|
|
if (cu->nr_inline_expansions > 0)
|
|
|
|
cu__for_each_class(cu, total_inlines_iterator, cookie);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2006-10-29 00:07:45 +02:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
int option, option_index;
|
2006-11-11 17:15:50 +01:00
|
|
|
const char *file_name;
|
2006-11-11 19:31:04 +01:00
|
|
|
struct cus *cus;
|
2006-10-31 21:23:16 +01:00
|
|
|
char *class_name = NULL;
|
|
|
|
char *function_name = NULL;
|
2006-11-18 02:43:08 +01:00
|
|
|
int show_externals = 0;
|
2006-10-30 19:15:09 +01:00
|
|
|
int show_sizes = 0;
|
[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
|
|
|
int show_nr_variables = 0;
|
2006-11-01 14:18:01 +01:00
|
|
|
int show_goto_labels = 0;
|
2006-11-01 14:34:42 +01:00
|
|
|
int show_nr_parameters = 0;
|
2006-11-01 14:42:18 +01:00
|
|
|
int show_function_name_len = 0;
|
2006-11-03 16:41:19 +01:00
|
|
|
int show_inline_expansions_stats = 0;
|
2006-11-03 18:38:43 +01:00
|
|
|
int show_inline_stats = 0;
|
2006-11-04 04:11:04 +01:00
|
|
|
int show_total_inline_expansion_stats = 0;
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
|
2006-11-18 02:43:08 +01:00
|
|
|
while ((option = getopt_long(argc, argv, "c:CegiINpsStTV",
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
long_options, &option_index)) >= 0)
|
|
|
|
switch (option) {
|
2006-11-03 16:41:19 +01:00
|
|
|
case 'c': class_name = optarg; break;
|
2006-11-03 18:38:43 +01:00
|
|
|
case 'C': show_inline_stats = 1; break;
|
2006-11-18 02:43:08 +01:00
|
|
|
case 'e': show_externals = 1; break;
|
2006-11-03 16:41:19 +01:00
|
|
|
case 's': show_sizes = 1; break;
|
[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
|
|
|
case 'S': show_nr_variables = 1; break;
|
2006-11-03 16:41:19 +01:00
|
|
|
case 'p': show_nr_parameters = 1; break;
|
|
|
|
case 'g': show_goto_labels = 1; break;
|
|
|
|
case 'i': show_inline_expansions = 1; break;
|
|
|
|
case 'I': show_inline_expansions_stats = 1; break;
|
2006-11-03 20:14:25 +01:00
|
|
|
case 't': show_total_inline_expansion_stats = 1;break;
|
[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
|
|
|
case 'T': show_variables = 1; break;
|
2006-11-03 16:41:19 +01:00
|
|
|
case 'N': show_function_name_len = 1; break;
|
|
|
|
case 'V': verbose = 1; break;
|
|
|
|
case 'h': usage(); return EXIT_SUCCESS;
|
|
|
|
default: usage(); return EXIT_FAILURE;
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (optind < argc) {
|
|
|
|
switch (argc - optind) {
|
|
|
|
case 1: file_name = argv[optind++]; break;
|
|
|
|
case 2: file_name = argv[optind++];
|
|
|
|
function_name = argv[optind++]; break;
|
|
|
|
default: usage(); return EXIT_FAILURE;
|
|
|
|
}
|
2006-11-11 17:15:50 +01:00
|
|
|
} else {
|
|
|
|
usage();
|
|
|
|
return EXIT_FAILURE;
|
2006-10-29 00:07:45 +02:00
|
|
|
}
|
|
|
|
|
2006-11-11 19:31:04 +01:00
|
|
|
cus = cus__new(file_name);
|
|
|
|
if (cus == NULL) {
|
|
|
|
fputs("pfunct: insufficient memory\n", stderr);
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cus__load(cus) != 0) {
|
2006-10-29 00:07:45 +02:00
|
|
|
fprintf(stderr, "pfunct: couldn't load DWARF info from %s\n",
|
Add getopt support in pfunct, options implemented should be self explaining,
except for --classes, that asks that all non-inlined functions that receive as
one of its parameter a pointer to the specified class be printed, just the name
if --verbose is not used, or its complete prototype and where it is in the
source code:
[acme@newtoy net-2.6]$ pfunct --verbose --class=inode fs/ext3/built-in.o
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 606 */
void ext3_free_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t block, long unsigned int count);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1404 */
ext3_fsblk_t ext3_new_blocks(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, long unsigned int * count, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 1668 */
ext3_fsblk_t ext3_new_block(handle_t * handle, struct inode * inode, ext3_fsblk_t goal, int * errp);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 346 */
void ext3_init_block_alloc_info(struct inode * inode);
/* /pub/scm/linux/kernel/git/acme/net-2.6/fs/ext3/balloc.c 388 */
void ext3_discard_reservation(struct inode * inode);
Signed-off-by: Arnaldo Carvalho de Melo <acme@mandriva.com>
2006-10-29 04:41:48 +01:00
|
|
|
file_name);
|
2006-10-29 00:07:45 +02:00
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
2006-11-03 20:14:25 +01:00
|
|
|
if (show_total_inline_expansion_stats) {
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_total_inlines_iterator, NULL);
|
2006-11-03 20:14:25 +01:00
|
|
|
print_total_inline_stats();
|
|
|
|
} else if (show_inline_stats)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_inlines_iterator, NULL);
|
2006-11-03 18:38:43 +01:00
|
|
|
else if (show_nr_parameters)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_nr_parameters_iterator, NULL);
|
[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
|
|
|
else if (show_nr_variables)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_variables_iterator, NULL);
|
2006-11-01 14:18:01 +01:00
|
|
|
else if (show_goto_labels)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_goto_labels_iterator, NULL);
|
2006-11-01 14:18:01 +01:00
|
|
|
else if (show_sizes)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_sizes_iterator, NULL);
|
2006-11-18 02:43:08 +01:00
|
|
|
else if (show_externals)
|
|
|
|
cus__for_each_cu(cus, cu_externals_iterator, NULL);
|
2006-11-01 22:08:54 +01:00
|
|
|
else if (show_function_name_len)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_function_name_len_iterator, NULL);
|
2006-10-31 21:23:16 +01:00
|
|
|
else if (class_name != NULL)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_class_iterator, class_name);
|
2006-11-03 16:41:19 +01:00
|
|
|
else if (function_name == NULL && !show_inline_expansions_stats)
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__print_classes(cus, DW_TAG_subprogram);
|
2006-10-31 21:23:16 +01:00
|
|
|
else
|
2006-11-11 19:31:04 +01:00
|
|
|
cus__for_each_cu(cus, cu_function_iterator, function_name);
|
2006-10-29 00:07:45 +02:00
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|