Also filter out NMI stack

This commit is contained in:
Søren Sandmann Pedersen
2009-10-29 07:40:51 -04:00
parent ae77f078d3
commit 1b64f1d924

253
tracker.c
View File

@ -19,7 +19,7 @@ typedef struct exit_t exit_t;
struct tracker_t struct tracker_t
{ {
StackStash *stash; StackStash *stash;
size_t n_event_bytes; size_t n_event_bytes;
size_t n_allocated_bytes; size_t n_allocated_bytes;
uint8_t * events; uint8_t * events;
@ -87,16 +87,16 @@ get_lines (const char *format, pid_t pid)
char *filename = g_strdup_printf (format, pid); char *filename = g_strdup_printf (format, pid);
char **result = NULL; char **result = NULL;
char *contents; char *contents;
if (g_file_get_contents (filename, &contents, NULL, NULL)) if (g_file_get_contents (filename, &contents, NULL, NULL))
{ {
result = g_strsplit (contents, "\n", -1); result = g_strsplit (contents, "\n", -1);
g_free (contents); g_free (contents);
} }
g_free (filename); g_free (filename);
return result; return result;
} }
@ -105,7 +105,7 @@ fake_new_process (tracker_t *tracker, pid_t pid)
{ {
char **lines; char **lines;
gboolean done = FALSE; gboolean done = FALSE;
if ((lines = get_lines ("/proc/%d/cmdline", pid))) if ((lines = get_lines ("/proc/%d/cmdline", pid)))
{ {
if (lines[0] && strlen (lines[0]) > 0) if (lines[0] && strlen (lines[0]) > 0)
@ -121,7 +121,7 @@ fake_new_process (tracker_t *tracker, pid_t pid)
if (!done && (lines = get_lines ("/proc/%d/status", pid))) if (!done && (lines = get_lines ("/proc/%d/status", pid)))
{ {
int i; int i;
for (i = 0; lines[i] != NULL; ++i) for (i = 0; lines[i] != NULL; ++i)
{ {
if (strncmp ("Name:", lines[i], 5) == 0) if (strncmp ("Name:", lines[i], 5) == 0)
@ -148,11 +148,11 @@ static void
fake_new_map (tracker_t *tracker, pid_t pid) fake_new_map (tracker_t *tracker, pid_t pid)
{ {
char **lines; char **lines;
if ((lines = get_lines ("/proc/%d/maps", pid))) if ((lines = get_lines ("/proc/%d/maps", pid)))
{ {
int i; int i;
for (i = 0; lines[i] != NULL; ++i) for (i = 0; lines[i] != NULL; ++i)
{ {
char file[256]; char file[256];
@ -161,13 +161,13 @@ fake_new_map (tracker_t *tracker, pid_t pid)
gulong offset; gulong offset;
gulong inode; gulong inode;
int count; int count;
file[255] = '\0'; file[255] = '\0';
count = sscanf ( count = sscanf (
lines[i], "%lx-%lx %*15s %lx %*x:%*x %lu %255s", lines[i], "%lx-%lx %*15s %lx %*x:%*x %lu %255s",
&start, &end, &offset, &inode, file); &start, &end, &offset, &inode, file);
if (count == 5) if (count == 5)
{ {
if (strcmp (file, "[vdso]") == 0) if (strcmp (file, "[vdso]") == 0)
@ -181,11 +181,11 @@ fake_new_map (tracker_t *tracker, pid_t pid)
offset = 0; offset = 0;
inode = 0; inode = 0;
} }
tracker_add_map (tracker, pid, start, end, offset, inode, file); tracker_add_map (tracker, pid, start, end, offset, inode, file);
} }
} }
g_strfreev (lines); g_strfreev (lines);
} }
} }
@ -195,24 +195,24 @@ populate_from_proc (tracker_t *tracker)
{ {
GDir *proc = g_dir_open ("/proc", 0, NULL); GDir *proc = g_dir_open ("/proc", 0, NULL);
const char *name; const char *name;
if (!proc) if (!proc)
return; return;
while ((name = g_dir_read_name (proc))) while ((name = g_dir_read_name (proc)))
{ {
pid_t pid; pid_t pid;
char *end; char *end;
pid = strtol (name, &end, 10); pid = strtol (name, &end, 10);
if (*end == 0) if (*end == 0)
{ {
fake_new_process (tracker, pid); fake_new_process (tracker, pid);
fake_new_map (tracker, pid); fake_new_map (tracker, pid);
} }
} }
g_dir_close (proc); g_dir_close (proc);
} }
@ -229,7 +229,7 @@ time_diff (const GTimeVal *first,
{ {
double first_ms = timeval_to_ms (first); double first_ms = timeval_to_ms (first);
double second_ms = timeval_to_ms (second); double second_ms = timeval_to_ms (second);
return first_ms - second_ms; return first_ms - second_ms;
} }
@ -238,21 +238,21 @@ tracker_new (void)
{ {
tracker_t *tracker = g_new0 (tracker_t, 1); tracker_t *tracker = g_new0 (tracker_t, 1);
GTimeVal before, after; GTimeVal before, after;
tracker->n_event_bytes = 0; tracker->n_event_bytes = 0;
tracker->n_allocated_bytes = DEFAULT_SIZE; tracker->n_allocated_bytes = DEFAULT_SIZE;
tracker->events = g_malloc (DEFAULT_SIZE); tracker->events = g_malloc (DEFAULT_SIZE);
tracker->stash = stack_stash_new (NULL); tracker->stash = stack_stash_new (NULL);
g_get_current_time (&before); g_get_current_time (&before);
populate_from_proc (tracker); populate_from_proc (tracker);
g_get_current_time (&after); g_get_current_time (&after);
g_print ("Time to populate %f\n", time_diff (&after, &before)); g_print ("Time to populate %f\n", time_diff (&after, &before));
return tracker; return tracker;
} }
@ -281,14 +281,14 @@ tracker_append (tracker_t *tracker,
if (tracker->n_allocated_bytes - tracker->n_event_bytes < n_bytes) if (tracker->n_allocated_bytes - tracker->n_event_bytes < n_bytes)
{ {
size_t new_size = tracker->n_allocated_bytes * 2; size_t new_size = tracker->n_allocated_bytes * 2;
tracker->events = g_realloc (tracker->events, new_size); tracker->events = g_realloc (tracker->events, new_size);
tracker->n_allocated_bytes = new_size; tracker->n_allocated_bytes = new_size;
} }
g_assert (tracker->n_allocated_bytes - tracker->n_event_bytes >= n_bytes); g_assert (tracker->n_allocated_bytes - tracker->n_event_bytes >= n_bytes);
memcpy (tracker->events + tracker->n_event_bytes, event, n_bytes); memcpy (tracker->events + tracker->n_event_bytes, event, n_bytes);
tracker->n_event_bytes += n_bytes; tracker->n_event_bytes += n_bytes;
@ -303,7 +303,7 @@ tracker_add_process (tracker_t * tracker,
event.header = MAKE_HEADER (NEW_PROCESS, pid); event.header = MAKE_HEADER (NEW_PROCESS, pid);
COPY_STRING (event.command_line, command_line); COPY_STRING (event.command_line, command_line);
tracker_append (tracker, &event, sizeof (event)); tracker_append (tracker, &event, sizeof (event));
} }
@ -341,14 +341,14 @@ tracker_add_map (tracker_t * tracker,
const char *filename) const char *filename)
{ {
new_map_t event; new_map_t event;
event.header = MAKE_HEADER (NEW_MAP, pid); event.header = MAKE_HEADER (NEW_MAP, pid);
COPY_STRING (event.filename, filename); COPY_STRING (event.filename, filename);
event.start = start; event.start = start;
event.end = end; event.end = end;
event.offset = offset; event.offset = offset;
event.inode = inode; event.inode = inode;
tracker_append (tracker, &event, sizeof (event)); tracker_append (tracker, &event, sizeof (event));
} }
@ -359,10 +359,10 @@ tracker_add_sample (tracker_t *tracker,
int n_ips) int n_ips)
{ {
sample_t event; sample_t event;
event.header = MAKE_HEADER (SAMPLE, pid); event.header = MAKE_HEADER (SAMPLE, pid);
event.trace = stack_stash_add_trace (tracker->stash, ips, n_ips, 1); event.trace = stack_stash_add_trace (tracker->stash, ips, n_ips, 1);
tracker_append (tracker, &event, sizeof (event)); tracker_append (tracker, &event, sizeof (event));
} }
@ -374,9 +374,9 @@ typedef struct map_t map_t;
struct process_t struct process_t
{ {
pid_t pid; pid_t pid;
char * comm; char * comm;
GPtrArray * maps; GPtrArray * maps;
}; };
@ -411,33 +411,33 @@ create_map (state_t *state, new_map_t *new_map)
map_t *map; map_t *map;
int i; int i;
pid_t pid = GET_PID (new_map->header); pid_t pid = GET_PID (new_map->header);
process = g_hash_table_lookup ( process = g_hash_table_lookup (
state->processes_by_pid, GINT_TO_POINTER (pid)); state->processes_by_pid, GINT_TO_POINTER (pid));
if (!process) if (!process)
return; return;
map = g_new0 (map_t, 1); map = g_new0 (map_t, 1);
map->filename = g_strdup (new_map->filename); map->filename = g_strdup (new_map->filename);
map->start = new_map->start; map->start = new_map->start;
map->end = new_map->end; map->end = new_map->end;
map->offset = new_map->offset; map->offset = new_map->offset;
map->inode = new_map->inode; map->inode = new_map->inode;
/* Remove existing maps that overlap the new one */ /* Remove existing maps that overlap the new one */
for (i = 0; i < process->maps->len; ++i) for (i = 0; i < process->maps->len; ++i)
{ {
map_t *m = process->maps->pdata[i]; map_t *m = process->maps->pdata[i];
if (m->start < map->end && m->end > map->start) if (m->start < map->end && m->end > map->start)
{ {
destroy_map (m); destroy_map (m);
g_ptr_array_remove_index (process->maps, i); g_ptr_array_remove_index (process->maps, i);
} }
} }
g_ptr_array_add (process->maps, map); g_ptr_array_add (process->maps, map);
} }
@ -445,16 +445,16 @@ static void
destroy_process (process_t *process) destroy_process (process_t *process)
{ {
int i; int i;
g_free (process->comm); g_free (process->comm);
for (i = 0; i < process->maps->len; ++i) for (i = 0; i < process->maps->len; ++i)
{ {
map_t *map = process->maps->pdata[i]; map_t *map = process->maps->pdata[i];
destroy_map (map); destroy_map (map);
} }
g_ptr_array_free (process->maps, TRUE); g_ptr_array_free (process->maps, TRUE);
g_free (process); g_free (process);
} }
@ -463,7 +463,7 @@ static void
create_process (state_t *state, new_process_t *new_process) create_process (state_t *state, new_process_t *new_process)
{ {
process_t *process = g_new0 (process_t, 1); process_t *process = g_new0 (process_t, 1);
process->pid = GET_PID (new_process->header); process->pid = GET_PID (new_process->header);
process->comm = g_strdup (new_process->command_line); process->comm = g_strdup (new_process->command_line);
process->maps = g_ptr_array_new (); process->maps = g_ptr_array_new ();
@ -471,7 +471,7 @@ create_process (state_t *state, new_process_t *new_process)
#if 0 #if 0
g_print ("new comm process %d\n", new_process->pid); g_print ("new comm process %d\n", new_process->pid);
#endif #endif
g_hash_table_insert ( g_hash_table_insert (
state->processes_by_pid, GINT_TO_POINTER (process->pid), process); state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
} }
@ -503,21 +503,21 @@ process_fork (state_t *state, fork_t *fork)
#if 0 #if 0
g_print ("new child %d\n", fork->child_pid); g_print ("new child %d\n", fork->child_pid);
#endif #endif
process->pid = fork->child_pid; process->pid = fork->child_pid;
process->comm = g_strdup (parent? parent->comm : "<unknown>"); process->comm = g_strdup (parent? parent->comm : "<unknown>");
process->maps = g_ptr_array_new (); process->maps = g_ptr_array_new ();
if (parent) if (parent)
{ {
for (i = 0; i < parent->maps->len; ++i) for (i = 0; i < parent->maps->len; ++i)
{ {
map_t *map = copy_map (parent->maps->pdata[i]); map_t *map = copy_map (parent->maps->pdata[i]);
g_ptr_array_add (process->maps, map); g_ptr_array_add (process->maps, map);
} }
} }
g_hash_table_insert ( g_hash_table_insert (
state->processes_by_pid, GINT_TO_POINTER (process->pid), process); state->processes_by_pid, GINT_TO_POINTER (process->pid), process);
} }
@ -533,7 +533,7 @@ process_exit (state_t *state, exit_t *exit)
#if 0 #if 0
g_print ("Exit for %d\n", exit->pid); g_print ("Exit for %d\n", exit->pid);
#endif #endif
/* ignore for now */ /* ignore for now */
} }
@ -541,7 +541,7 @@ static void
free_process (gpointer data) free_process (gpointer data)
{ {
process_t *process = data; process_t *process = data;
destroy_process (process); destroy_process (process);
} }
@ -549,19 +549,19 @@ static state_t *
state_new (void) state_new (void)
{ {
state_t *state = g_new0 (state_t, 1); state_t *state = g_new0 (state_t, 1);
state->processes_by_pid = state->processes_by_pid =
g_hash_table_new_full (g_direct_hash, g_direct_equal, g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, free_process); NULL, free_process);
state->unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal); state->unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal);
state->unique_comms = g_hash_table_new (g_str_hash, g_str_equal); state->unique_comms = g_hash_table_new (g_str_hash, g_str_equal);
state->bin_files = g_hash_table_new_full (g_str_hash, g_str_equal, state->bin_files = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free,
(GDestroyNotify)bin_file_free); (GDestroyNotify)bin_file_free);
return state; return state;
} }
static void static void
state_free (state_t *state) state_free (state_t *state)
@ -570,7 +570,7 @@ state_free (state_t *state)
g_hash_table_destroy (state->unique_symbols); g_hash_table_destroy (state->unique_symbols);
g_hash_table_destroy (state->unique_comms); g_hash_table_destroy (state->unique_comms);
g_hash_table_destroy (state->bin_files); g_hash_table_destroy (state->bin_files);
g_free (state); g_free (state);
} }
@ -584,27 +584,27 @@ static void
parse_kallsym_line (const char *line, GArray *table) parse_kallsym_line (const char *line, GArray *table)
{ {
char **tokens = g_strsplit_set (line, " \t", -1); char **tokens = g_strsplit_set (line, " \t", -1);
if (tokens[0] && tokens[1] && tokens[2]) if (tokens[0] && tokens[1] && tokens[2])
{ {
glong address; glong address;
char *endptr; char *endptr;
address = strtoul (tokens[0], &endptr, 16); address = strtoul (tokens[0], &endptr, 16);
if (*endptr == '\0' && if (*endptr == '\0' &&
(strcmp (tokens[1], "T") == 0 || (strcmp (tokens[1], "T") == 0 ||
strcmp (tokens[1], "t") == 0)) strcmp (tokens[1], "t") == 0))
{ {
kernel_symbol_t sym; kernel_symbol_t sym;
sym.address = address; sym.address = address;
sym.name = g_strdup (tokens[2]); sym.name = g_strdup (tokens[2]);
g_array_append_val (table, sym); g_array_append_val (table, sym);
} }
} }
g_strfreev (tokens); g_strfreev (tokens);
} }
@ -614,24 +614,24 @@ parse_kallsyms (const char *kallsyms,
{ {
const char *sol; const char *sol;
const char *eol; const char *eol;
sol = kallsyms; sol = kallsyms;
eol = strchr (sol, '\n'); eol = strchr (sol, '\n');
while (eol) while (eol)
{ {
char *line = g_strndup (sol, eol - sol); char *line = g_strndup (sol, eol - sol);
parse_kallsym_line (line, table); parse_kallsym_line (line, table);
g_free (line); g_free (line);
sol = eol + 1; sol = eol + 1;
eol = strchr (sol, '\n'); eol = strchr (sol, '\n');
} }
if (table->len <= 1) if (table->len <= 1)
return FALSE; return FALSE;
return TRUE; return TRUE;
} }
@ -640,7 +640,7 @@ compare_syms (gconstpointer a, gconstpointer b)
{ {
const kernel_symbol_t *sym_a = a; const kernel_symbol_t *sym_a = a;
const kernel_symbol_t *sym_b = b; const kernel_symbol_t *sym_b = b;
if (sym_a->address > sym_b->address) if (sym_a->address > sym_b->address)
return 1; return 1;
else if (sym_a->address == sym_b->address) else if (sym_a->address == sym_b->address)
@ -665,16 +665,16 @@ do_lookup (kernel_symbol_t *symbols,
{ {
if (address >= symbols[last].address) if (address >= symbols[last].address)
return &(symbols[last]); return &(symbols[last]);
last--; last--;
} }
return NULL; return NULL;
} }
else else
{ {
int mid = (first + last) / 2; int mid = (first + last) / 2;
if (symbols[mid].address > address) if (symbols[mid].address > address)
return do_lookup (symbols, address, first, mid); return do_lookup (symbols, address, first, mid);
else else
@ -687,11 +687,11 @@ get_kernel_symbols (void)
{ {
static GArray *kernel_syms; static GArray *kernel_syms;
static gboolean initialized = FALSE; static gboolean initialized = FALSE;
#if 0 #if 0
find_kernel_binary(); find_kernel_binary();
#endif #endif
if (!initialized) if (!initialized)
{ {
char *kallsyms; char *kallsyms;
@ -700,7 +700,7 @@ get_kernel_symbols (void)
if (kallsyms) if (kallsyms)
{ {
kernel_syms = g_array_new (TRUE, TRUE, sizeof (kernel_symbol_t)); kernel_syms = g_array_new (TRUE, TRUE, sizeof (kernel_symbol_t));
if (parse_kallsyms (kallsyms, kernel_syms)) if (parse_kallsyms (kallsyms, kernel_syms))
{ {
g_array_sort (kernel_syms, compare_syms); g_array_sort (kernel_syms, compare_syms);
@ -711,24 +711,25 @@ get_kernel_symbols (void)
kernel_syms = NULL; kernel_syms = NULL;
} }
} }
g_free (kallsyms); g_free (kallsyms);
} }
if (!kernel_syms) if (!kernel_syms)
{ {
g_print ("Warning: /proc/kallsyms could not be " g_print ("Warning: /proc/kallsyms could not be "
"read. Kernel symbols will not be available\n"); "read. Kernel symbols will not be available\n");
} }
initialized = TRUE; initialized = TRUE;
} }
return kernel_syms; return kernel_syms;
} }
static const char skip_kernel_symbols[][32] = static const char skip_kernel_symbols[][32] =
{ {
/* IRQ stack */
"common_interrupt", "common_interrupt",
"apic_timer_interrupt", "apic_timer_interrupt",
"smp_apic_timer_interrupt", "smp_apic_timer_interrupt",
@ -739,6 +740,20 @@ static const char skip_kernel_symbols[][32] =
"__perf_event_overflow", "__perf_event_overflow",
"perf_prepare_sample", "perf_prepare_sample",
"perf_callchain", "perf_callchain",
/* NMI stack */
"nmi_stack_correct",
"do_nmi",
"notify_die",
"atomic_notifier_call_chain",
"notifier_call_chain",
"perf_event_nmi_handler",
"intel_pmu_handle_irq",
"perf_event_overflow",
"__perf_event_overflow",
"perf_prepare_sample",
"perf_callchain",
"" ""
}; };
@ -750,12 +765,12 @@ lookup_kernel_symbol (gulong address)
const char *sym; const char *sym;
const char *s; const char *s;
int i; int i;
if (ksyms->len == 0) if (ksyms->len == 0)
return NULL; return NULL;
result = do_lookup ((kernel_symbol_t *)ksyms->data, address, 0, ksyms->len - 1); result = do_lookup ((kernel_symbol_t *)ksyms->data, address, 0, ksyms->len - 1);
sym = result? result->name : NULL; sym = result? result->name : NULL;
@ -791,14 +806,14 @@ static char *
unique_dup (GHashTable *unique_symbols, const char *sym) unique_dup (GHashTable *unique_symbols, const char *sym)
{ {
char *result; char *result;
result = g_hash_table_lookup (unique_symbols, sym); result = g_hash_table_lookup (unique_symbols, sym);
if (!result) if (!result)
{ {
result = elf_demangle (sym); result = elf_demangle (sym);
g_hash_table_insert (unique_symbols, (char *)sym, result); g_hash_table_insert (unique_symbols, (char *)sym, result);
} }
return result; return result;
} }
@ -806,15 +821,15 @@ static map_t *
process_locate_map (process_t *process, gulong addr) process_locate_map (process_t *process, gulong addr)
{ {
int i; int i;
for (i = 0; i < process->maps->len; ++i) for (i = 0; i < process->maps->len; ++i)
{ {
map_t *map = process->maps->pdata[i]; map_t *map = process->maps->pdata[i];
if (addr >= map->start && addr < map->end) if (addr >= map->start && addr < map->end)
return map; return map;
} }
return NULL; return NULL;
} }
@ -837,7 +852,7 @@ make_message (state_t *state, const char *format, ...)
else else
{ {
result = message; result = message;
g_hash_table_insert (state->unique_comms, result, result); g_hash_table_insert (state->unique_comms, result, result);
} }
@ -866,9 +881,9 @@ lookup_symbol (state_t *state,
gboolean kernel) gboolean kernel)
{ {
const char *sym; const char *sym;
g_assert (process); g_assert (process);
if (kernel) if (kernel)
{ {
sym = lookup_kernel_symbol (address); sym = lookup_kernel_symbol (address);
@ -876,7 +891,7 @@ lookup_symbol (state_t *state,
else else
{ {
map_t *map = process_locate_map (process, address); map_t *map = process_locate_map (process, address);
if (!map) if (!map)
{ {
sym = make_message (state, "No map [%s]", process->comm); sym = make_message (state, "No map [%s]", process->comm);
@ -885,7 +900,7 @@ lookup_symbol (state_t *state,
{ {
bin_file_t *bin_file = state_get_bin_file (state, map->filename); bin_file_t *bin_file = state_get_bin_file (state, map->filename);
const bin_symbol_t *bin_sym; const bin_symbol_t *bin_sym;
address -= map->start; address -= map->start;
address += map->offset; address += map->offset;
@ -899,12 +914,12 @@ lookup_symbol (state_t *state,
else else
{ {
bin_sym = bin_file_lookup_symbol (bin_file, address); bin_sym = bin_file_lookup_symbol (bin_file, address);
sym = bin_symbol_get_name (bin_file, bin_sym); sym = bin_symbol_get_name (bin_file, bin_sym);
} }
} }
} }
if (sym) if (sym)
return unique_dup (state->unique_symbols, sym); return unique_dup (state->unique_symbols, sym);
else else
@ -916,7 +931,7 @@ struct context_info_t
{ {
enum perf_callchain_context context; enum perf_callchain_context context;
char name[32]; char name[32];
}; };
static const context_info_t context_info[] = static const context_info_t context_info[] =
{ {
@ -934,15 +949,15 @@ static const context_info_t *
get_context_info (enum perf_callchain_context context) get_context_info (enum perf_callchain_context context)
{ {
int i; int i;
for (i = 0; i < sizeof (context_info) / sizeof (context_info[0]); ++i) for (i = 0; i < sizeof (context_info) / sizeof (context_info[0]); ++i)
{ {
const context_info_t *info = &context_info[i]; const context_info_t *info = &context_info[i];
if (info->context == context) if (info->context == context)
return info; return info;
} }
return NULL; return NULL;
} }
@ -960,7 +975,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
process = g_hash_table_lookup ( process = g_hash_table_lookup (
state->processes_by_pid, GINT_TO_POINTER (pid)); state->processes_by_pid, GINT_TO_POINTER (pid));
if (!process) if (!process)
{ {
static gboolean warned; static gboolean warned;
@ -973,7 +988,7 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
} }
return; return;
} }
len = 5; len = 5;
for (n = sample->trace; n != NULL; n = n->parent) for (n = sample->trace; n != NULL; n = n->parent)
len++; len++;
@ -982,14 +997,14 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
resolved_traces = g_new (uint64_t, len); resolved_traces = g_new (uint64_t, len);
else else
resolved_traces = stack_addrs; resolved_traces = stack_addrs;
len = 0; len = 0;
for (n = sample->trace; n != NULL; n = n->parent) for (n = sample->trace; n != NULL; n = n->parent)
{ {
uint64_t address = n->data; uint64_t address = n->data;
const context_info_t *new_context; const context_info_t *new_context;
const char *symbol; const char *symbol;
new_context = get_context_info (address); new_context = get_context_info (address);
if (new_context) if (new_context)
{ {
@ -997,16 +1012,16 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
symbol = unique_dup (state->unique_symbols, context->name); symbol = unique_dup (state->unique_symbols, context->name);
else else
symbol = NULL; symbol = NULL;
context = new_context; context = new_context;
} }
else else
{ {
gboolean kernel = context && context->context == PERF_CONTEXT_KERNEL; gboolean kernel = context && context->context == PERF_CONTEXT_KERNEL;
symbol = lookup_symbol (state, process, address, kernel); symbol = lookup_symbol (state, process, address, kernel);
} }
if (symbol) if (symbol)
resolved_traces[len++] = POINTER_TO_U64 (symbol); resolved_traces[len++] = POINTER_TO_U64 (symbol);
} }
@ -1021,9 +1036,9 @@ process_sample (state_t *state, StackStash *resolved, sample_t *sample)
resolved_traces[len++] = resolved_traces[len++] =
POINTER_TO_U64 (unique_dup (state->unique_symbols, context->name)); POINTER_TO_U64 (unique_dup (state->unique_symbols, context->name));
} }
cmdline = make_message (state, "[%s]", process->comm); cmdline = make_message (state, "[%s]", process->comm);
resolved_traces[len++] = POINTER_TO_U64 (cmdline); resolved_traces[len++] = POINTER_TO_U64 (cmdline);
resolved_traces[len++] = POINTER_TO_U64 ( resolved_traces[len++] = POINTER_TO_U64 (
unique_dup (state->unique_symbols, everything)); unique_dup (state->unique_symbols, everything));
@ -1042,22 +1057,22 @@ tracker_create_profile (tracker_t *tracker)
Profile *profile; Profile *profile;
state_t *state; state_t *state;
uint8_t *event; uint8_t *event;
state = state_new (); state = state_new ();
resolved_stash = stack_stash_new (g_free); resolved_stash = stack_stash_new (g_free);
event = tracker->events; event = tracker->events;
while (event < end) while (event < end)
{ {
event_type_t type = GET_TYPE (*(uint32_t *)event); event_type_t type = GET_TYPE (*(uint32_t *)event);
switch (type) switch (type)
{ {
case NEW_PROCESS: case NEW_PROCESS:
create_process (state, (new_process_t *)event); create_process (state, (new_process_t *)event);
event += sizeof (new_process_t); event += sizeof (new_process_t);
break; break;
case NEW_MAP: case NEW_MAP:
create_map (state, (new_map_t *)event); create_map (state, (new_map_t *)event);
event += sizeof (new_map_t); event += sizeof (new_map_t);
@ -1072,7 +1087,7 @@ tracker_create_profile (tracker_t *tracker)
process_exit (state, (exit_t *)event); process_exit (state, (exit_t *)event);
event += sizeof (exit_t); event += sizeof (exit_t);
break; break;
case SAMPLE: case SAMPLE:
process_sample (state, resolved_stash, (sample_t *)event); process_sample (state, resolved_stash, (sample_t *)event);
event += sizeof (sample_t); event += sizeof (sample_t);
@ -1084,6 +1099,6 @@ tracker_create_profile (tracker_t *tracker)
state_free (state); state_free (state);
stack_stash_unref (resolved_stash); stack_stash_unref (resolved_stash);
return profile; return profile;
} }