mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-11 07:30:54 +00:00
Add some experimental (and unused) code to look up kernel symbols.
2005-11-13 Soeren Sandmann <sandmann@redhat.com> * process.c: Add some experimental (and unused) code to look up kernel symbols.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
b6e9105cd2
commit
7414ddd5db
@ -1,3 +1,8 @@
|
|||||||
|
2005-11-13 Soeren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
|
* process.c: Add some experimental (and unused) code to look up
|
||||||
|
kernel symbols.
|
||||||
|
|
||||||
Sat Nov 12 23:39:29 2005 Soeren Sandmann <sandmann@redhat.com>
|
Sat Nov 12 23:39:29 2005 Soeren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
* sysprof.c (set_sizes): Put the vertical splitter at 3/8 *
|
* sysprof.c (set_sizes): Put the vertical splitter at 3/8 *
|
||||||
|
|||||||
226
process.c
226
process.c
@ -54,9 +54,9 @@ struct Process
|
|||||||
|
|
||||||
GList *maps;
|
GList *maps;
|
||||||
GList *bad_pages;
|
GList *bad_pages;
|
||||||
|
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
Symbol undefined;
|
Symbol undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ read_maps (int pid)
|
|||||||
guint start;
|
guint start;
|
||||||
guint end;
|
guint end;
|
||||||
guint offset;
|
guint offset;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_print ("buffer: %s\n", buffer);
|
g_print ("buffer: %s\n", buffer);
|
||||||
#endif
|
#endif
|
||||||
@ -106,7 +106,7 @@ read_maps (int pid)
|
|||||||
if (count == 4)
|
if (count == 4)
|
||||||
{
|
{
|
||||||
Map *map;
|
Map *map;
|
||||||
|
|
||||||
map = g_new (Map, 1);
|
map = g_new (Map, 1);
|
||||||
|
|
||||||
map->filename = g_strdup (file);
|
map->filename = g_strdup (file);
|
||||||
@ -139,12 +139,12 @@ create_process (const char *cmdline, int pid)
|
|||||||
Process *p;
|
Process *p;
|
||||||
|
|
||||||
p = g_new0 (Process, 1);
|
p = g_new0 (Process, 1);
|
||||||
|
|
||||||
if (*cmdline != '\0')
|
if (*cmdline != '\0')
|
||||||
p->cmdline = g_strdup_printf ("[%s]", cmdline);
|
p->cmdline = g_strdup_printf ("[%s]", cmdline);
|
||||||
else
|
else
|
||||||
p->cmdline = g_strdup_printf ("[pid %d]", pid);
|
p->cmdline = g_strdup_printf ("[pid %d]", pid);
|
||||||
|
|
||||||
p->bad_pages = NULL;
|
p->bad_pages = NULL;
|
||||||
p->maps = NULL;
|
p->maps = NULL;
|
||||||
p->pid = pid;
|
p->pid = pid;
|
||||||
@ -187,7 +187,7 @@ process_free_maps (Process *process)
|
|||||||
for (list = process->maps; list != NULL; list = list->next)
|
for (list = process->maps; list != NULL; list = list->next)
|
||||||
{
|
{
|
||||||
Map *map = list->data;
|
Map *map = list->data;
|
||||||
|
|
||||||
if (map->filename)
|
if (map->filename)
|
||||||
g_free (map->filename);
|
g_free (map->filename);
|
||||||
|
|
||||||
@ -213,15 +213,15 @@ void
|
|||||||
process_ensure_map (Process *process, int pid, gulong addr)
|
process_ensure_map (Process *process, int pid, gulong addr)
|
||||||
{
|
{
|
||||||
/* Round down to closest page */
|
/* Round down to closest page */
|
||||||
|
|
||||||
addr = (addr - addr % PAGE_SIZE);
|
addr = (addr - addr % PAGE_SIZE);
|
||||||
|
|
||||||
if (process_has_page (process, addr))
|
if (process_has_page (process, addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (g_list_find (process->bad_pages, (gpointer)addr))
|
if (g_list_find (process->bad_pages, (gpointer)addr))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* a map containing addr was not found */
|
/* a map containing addr was not found */
|
||||||
if (process->maps)
|
if (process->maps)
|
||||||
process_free_maps (process);
|
process_free_maps (process);
|
||||||
@ -256,7 +256,7 @@ get_cmdline (int pid)
|
|||||||
{
|
{
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
char *filename = idle_free (g_strdup_printf ("/proc/%d/cmdline", pid));
|
char *filename = idle_free (g_strdup_printf ("/proc/%d/cmdline", pid));
|
||||||
|
|
||||||
if (g_file_get_contents (filename, &cmdline, NULL, NULL))
|
if (g_file_get_contents (filename, &cmdline, NULL, NULL))
|
||||||
{
|
{
|
||||||
if (*cmdline == '\0')
|
if (*cmdline == '\0')
|
||||||
@ -266,7 +266,7 @@ get_cmdline (int pid)
|
|||||||
}
|
}
|
||||||
return cmdline;
|
return cmdline;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -275,7 +275,7 @@ get_statname (int pid)
|
|||||||
{
|
{
|
||||||
char *stat;
|
char *stat;
|
||||||
char *filename = idle_free (g_strdup_printf ("/proc/%d/stat", pid));
|
char *filename = idle_free (g_strdup_printf ("/proc/%d/stat", pid));
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_print ("stat %d\n", pid);
|
g_print ("stat %d\n", pid);
|
||||||
#endif
|
#endif
|
||||||
@ -285,7 +285,7 @@ get_statname (int pid)
|
|||||||
char result[200];
|
char result[200];
|
||||||
|
|
||||||
idle_free (stat);
|
idle_free (stat);
|
||||||
|
|
||||||
if (sscanf (stat, "%*d %200s %*s", result) == 1)
|
if (sscanf (stat, "%*d %200s %*s", result) == 1)
|
||||||
return g_strndup (result, 200);
|
return g_strndup (result, 200);
|
||||||
}
|
}
|
||||||
@ -309,13 +309,13 @@ static char *
|
|||||||
get_name (int pid)
|
get_name (int pid)
|
||||||
{
|
{
|
||||||
char *cmdline = NULL;
|
char *cmdline = NULL;
|
||||||
|
|
||||||
if ((cmdline = get_cmdline (pid)))
|
if ((cmdline = get_cmdline (pid)))
|
||||||
return cmdline;
|
return cmdline;
|
||||||
|
|
||||||
if ((cmdline = get_statname (pid)))
|
if ((cmdline = get_statname (pid)))
|
||||||
return cmdline;
|
return cmdline;
|
||||||
|
|
||||||
return get_pidname (pid);
|
return get_pidname (pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -326,37 +326,193 @@ process_get_from_pid (int pid)
|
|||||||
gchar *cmdline = NULL;
|
gchar *cmdline = NULL;
|
||||||
|
|
||||||
initialize();
|
initialize();
|
||||||
|
|
||||||
p = g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid));
|
p = g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid));
|
||||||
|
|
||||||
if (p)
|
if (p)
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
cmdline = get_name (pid);
|
cmdline = get_name (pid);
|
||||||
|
|
||||||
idle_free (cmdline);
|
idle_free (cmdline);
|
||||||
|
|
||||||
p = g_hash_table_lookup (processes_by_cmdline, cmdline);
|
p = g_hash_table_lookup (processes_by_cmdline, cmdline);
|
||||||
if (!p)
|
if (!p)
|
||||||
p = create_process (cmdline, pid);
|
p = create_process (cmdline, pid);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#include <sys/utsname.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
file_exists (const char *name)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
fd = open (name, O_RDONLY);
|
||||||
|
|
||||||
|
g_print ("trying: %s\n", name);
|
||||||
|
|
||||||
|
if (fd > 0)
|
||||||
|
{
|
||||||
|
close (fd);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gchar *
|
||||||
|
look_for_vmlinux (void)
|
||||||
|
{
|
||||||
|
struct utsname utsname;
|
||||||
|
char *result;
|
||||||
|
GList *names;
|
||||||
|
GList *list;
|
||||||
|
uname (&utsname);
|
||||||
|
|
||||||
|
names = NULL;
|
||||||
|
|
||||||
|
names = g_list_prepend (
|
||||||
|
names, g_strdup_printf (
|
||||||
|
"/usr/lib/debug/lib/modules/%s/vmlinux", utsname.release));
|
||||||
|
|
||||||
|
names = g_list_prepend (
|
||||||
|
names, g_strdup_printf (
|
||||||
|
"/boot/vmlinux-%s", utsname.release));
|
||||||
|
|
||||||
|
result = NULL;
|
||||||
|
|
||||||
|
for (list = names; list != NULL; list = list->next)
|
||||||
|
{
|
||||||
|
char *name = list->data;
|
||||||
|
|
||||||
|
if (file_exists (name))
|
||||||
|
{
|
||||||
|
result = g_strdup (name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_list_foreach (names, (GFunc)g_free, NULL);
|
||||||
|
g_list_free (names);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_kallsym_line (const char *line,
|
||||||
|
GHashTable *table)
|
||||||
|
{
|
||||||
|
char **tokens = g_strsplit_set (line, " \t", -1);
|
||||||
|
|
||||||
|
if (tokens[0] && tokens[1] && tokens[2])
|
||||||
|
{
|
||||||
|
glong address;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
address = strtoul (tokens[0], &endptr, 16);
|
||||||
|
|
||||||
|
if (*endptr == '\0')
|
||||||
|
{
|
||||||
|
g_hash_table_insert (
|
||||||
|
table, GUINT_TO_POINTER (address), g_strdup (tokens[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_kallsyms (const char *kallsyms,
|
||||||
|
GHashTable *table)
|
||||||
|
{
|
||||||
|
const char *sol;
|
||||||
|
const char *eol;
|
||||||
|
|
||||||
|
sol = kallsyms;
|
||||||
|
eol = strchr (sol, '\n');
|
||||||
|
while (eol)
|
||||||
|
{
|
||||||
|
char *line = g_strndup (sol, eol - sol);
|
||||||
|
|
||||||
|
parse_kallsym_line (line, table);
|
||||||
|
|
||||||
|
g_free (line);
|
||||||
|
|
||||||
|
sol = eol + 1;
|
||||||
|
eol = strchr (sol, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static GHashTable *
|
||||||
|
get_kernel_symbols (void)
|
||||||
|
{
|
||||||
|
static GHashTable *kernel_syms;
|
||||||
|
|
||||||
|
if (!kernel_syms)
|
||||||
|
{
|
||||||
|
char *kallsyms;
|
||||||
|
g_file_get_contents ("/proc/kallsyms", &kallsyms, NULL, NULL);
|
||||||
|
|
||||||
|
if (kallsyms)
|
||||||
|
{
|
||||||
|
kernel_syms = g_hash_table_new_full (g_direct_hash, g_direct_equal,
|
||||||
|
NULL, g_free);
|
||||||
|
|
||||||
|
parse_kallsyms (kallsyms, kernel_syms);
|
||||||
|
|
||||||
|
g_free (kallsyms);
|
||||||
|
g_hash_table_destroy (kernel_syms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Symbol *
|
||||||
|
lookup_kernel_symbol (gulong address)
|
||||||
|
{
|
||||||
|
static Symbol kernel;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("kernel binary: %s\n", find_kernel_binary ());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
kernel.name = "In kernel";
|
||||||
|
kernel.address = 0x00001337;
|
||||||
|
return &kernel;
|
||||||
|
}
|
||||||
|
|
||||||
const Symbol *
|
const Symbol *
|
||||||
process_lookup_symbol (Process *process, gulong address)
|
process_lookup_symbol (Process *process, gulong address)
|
||||||
{
|
{
|
||||||
const Symbol *result;
|
const Symbol *result;
|
||||||
static Symbol kernel;
|
|
||||||
Map *map = process_locate_map (process, address);
|
Map *map = process_locate_map (process, address);
|
||||||
|
|
||||||
/* g_print ("addr: %x\n", address); */
|
/* g_print ("addr: %x\n", address); */
|
||||||
|
|
||||||
if (address == 0x1)
|
if (address == 0x1)
|
||||||
{
|
{
|
||||||
kernel.name = "In kernel";
|
return lookup_kernel_symbol (address);
|
||||||
kernel.address = 0x00001337;
|
|
||||||
return &kernel;
|
|
||||||
}
|
}
|
||||||
else if (!map)
|
else if (!map)
|
||||||
{
|
{
|
||||||
@ -366,27 +522,27 @@ process_lookup_symbol (Process *process, gulong address)
|
|||||||
g_strdup_printf ("(??? %s)", process->cmdline);
|
g_strdup_printf ("(??? %s)", process->cmdline);
|
||||||
process->undefined.address = 0xBABE0001;
|
process->undefined.address = 0xBABE0001;
|
||||||
}
|
}
|
||||||
|
|
||||||
return &process->undefined;
|
return &process->undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
address -= map->start;
|
address -= map->start;
|
||||||
address += map->offset;
|
address += map->offset;
|
||||||
|
|
||||||
if (!map->bin_file)
|
if (!map->bin_file)
|
||||||
map->bin_file = bin_file_new (map->filename);
|
map->bin_file = bin_file_new (map->filename);
|
||||||
|
|
||||||
/* g_print ("%s: start: %p, load: %p\n", */
|
/* g_print ("%s: start: %p, load: %p\n", */
|
||||||
/* map->filename, map->start, bin_file_get_load_address (map->bin_file)); */
|
/* map->filename, map->start, bin_file_get_load_address (map->bin_file)); */
|
||||||
|
|
||||||
result = bin_file_lookup_symbol (map->bin_file, address);
|
result = bin_file_lookup_symbol (map->bin_file, address);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
g_print (" ---> %s\n", result->name);
|
g_print (" ---> %s\n", result->name);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* g_print ("(%x) %x %x name; %s\n", address, map->start, map->offset, result->name); */
|
/* g_print ("(%x) %x %x name; %s\n", address, map->start, map->offset, result->name); */
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user