mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
*** empty log message ***
This commit is contained in:
2
Makefile
2
Makefile
@ -7,7 +7,7 @@ else
|
|||||||
|
|
||||||
CFLAGS := $(shell pkg-config --cflags gtk+-2.0 libglade-2.0) -Wall -g
|
CFLAGS := $(shell pkg-config --cflags gtk+-2.0 libglade-2.0) -Wall -g
|
||||||
LIBS := $(shell pkg-config --libs gtk+-2.0 libglade-2.0) -lbfd -liberty
|
LIBS := $(shell pkg-config --libs gtk+-2.0 libglade-2.0) -lbfd -liberty
|
||||||
C_FILES := sysprof.c binfile.c stackstash.c watch.c process.c profile.c treeviewutils.c
|
C_FILES := sysprof.c binfile.c stackstash.c watch.c process.c profile.c treeviewutils.c sfile.c
|
||||||
OBJS := $(addsuffix .o, $(basename $(C_FILES)))
|
OBJS := $(addsuffix .o, $(basename $(C_FILES)))
|
||||||
BINARY := sysprof
|
BINARY := sysprof
|
||||||
MODULE := sysprof-module
|
MODULE := sysprof-module
|
||||||
|
|||||||
7
TODO
7
TODO
@ -1,14 +1,15 @@
|
|||||||
- consider caching [filename => bin_file]
|
- consider caching [filename => bin_file]
|
||||||
- Have kernel modulereport the file the symbol was found in
|
- Have kernel modulereport the file the symbol was found in
|
||||||
Should avoid a lot of potential brokenness with dlopen etc.
|
Should avoid a lot of potential broken/raciness with dlopen etc.
|
||||||
- grep FIXME
|
- grep FIXME
|
||||||
- hide internal stuff in ProfileDescendant
|
- hide internal stuff in ProfileDescendant
|
||||||
|
|
||||||
- loading and saving
|
- loading and saving
|
||||||
|
|
||||||
- Non-GUI version that can save in a format the GUI can understand.
|
- Non-GUI version that can save in a format the GUI can understand.
|
||||||
Could be used for profiling startup etc. Should be able to dump the
|
Could be used for profiling startup etc. Would preferably be able to
|
||||||
data to a network socket.
|
dump the data to a network socket. Should be able to react to eg.
|
||||||
|
SIGUSR1 by dumping the data.
|
||||||
|
|
||||||
- Port to GtkAction
|
- Port to GtkAction
|
||||||
|
|
||||||
|
|||||||
@ -190,6 +190,7 @@ get_number (const char *input_name,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
static Node *
|
static Node *
|
||||||
create_node (const char **names,
|
create_node (const char **names,
|
||||||
const char **values,
|
const char **values,
|
||||||
@ -345,6 +346,7 @@ profile_load (const char *filename,
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
profile_object_free (ProfileObject *obj)
|
profile_object_free (ProfileObject *obj)
|
||||||
|
|||||||
239
sfile.c
239
sfile.c
@ -72,6 +72,40 @@ struct Fragment
|
|||||||
|
|
||||||
struct Action
|
struct Action
|
||||||
{
|
{
|
||||||
|
TransitionType type;
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
} begin_record;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int n_items;
|
||||||
|
} begin_list;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int id;
|
||||||
|
} end;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
gpointer *location;
|
||||||
|
} pointer;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
int value;
|
||||||
|
} integer;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char *value;
|
||||||
|
} string;
|
||||||
|
} u;
|
||||||
};
|
};
|
||||||
|
|
||||||
static State *
|
static State *
|
||||||
@ -426,9 +460,9 @@ typedef struct ParseNode ParseNode;
|
|||||||
|
|
||||||
struct BuildContext
|
struct BuildContext
|
||||||
{
|
{
|
||||||
ParseNode *root;
|
State *state;
|
||||||
ParseNode *current_node;
|
Action *actions;
|
||||||
GHashTable *nodes_by_id;
|
int n_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ParseNode
|
struct ParseNode
|
||||||
@ -442,42 +476,6 @@ struct ParseNode
|
|||||||
SFormat *format;
|
SFormat *format;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
|
||||||
sfile_begin_get_record (SFileInput *file)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
sfile_begin_get_list (SFileInput *file)
|
|
||||||
{
|
|
||||||
return -1; /* FIXME */
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sfile_get_pointer (SFileInput *file,
|
|
||||||
gpointer *pointer)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sfile_get_integer (SFileInput *file,
|
|
||||||
int *integer)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sfile_get_string (SFileInput *file,
|
|
||||||
char **string)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
sfile_end_get (SFileInput *file,
|
|
||||||
gpointer object)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
get_number (const char *text, int *number)
|
get_number (const char *text, int *number)
|
||||||
{
|
{
|
||||||
@ -498,6 +496,98 @@ get_number (const char *text, int *number)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SFileInput
|
||||||
|
{
|
||||||
|
int n_actions;
|
||||||
|
Action *actions;
|
||||||
|
Action *current_action;
|
||||||
|
GHashTable *actions_by_location;
|
||||||
|
GHashTable *objects_by_id;
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
sfile_begin_get_record (SFileInput *file, const char *name)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
|
||||||
|
g_return_if_fail (action->type == BEGIN_RECORD &&
|
||||||
|
strcmp (action->name, name) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
sfile_begin_get_list (SFileInput *file,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
|
||||||
|
g_return_val_if_fail (action->type == BEGIN_LIST &&
|
||||||
|
strcmp (action->name, name) == 0, 0);
|
||||||
|
|
||||||
|
return action->u.begin_list.n_items;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sfile_get_pointer (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
|
gpointer *location)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
g_return_if_fail (action->type == POINTER &&
|
||||||
|
strcmp (action->name, name) == 0);
|
||||||
|
|
||||||
|
action->u.pointer.location = location;
|
||||||
|
|
||||||
|
if (location)
|
||||||
|
{
|
||||||
|
if (g_hash_table_lookup (file->actions_by_location, location))
|
||||||
|
g_warning ("Reading into the same location twice\n");
|
||||||
|
|
||||||
|
g_hash_table_insert (file->actions_by_location, location, action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sfile_get_integer (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
|
int *integer)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
g_return_if_fail (action->type == INTEGER &&
|
||||||
|
strcmp (action->name, name) == 0);
|
||||||
|
|
||||||
|
if (integer)
|
||||||
|
*integer = action->u.integer.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sfile_get_string (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
|
char **string)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
g_return_if_fail (action->type == STRING &&
|
||||||
|
strcmp (action->name, name) == 0);
|
||||||
|
|
||||||
|
if (string)
|
||||||
|
*string = g_strdup (action->u.string.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sfile_end_get (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
|
gpointer object)
|
||||||
|
{
|
||||||
|
Action *action = file->current_action++;
|
||||||
|
|
||||||
|
g_return_if_fail ((action->type == END_LIST ||
|
||||||
|
action->type == END_RECORD) &&
|
||||||
|
strcmp (action->name, name) == 0);
|
||||||
|
|
||||||
|
if (action->u.end.id)
|
||||||
|
g_hash_table_insert (file->objects_by_id,
|
||||||
|
GINT_TO_POINTER (action->u.end.id), object);
|
||||||
|
}
|
||||||
|
|
||||||
static ParseNode *
|
static ParseNode *
|
||||||
parse_node_new (ParseNode *parent,
|
parse_node_new (ParseNode *parent,
|
||||||
const char *name)
|
const char *name)
|
||||||
@ -526,7 +616,7 @@ handle_begin_element (GMarkupParseContext *parse_context,
|
|||||||
{
|
{
|
||||||
BuildContext *build = user_data;
|
BuildContext *build = user_data;
|
||||||
const char *id_string;
|
const char *id_string;
|
||||||
ParseNode *node;
|
Action action;
|
||||||
int id;
|
int id;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -559,24 +649,10 @@ handle_begin_element (GMarkupParseContext *parse_context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (build->current_node->text->len > 0)
|
/* */
|
||||||
{
|
|
||||||
/* FIXME: mixing children and text */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
node = parse_node_new (build->current_node, element_name);
|
|
||||||
|
|
||||||
if (id_string)
|
if (!state_transition_begin (build->state, element_name, &action.type, err)) {
|
||||||
{
|
};
|
||||||
node->id = GINT_TO_POINTER (id);
|
|
||||||
g_hash_table_insert (build->nodes_by_id, node->id, node);
|
|
||||||
}
|
|
||||||
|
|
||||||
build->current_node = node;
|
|
||||||
|
|
||||||
if (!build->root)
|
|
||||||
build->root = node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -586,8 +662,6 @@ handle_end_element (GMarkupParseContext *context,
|
|||||||
GError **err)
|
GError **err)
|
||||||
{
|
{
|
||||||
BuildContext *build = user_data;
|
BuildContext *build = user_data;
|
||||||
|
|
||||||
build->current_node = build->current_node->parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -598,20 +672,10 @@ handle_text (GMarkupParseContext *context,
|
|||||||
GError **err)
|
GError **err)
|
||||||
{
|
{
|
||||||
BuildContext *build = user_data;
|
BuildContext *build = user_data;
|
||||||
|
|
||||||
if (build->current_node->children->len > 0)
|
|
||||||
{
|
|
||||||
/* FIXME: set error: mixing children and text */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_append (build->current_node->text, text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ParseNode *
|
static Action *
|
||||||
build_tree (const char *text,
|
build_actions (const char *contents, int *n_actions, GError **err)
|
||||||
GHashTable *nodes_by_id,
|
|
||||||
GError **err)
|
|
||||||
{
|
{
|
||||||
BuildContext build;
|
BuildContext build;
|
||||||
GMarkupParseContext *parse_context;
|
GMarkupParseContext *parse_context;
|
||||||
@ -624,41 +688,15 @@ build_tree (const char *text,
|
|||||||
NULL, /* error */
|
NULL, /* error */
|
||||||
};
|
};
|
||||||
|
|
||||||
build.root = NULL;
|
|
||||||
build.current_node = NULL;
|
|
||||||
build.nodes_by_id = nodes_by_id;
|
|
||||||
|
|
||||||
parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL);
|
parse_context = g_markup_parse_context_new (&parser, 0, &build, NULL);
|
||||||
|
|
||||||
if (!g_markup_parse_context_parse (parse_context, text, -1, err))
|
if (!g_markup_parse_context_parse (parse_context, contents, -1, err))
|
||||||
{
|
{
|
||||||
/* FIXME: free stuff */
|
/* FIXME: free stuff */
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!build.root)
|
return build.actions;
|
||||||
{
|
|
||||||
/* FIXME: empty document not allowed */
|
|
||||||
/* FIXME: free stuff */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return build.root;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean check_structure (ParseNode *node, SFormat *format, GHashTable *nodes_by_id, GError **err);
|
|
||||||
|
|
||||||
|
|
||||||
struct SFileInput
|
|
||||||
{
|
|
||||||
int n_actions;
|
|
||||||
Action *actions;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Action *
|
|
||||||
build_actions (const char *contents, int *n_actions, GError **err)
|
|
||||||
{
|
|
||||||
return NULL; /* FIXME */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SFileInput *
|
SFileInput *
|
||||||
@ -668,9 +706,6 @@ sfile_load (const char *filename,
|
|||||||
{
|
{
|
||||||
gchar *contents;
|
gchar *contents;
|
||||||
gsize length;
|
gsize length;
|
||||||
ParseNode *tree;
|
|
||||||
GHashTable *nodes_by_id;
|
|
||||||
GArray *read_list;
|
|
||||||
SFileInput *input;
|
SFileInput *input;
|
||||||
|
|
||||||
if (!g_file_get_contents (filename, &contents, &length, err))
|
if (!g_file_get_contents (filename, &contents, &length, err))
|
||||||
|
|||||||
8
sfile.h
8
sfile.h
@ -17,15 +17,19 @@ gpointer sformat_new_string (const char *name);
|
|||||||
SFileInput * sfile_load (const char *filename,
|
SFileInput * sfile_load (const char *filename,
|
||||||
SFormat *format,
|
SFormat *format,
|
||||||
GError **err);
|
GError **err);
|
||||||
void sfile_begin_get_record (SFileInput *file);
|
void sfile_begin_get_record (SFileInput *file, const char *name);
|
||||||
int sfile_begin_get_list (SFileInput *file);
|
int sfile_begin_get_list (SFileInput *file, const char *name);
|
||||||
void sfile_get_pointer (SFileInput *file,
|
void sfile_get_pointer (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
gpointer *pointer);
|
gpointer *pointer);
|
||||||
void sfile_get_integer (SFileInput *file,
|
void sfile_get_integer (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
int *integer);
|
int *integer);
|
||||||
void sfile_get_string (SFileInput *file,
|
void sfile_get_string (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
char **string);
|
char **string);
|
||||||
void sfile_end_get (SFileInput *file,
|
void sfile_end_get (SFileInput *file,
|
||||||
|
const char *name,
|
||||||
gpointer object);
|
gpointer object);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|||||||
@ -78,13 +78,16 @@ init_userspace_reader (userspace_reader *reader,
|
|||||||
reader->page = NULL;
|
reader->page = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is mostly cutted and pasted from ptrace.c
|
||||||
|
* I removed some locking and other stuff though. I hope it
|
||||||
|
* wasn't important.
|
||||||
|
*/
|
||||||
|
|
||||||
/* Access another process' address space.
|
/* Access another process' address space.
|
||||||
* Source/target buffer must be kernel space,
|
* Source/target buffer must be kernel space,
|
||||||
* Do not walk the page table directly, use get_user_pages
|
* Do not walk the page table directly, use get_user_pages
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
|
static int x_access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
|
||||||
{
|
{
|
||||||
struct mm_struct *mm;
|
struct mm_struct *mm;
|
||||||
@ -244,6 +247,7 @@ generate_stack_trace(struct task_struct *task,
|
|||||||
init_userspace_reader (&reader, task);
|
init_userspace_reader (&reader, task);
|
||||||
while (i < SYSPROF_MAX_ADDRESSES && read_frame (&reader, addr, &frame) &&
|
while (i < SYSPROF_MAX_ADDRESSES && read_frame (&reader, addr, &frame) &&
|
||||||
addr < START_OF_STACK && addr >= regs->esp) {
|
addr < START_OF_STACK && addr >= regs->esp) {
|
||||||
|
|
||||||
trace->addresses[i++] = (void *)frame.return_address;
|
trace->addresses[i++] = (void *)frame.return_address;
|
||||||
addr = frame.next;
|
addr = frame.next;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user