diff --git a/binfile.c b/binfile.c index 6a1c8e0f..1a48956c 100644 --- a/binfile.c +++ b/binfile.c @@ -394,7 +394,9 @@ bin_file_lookup_symbol (BinFile *bf, data = bf->symbols; +#if 0 g_print ("looking up %p in %s ", address, bf->filename); +#endif if (address < data[last].address) { @@ -418,7 +420,9 @@ bin_file_lookup_symbol (BinFile *bf, result = &data[last]; } +#if 0 g_print ("-> %s\n", result->name); +#endif /* If the name is "call_gmon_start", the file probably doesn't * have any other symbols diff --git a/process.c b/process.c index 9fd29fa7..7461bbfa 100644 --- a/process.c +++ b/process.c @@ -22,7 +22,7 @@ struct Map char * filename; gulong start; gulong end; - gulong offset; + gulong offset; gboolean do_offset; BinFile * bin_file; @@ -34,6 +34,8 @@ struct Process GList *maps; GList *bad_pages; + + int pid; }; static void @@ -68,15 +70,6 @@ should_offset (const char *filename, int pid) return result; } -static gboolean -check_do_offset (const Map *map, int pid) -{ - if (map->filename) - return should_offset (map->filename, pid); - else - return TRUE; -} - static GList * read_maps (int pid) { @@ -99,21 +92,25 @@ read_maps (int pid) guint start; guint end; guint offset; + +#if 0 + g_print ("buffer: %s\n", buffer); +#endif count = sscanf ( - buffer, "%x-%x %*15s %x %*u:%*u %*u %255s", + buffer, "%x-%x %*15s %x %*x:%*x %*u %255s", &start, &end, &offset, file); if (count == 4) { Map *map; - + map = g_new (Map, 1); map->filename = g_strdup (file); map->start = start; map->end = end; - map->offset = offset; //check_do_offset (map, pid); + map->offset = offset; map->bin_file = NULL; @@ -137,6 +134,7 @@ create_process (const char *cmdline, int pid) p->cmdline = g_strdup_printf ("[%s]", cmdline); p->bad_pages = NULL; p->maps = NULL; + p->pid = pid; g_assert (!g_hash_table_lookup (processes_by_pid, GINT_TO_POINTER (pid))); g_assert (!g_hash_table_lookup (processes_by_cmdline, cmdline)); @@ -269,7 +267,7 @@ process_lookup_symbol (Process *process, gulong address) g_free (undefined.name); undefined.name = g_strdup_printf ("??? (%s)", process->cmdline); undefined.address = 0xBABE0001; - + return &undefined; } @@ -282,17 +280,22 @@ process_lookup_symbol (Process *process, gulong address) if (!map->bin_file) map->bin_file = bin_file_new (map->filename); +#if 0 /* FIXME - this seems to work with prelinked binaries, but is * it correct? IE., will normal binaries always have a preferred_addres of 0? */ -/* address = address - map->start + map->offset + bin_file_get_load_address (map->bin_file); */ -/* address -= map->start; */ -/* address += map->offset; */ -/* address += bin_file_get_load_address (map->bin_file); */ + address = address - map->start + map->offset + bin_file_get_load_address (map->bin_file); + address -= map->start; + address += map->offset; + address += bin_file_get_load_address (map->bin_file); +#endif /* g_print ("%s: start: %p, load: %p\n", */ /* map->filename, map->start, bin_file_get_load_address (map->bin_file)); */ + if (should_offset (map->filename, process->pid)) + address -= map->start; + result = bin_file_lookup_symbol (map->bin_file, address); /* g_print ("(%x) %x %x name; %s\n", address, map->start, map->offset, result->name); */ diff --git a/sysprof-module.c b/sysprof-module.c index 7e09b8bc..3ae67df8 100644 --- a/sysprof-module.c +++ b/sysprof-module.c @@ -7,14 +7,13 @@ #include #include /* Needed for KERN_ALERT */ #include /* Needed by all modules */ -#ifdef KERNEL24 -# include -#endif #include + #include #include #include #include +#include #include "sysprof-module.h" @@ -79,13 +78,76 @@ init_userspace_reader (userspace_reader *reader, reader->page = NULL; } +/* Access another process' address space. + * Source/target buffer must be kernel space, + * 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) +{ + struct mm_struct *mm; + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; + + mm = tsk->mm; + if (!mm) + return 0; + + down_read(&mm->mmap_sem); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(tsk, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + flush_cache_page(vma, addr); + + maddr = kmap(page); + if (write) { + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + } + kunmap(page); + page_cache_release(page); + len -= bytes; + buf += bytes; + addr += bytes; + } + up_read(&mm->mmap_sem); + + return buf - old_buf; +} + static int read_user_space (userspace_reader *reader, unsigned long address, unsigned long *result) { +#if 0 unsigned long user_page = (address & PAGE_MASK); int res; +#endif + + return x_access_process_vm(reader->task, address, result, 4, 0); +} +#if 0 + struct task_struct *tsk, unsigned long addr, void *buf, int len, int write); if (user_page == 0) return 0; @@ -93,19 +155,24 @@ read_user_space (userspace_reader *reader, if (!reader->user_page || user_page != reader->user_page) { int found; struct page *page; + pte_t pte; - found = get_user_pages (reader->task, reader->task->mm, user_page, - 1, 0, 0, &page, NULL); + found = get_user_pages (reader->task, reader->task->mm, + user_page, 1, 0, 0, &page, NULL); if (!found) return 0; + if (!pte_present (page)) + return 0; + if (reader->user_page) kunmap (reader->page); - reader->user_page = user_page; reader->kernel_page = (unsigned long)kmap (page); + reader->user_page = user_page; reader->page = page; + } if (get_user (res, (int *)(reader->kernel_page + (address - user_page))) != 0) @@ -115,6 +182,7 @@ read_user_space (userspace_reader *reader, return 1; } +#endif static void done_userspace_reader (userspace_reader *reader) diff --git a/sysprof.c b/sysprof.c index b5f527cc..b25206ad 100644 --- a/sysprof.c +++ b/sysprof.c @@ -110,10 +110,12 @@ on_read (gpointer data) rd = read (app->input_fd, &trace, sizeof (trace)); +#if 0 g_print ("pid: %d\n", trace.pid); for (i=0; i < trace.n_addresses; ++i) g_print ("rd: %08x\n", trace.addresses[i]); g_print ("-=-\n"); +#endif if (rd > 0 && app->profiling && !app->generating_profile) {