diff --git a/ChangeLog b/ChangeLog index 209834a2..9dc3d566 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2006-10-09 Soren Sandmann + + * profile.c (profile_list_callers): Make this function return a + list of immediate callers again. + + * sysprof.c (build_gui): Change label back to "Callers" + + * process.c (get_kernel_symbols): Only attempt to read the kernel + symbols once. + 2006-10-09 Soren Sandmann * binfile.c (bin_file_get_inode): Remove this function diff --git a/TODO b/TODO index 2e896262..ae43fb8c 100644 --- a/TODO +++ b/TODO @@ -34,6 +34,8 @@ Before 1.0.4: Before 1.2: +* Make sure that labels look decent in case of "No Map" etc. + * Elf bugs: - error handling for bin_parser is necessary. @@ -422,6 +424,7 @@ http://www.linuxbase.org/spec/booksets/LSB-Embedded/LSB-Embedded/ehframe.html should do a globale s/callers/ancestors on the code. - not sure it's an improvement. Often it is more interesting to find the immediate callers. + - Now it's back to just listing the immediate callers. - Have kernel module report the file the address was found in Should avoid a lot of potential broken/raciness with dlopen etc. diff --git a/process.c b/process.c index ae73990f..f8437464 100644 --- a/process.c +++ b/process.c @@ -555,9 +555,10 @@ parse_kallsyms (const char *kallsyms, static GHashTable * get_kernel_symbols (void) { + static gboolean read_symbols = FALSE; static GHashTable *kernel_syms; - if (!kernel_syms) + if (!read_symbols) { char *kallsyms; g_file_get_contents ("/proc/kallsyms", &kallsyms, NULL, NULL); @@ -572,6 +573,8 @@ get_kernel_symbols (void) g_free (kallsyms); g_hash_table_destroy (kernel_syms); } + + read_symbols = TRUE; } return NULL; diff --git a/profile.c b/profile.c index 1a874918..519dc100 100644 --- a/profile.c +++ b/profile.c @@ -359,6 +359,89 @@ profile_caller_new (void) return caller; } +ProfileCaller * +profile_list_callers (Profile *profile, + char *callee_name) +{ + StackNode *node; + StackNode *callees; + GHashTable *callers_by_name; + GHashTable *processed_callers; + ProfileCaller *result = NULL; + + callers_by_name = g_hash_table_new (g_direct_hash, g_direct_equal); + processed_callers = g_hash_table_new (g_direct_hash, g_direct_equal); + + callees = stack_stash_find_node (profile->stash, callee_name); + + for (node = callees; node != NULL; node = node->next) + { + gpointer name; + + if (node->parent) + name = node->parent->address; + else + name = NULL; + + if (!g_hash_table_lookup (callers_by_name, name)) + { + ProfileCaller *caller = profile_caller_new (); + caller->name = name; + caller->next = result; + caller->total = 0; + caller->self = 0; + + g_hash_table_insert (callers_by_name, name, caller); + result = caller; + } + } + + for (node = callees; node != NULL; node = node->next) + { + StackNode *top_caller = node->parent; + StackNode *top_callee = node; + StackNode *n; + ProfileCaller *caller; + + for (n = node; n && n->parent; n = n->parent) + { + if (n->address == node->address && + n->parent->address == node->parent->address) + { + top_caller = n->parent; + top_callee = n; + } + } + + if (node->parent) + caller = g_hash_table_lookup (callers_by_name, node->parent->address); + else + caller = g_hash_table_lookup (callers_by_name, NULL); + + if (!g_hash_table_lookup (processed_callers, top_caller)) + { + caller->total += top_callee->total; + + g_hash_table_insert (processed_callers, top_caller, top_caller); + } + + caller->self += node->size; + } + + g_hash_table_destroy (processed_callers); + g_hash_table_destroy (callers_by_name); + + return result; +} + +#if 0 +/* This code generates a list of all ancestors, rather than + * all callers. It turned out to not work well in practice, + * but on the other hand the single list of callers is not + * all that great either, so we'll keep it around commented + * out for now + */ + static void add_to_list (gpointer key, gpointer value, @@ -380,8 +463,8 @@ listify_hash_table (GHashTable *hash_table) } ProfileCaller * -profile_list_callers (Profile *profile, - char *callee_name) +profile_list_ancestors (Profile *profile, + char *callee_name) { StackNode *callees; StackNode *node; @@ -459,6 +542,7 @@ profile_list_callers (Profile *profile, return result; } +#endif void profile_free (Profile *profile) diff --git a/sysprof.c b/sysprof.c index 98eb88d8..7f3a8362 100644 --- a/sysprof.c +++ b/sysprof.c @@ -1447,7 +1447,7 @@ build_gui (Application *app) /* callers view */ app->callers_view = (GtkTreeView *)glade_xml_get_widget (xml, "callers_view"); gtk_tree_view_set_enable_search (app->callers_view, FALSE); - col = add_plain_text_column (app->callers_view, _("Ancestors"), CALLERS_NAME); + col = add_plain_text_column (app->callers_view, _("Callers"), CALLERS_NAME); add_double_format_column (app->callers_view, _("Self"), CALLERS_SELF, "%.2f "); add_double_format_column (app->callers_view, _("Total"), CALLERS_TOTAL, "%.2f "); g_signal_connect (app->callers_view, "row-activated",