From: Søren Sandmann Pedersen Date: Tue, 8 Sep 2009 03:35:30 +0000 (-0400) Subject: Remove last bits of process.[ch] X-Git-Tag: 1.1.2~20 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=3d9cbe20e74eea26bbd386b10f00c5cb449bc5b1;p=platform%2Fupstream%2Fsysprof.git Remove last bits of process.[ch] --- diff --git a/collector.c b/collector.c index 561211b..df0172a 100644 --- a/collector.c +++ b/collector.c @@ -32,7 +32,6 @@ #include "collector.h" #include "module/sysprof-module.h" #include "watch.h" -#include "process.h" #include "elfparser.h" #include "tracker.h" @@ -554,190 +553,10 @@ collector_get_n_samples (Collector *collector) return collector->n_samples; } -typedef struct -{ - StackStash *resolved_stash; - GHashTable *unique_symbols; - GHashTable *unique_cmdlines; -} ResolveInfo; - -/* Note that 'unique_symbols' is a direct_hash table. Ie., we - * rely on the address of symbol strings being different for different - * symbols. - */ -static char * -unique_dup (GHashTable *unique_symbols, const char *sym) -{ - char *result; - - result = g_hash_table_lookup (unique_symbols, sym); - if (!result) - { - result = elf_demangle (sym); - g_hash_table_insert (unique_symbols, (char *)sym, result); - } - - return result; -} - -static char * -lookup_symbol (Process *process, uint64_t address, - GHashTable *unique_symbols, - gboolean kernel, - gboolean first_addr) -{ - const char *sym; - - g_assert (process); - - if (kernel) - { - gulong offset; - sym = process_lookup_kernel_symbol ((gulong)address, &offset); - - /* If offset is 0, it is a callback, not a return address. - * - * If "first_addr" is true, then the address is an - * instruction pointer, not a return address, so it may - * legitimately be at offset 0. - */ - if (offset == 0 && !first_addr) - { -#if 0 - g_print ("rejecting callback: %s (%p)\n", sym, address); -#endif - sym = NULL; - } - - /* If offset is greater than 4096, then what happened is most - * likely that it is the address of something in the gap between the - * kernel text and the text of the modules. Rather than assign - * this to the last function of the kernel text, we remove it here. - * - * FIXME: what we really should do is find out where this split - * is, and act accordingly. Actually, we should look at /proc/modules - */ - if (offset > 4096) - { -#if 0 - g_print ("offset\n"); -#endif - sym = NULL; - } - } - else - { - gulong offset; - - sym = process_lookup_symbol (process, (gulong)address, &offset); - - if (offset == 0 && !first_addr) - { -#if 0 - sym = g_strdup_printf ("%s [callback]", sym); - g_print ("rejecting %s since it looks like a callback\n", - sym); - sym = NULL; -#endif - } - } - - if (sym) - return unique_dup (unique_symbols, sym); - else - return NULL; -} - -static void -resolve_symbols (StackLink *trace, gint size, gpointer data) -{ - static const char *const everything = "[Everything]"; - ResolveInfo *info = data; - gboolean in_kernel = FALSE; - gboolean first_addr = TRUE; - uint64_t addr_stack[128]; - uint64_t *resolved_trace; - StackLink *link; - Process *process; - char *cmdline; - int len; - - len = 2; - - for (link = trace; link && link->next; link = link->next) - { - if (link->data == 0x01) - in_kernel = TRUE; - - len++; - } - - if (len > 128) - resolved_trace = g_new (uint64_t, len); - else - resolved_trace = addr_stack; - - process = U64_TO_POINTER (link->data); - - len = 0; - for (link = trace; link && link->next; link = link->next) - { - uint64_t address = link->data; - char *symbol; - - if (address == 0x01) - in_kernel = FALSE; - - symbol = lookup_symbol (process, address, info->unique_symbols, - in_kernel, first_addr); - first_addr = FALSE; - - if (symbol) - resolved_trace[len++] = POINTER_TO_U64 (symbol); - } - - cmdline = g_hash_table_lookup ( - info->unique_cmdlines, (char *)process_get_cmdline (process)); - - if (!cmdline) - { - cmdline = g_strdup (process_get_cmdline (process)); - - g_hash_table_insert (info->unique_cmdlines, cmdline, cmdline); - } - - resolved_trace[len++] = POINTER_TO_U64 (cmdline); - resolved_trace[len++] = POINTER_TO_U64 ( - unique_dup (info->unique_symbols, everything)); - - stack_stash_add_trace (info->resolved_stash, resolved_trace, len, size); - - if (resolved_trace != addr_stack) - g_free (resolved_trace); -} - Profile * collector_create_profile (Collector *collector) { return tracker_create_profile (collector->tracker); - - ResolveInfo info; - Profile *profile; - - info.resolved_stash = stack_stash_new ((GDestroyNotify)g_free); - info.unique_symbols = g_hash_table_new (g_direct_hash, g_direct_equal); - info.unique_cmdlines = g_hash_table_new (g_str_hash, g_str_equal); - - stack_stash_foreach (collector->stash, resolve_symbols, &info); - - g_hash_table_destroy (info.unique_symbols); - g_hash_table_destroy (info.unique_cmdlines); - - profile = profile_new (info.resolved_stash); - - stack_stash_unref (info.resolved_stash); - - return profile; } GQuark diff --git a/process.c b/process.c deleted file mode 100644 index bf6991a..0000000 --- a/process.c +++ /dev/null @@ -1,329 +0,0 @@ -/* MemProf -- memory profiler and leak detector - * Copyright 1999, 2000, 2001, Red Hat, Inc. - * Copyright 2002, Kristian Rietveld - * - * Sysprof -- Sampling, systemwide CPU profiler - * Copyright 2004-2007 Soeren Sandmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "process.h" -#include "binfile.h" - -static GHashTable *processes_by_pid; - -struct Process -{ - char * cmdline; - - int n_maps; - Map * maps; - - GList * bad_pages; - - int pid; - - char * undefined; -}; - -static void -initialize (void) -{ - if (!processes_by_pid) - processes_by_pid = g_hash_table_new (g_direct_hash, g_direct_equal); -} - -static Process * -create_process (const char *cmdline, int pid) -{ - Process *p; - - p = g_new0 (Process, 1); - - if (*cmdline != '\0') - p->cmdline = g_strdup_printf ("[%s]", cmdline); - else - p->cmdline = g_strdup_printf ("[pid %d]", pid); - - p->bad_pages = NULL; - p->n_maps = 0; - p->maps = NULL; - p->pid = pid; - p->undefined = NULL; - - g_assert (!g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid))); - - g_hash_table_insert (processes_by_pid, GINT_TO_POINTER (pid), p); - - return p; -} - -static Map * -process_locate_map (Process *process, gulong addr) -{ - int i; - - for (i = 0; i < process->n_maps; ++i) - { - Map *map = &(process->maps[i]); - - if ((addr >= map->start) && - (addr < map->end)) - { - if (i > 4) - { - /* FIXME: Is this move-to-front really worth it? */ - Map tmp = *map; - - memmove (process->maps + 1, process->maps, i * sizeof (Map)); - - *(process->maps) = tmp; - - map = process->maps; - } - - return map; - } - } - - return NULL; -} - -static void -free_process (gpointer key, gpointer value, gpointer data) -{ - Process *process = value; - - free_maps (&(process->n_maps), process->maps); - - g_free (process->undefined); - g_free (process->cmdline); - g_list_free (process->bad_pages); - - g_free (process); -} - -void -process_flush_caches (void) -{ - if (!processes_by_pid) - return; - - g_hash_table_foreach (processes_by_pid, free_process, NULL); - g_hash_table_destroy (processes_by_pid); - - processes_by_pid = NULL; -} - - -static gboolean -process_has_page (Process *process, gulong addr) -{ - if (process_locate_map (process, addr)) - return TRUE; - else - return FALSE; -} - -void -process_ensure_map (Process *process, int pid, gulong addr) -{ - /* Round down to closest page */ - - addr = (addr - addr % process_get_page_size()); - - if (process_has_page (process, addr)) - return; - - if (g_list_find (process->bad_pages, (gpointer)addr)) - return; - - /* a map containing addr was not found */ - if (process->maps) - free_maps (&(process->n_maps), process->maps); - - process->maps = read_maps (pid, &(process->n_maps)); - - if (!process_has_page (process, addr)) - { -#if 0 - g_print ("Bad page: %p\n", addr); -#endif - process->bad_pages = g_list_prepend (process->bad_pages, (gpointer)addr); - } -} - -static gboolean -do_idle_free (gpointer d) -{ - g_free (d); - return FALSE; -} - -static char * -idle_free (char *d) -{ - g_idle_add (do_idle_free, d); - return d; -} - -static char * -get_cmdline (int pid) -{ - char *cmdline; - char *filename = idle_free (g_strdup_printf ("/proc/%d/cmdline", pid)); - - if (g_file_get_contents (filename, &cmdline, NULL, NULL)) - { - if (*cmdline == '\0') - { - g_free (cmdline); - return NULL; - } - return cmdline; - } - - return NULL; -} - -static char * -get_statname (int pid) -{ - char *stat; - char *filename = idle_free (g_strdup_printf ("/proc/%d/stat", pid)); - - if (g_file_get_contents (filename, &stat, NULL, NULL)) - { - char result[200]; - - idle_free (stat); - - if (sscanf (stat, "%*d %200s %*s", result) == 1) - return g_strndup (result, 200); - } - - return NULL; -} - -static char * -get_pidname (int pid) -{ - if (pid == -1) - return g_strdup_printf ("kernel"); - else - return g_strdup_printf ("pid %d", pid); -} - -static char * -get_name (int pid) -{ - char *cmdline = NULL; - - if ((cmdline = get_cmdline (pid))) - return cmdline; - - if ((cmdline = get_statname (pid))) - return cmdline; - - return get_pidname (pid); -} - -Process * -process_get_from_pid (int pid) -{ - Process *p; - - initialize(); - - p = g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid)); - - if (!p) - p = create_process (idle_free (get_name (pid)), pid); - - return p; -} - -static gboolean -file_exists (const char *name) -{ - int fd; - fd = open (name, O_RDONLY); - - if (fd > 0) - { - close (fd); - return TRUE; - } - return FALSE; -} - -static gchar * -look_for_vmlinux (void) -{ - static const char names[][48] = { - "/lib/modules/%s/build/vmlinux", - "/usr/lib/debug/lib/modules/%s/vmlinux", - "/lib/modules/%s/source/vmlinux", - "/boot/vmlinux-%s", - }; - struct utsname utsname; - int i; - - uname (&utsname); - - for (i = 0; i < G_N_ELEMENTS (names); ++i) - { - char *filename = g_strdup_printf (names[i], utsname.release); - - if (file_exists (filename)) - return filename; - - g_free (filename); - } - - return NULL; -} - -static const gchar * -find_kernel_binary (void) -{ - static gboolean looked_for_vmlinux; - static gchar *binary = NULL; - - if (!looked_for_vmlinux) - { - binary = look_for_vmlinux (); - looked_for_vmlinux = TRUE; - } - - return binary; -} - -const char * -process_get_cmdline (Process *process) -{ - return process->cmdline; -} diff --git a/process.h b/process.h deleted file mode 100644 index 21faf4d..0000000 --- a/process.h +++ /dev/null @@ -1,65 +0,0 @@ -/* MemProf -- memory profiler and leak detector - * Copyright 1999, 2000, 2001, Red Hat, Inc. - * Copyright 2002, Kristian Rietveld - * - * Sysprof -- Sampling, systemwide CPU profiler - * Copyright 2004, Red Hat, Inc - * Copyright 2004, 2005, Soeren Sandmann - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef PROCESS_H -#define PROCESS_H - -#include -#include "binfile.h" - -typedef struct Process Process; - -/* We are making the assumption that pid's are not recycled during - * a profiling run. That is wrong, but necessary to avoid reading - * from /proc//maps on every sample (which would be a race - * condition anyway). - * - * If the address passed to new_from_pid() is somewhere that hasn't - * been checked before, the mappings are reread for the Process. This - * means that if some previously sampled pages have been unmapped, - * they will be lost and appear as "???" on the profile. - * - * To flush the pid cache, call process_flush_caches(). - * This will invalidate all instances of Process. - * - * The real fix for this is probably to have the kernel module report the - * maps along with the stacktrace. - * - */ - -Process * process_get_from_pid (int pid); -void process_ensure_map (Process *process, - int pid, - gulong address); -const char * process_lookup_symbol (Process *process, - gulong address, - gulong *offset); -const char * process_get_cmdline (Process *process); -void process_flush_caches (void); -const guint8 *process_get_vdso_bytes (gsize *length); -gboolean process_is_kernel_address (gulong address); -const char * process_lookup_kernel_symbol (gulong address, - gulong *offset); -int process_get_page_size (void); - -#endif diff --git a/profile.c b/profile.c index b5ec149..51f328f 100644 --- a/profile.c +++ b/profile.c @@ -22,7 +22,6 @@ #include #include "binfile.h" -#include "process.h" #include "stackstash.h" #include "profile.h" #include "sfile.h" diff --git a/sysprof-cli.c b/sysprof-cli.c index 19be1f7..8dbe334 100644 --- a/sysprof-cli.c +++ b/sysprof-cli.c @@ -30,7 +30,6 @@ #include "stackstash.h" #include "module/sysprof-module.h" #include "profile.h" -#include "process.h" #include "watch.h" #include "signal-handler.h" #include "collector.h"