mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
New function.
2006-10-09 Soren Sandmann <ssp@localhost.localdomain> * process.c (process_get_vdso_bytes): New function. * elfparser.c (parser_new_from_data): export this function as elf_parser_new_from_data(). * binfile.c (read_inode): Don't stat if filename is '[vdso]'. Instead just return -1; (bin_file_new): Use elf_parser_new_from_data() when the file is [vdso]. * process.c (read_maps): Change the offset of the vdso map to 0 and the inode to -1. * elfparser.c (elf_parser_lookup_symbol): Remove unused 'size' variable. * binfile.c (find_separate_debug_file): Deal with cycles in the debuglink graph. * configure.ac: Set version to 1.1.0. Print warning about HEAD.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
4050648b0e
commit
b54b0809b6
25
ChangeLog
25
ChangeLog
@ -1,4 +1,27 @@
|
||||
2006-10-08 Soren Sandmann <sandmann@daimi.au.dk>
|
||||
2006-10-09 Soren Sandmann <ssp@localhost.localdomain>
|
||||
|
||||
* process.c (process_get_vdso_bytes): New function.
|
||||
|
||||
* elfparser.c (parser_new_from_data): export this function as
|
||||
elf_parser_new_from_data().
|
||||
|
||||
* binfile.c (read_inode): Don't stat if filename is
|
||||
'[vdso]'. Instead just return -1;
|
||||
(bin_file_new): Use elf_parser_new_from_data() when the file is
|
||||
[vdso].
|
||||
|
||||
* process.c (read_maps): Change the offset of the vdso map to 0
|
||||
and the inode to -1.
|
||||
|
||||
* elfparser.c (elf_parser_lookup_symbol): Remove unused 'size'
|
||||
variable.
|
||||
|
||||
* binfile.c (find_separate_debug_file): Deal with cycles in the
|
||||
debuglink graph.
|
||||
|
||||
* configure.ac: Set version to 1.1.0. Print warning about HEAD.
|
||||
|
||||
2006-10-08 Soren Sandmann <ssp@localhost.localdomain>
|
||||
|
||||
* binfile.c: Don't include bfd.h
|
||||
|
||||
|
||||
16
TODO
16
TODO
@ -37,11 +37,16 @@ Before 1.2:
|
||||
* Elf bugs:
|
||||
- error handling for bin_parser is necessary.
|
||||
|
||||
- don't loop infinitely if there are cycles in the debuglink graph.
|
||||
|
||||
* Find out why all apps have an "In file /usr/bin/<app binary>" below
|
||||
_libc_main. If possible, maybe make up a name for it.
|
||||
|
||||
* vdso stuff:
|
||||
- the "[vdso]" string should be #defined somewhere
|
||||
- Does get_vdso_bytes() belong in process.c?
|
||||
- Is basing on "[vdso]" always correct?
|
||||
|
||||
* Convert things like [heap] and [stack] to more understandable labels.
|
||||
|
||||
* Strategies for taking reliable stacktraces.
|
||||
|
||||
Three different kinds of files
|
||||
@ -64,6 +69,7 @@ Before 1.2:
|
||||
- vdso
|
||||
- assume its the same across processes, just look at
|
||||
sysprof's own copy.
|
||||
Done: vdso is done now
|
||||
- send copy of it to userspace once, or for every
|
||||
sample.
|
||||
|
||||
@ -154,8 +160,6 @@ Before 1.2:
|
||||
|
||||
* Make it compile and work on x86-64
|
||||
|
||||
* Add "sysprof --version"
|
||||
|
||||
* With kernel module not installed, select Profiler->Start, then dismiss
|
||||
the alert. This causes the start button to appear prelighted. Probably
|
||||
just another gtk+ bug.
|
||||
@ -652,6 +656,10 @@ Later:
|
||||
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ALREADY DONE -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
* don't loop infinitely if there are cycles in the debuglink graph.
|
||||
|
||||
* Add "sysprof --version"
|
||||
|
||||
* Fix (potential) performance issues in symbol lookup.
|
||||
|
||||
- when an elf file is read, it should be checked that the various
|
||||
|
||||
80
binfile.c
80
binfile.c
@ -23,9 +23,9 @@
|
||||
/* Most interesting code in this file is lifted from bfdutils.c
|
||||
* and process.c from Memprof,
|
||||
*/
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
#include "binfile.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
@ -33,7 +33,10 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "binfile.h"
|
||||
#include "elfparser.h"
|
||||
#include "process.h"
|
||||
|
||||
struct BinFile
|
||||
{
|
||||
@ -54,9 +57,11 @@ static ino_t
|
||||
read_inode (const char *filename)
|
||||
{
|
||||
struct stat statbuf;
|
||||
|
||||
|
||||
if (strcmp (filename, "[vdso]") == 0)
|
||||
return (ino_t)-1;
|
||||
|
||||
stat (filename, &statbuf);
|
||||
|
||||
return statbuf.st_ino;
|
||||
}
|
||||
|
||||
@ -84,7 +89,7 @@ separate_debug_file_exists (const char *name, guint32 crc)
|
||||
}
|
||||
|
||||
/* FIXME - not10: this should probably be detected by config.h -- find out what gdb does*/
|
||||
static const char *const debug_file_directory = "/usr/lib/debug";
|
||||
static const char *const debug_file_directory = DEBUGDIR;
|
||||
|
||||
static ElfParser *
|
||||
get_debug_file (ElfParser *elf,
|
||||
@ -131,6 +136,21 @@ get_debug_file (ElfParser *elf,
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
list_contains_name (GList *names, const char *name)
|
||||
{
|
||||
GList *list;
|
||||
for (list = names; list != NULL; list = list->next)
|
||||
{
|
||||
const char *n = list->data;
|
||||
|
||||
if (strcmp (n, name) == 0)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static ElfParser *
|
||||
find_separate_debug_file (ElfParser *elf,
|
||||
const char *filename)
|
||||
@ -138,29 +158,35 @@ find_separate_debug_file (ElfParser *elf,
|
||||
ElfParser *debug;
|
||||
char *debug_name = NULL;
|
||||
char *fname;
|
||||
GList *seen_names = NULL;
|
||||
|
||||
fname = g_strdup (filename);
|
||||
|
||||
/* FIXME: there is an infinite loop if there are cycles in
|
||||
* the debug_link graph
|
||||
*/
|
||||
do
|
||||
{
|
||||
if (list_contains_name (seen_names, fname))
|
||||
{
|
||||
/* cycle detected, just return the original elf file itself */
|
||||
break;
|
||||
}
|
||||
|
||||
debug = get_debug_file (elf, fname, &debug_name);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
elf_parser_free (elf);
|
||||
elf = debug;
|
||||
|
||||
g_free (fname);
|
||||
|
||||
seen_names = g_list_prepend (seen_names, fname);
|
||||
fname = debug_name;
|
||||
}
|
||||
}
|
||||
while (debug);
|
||||
|
||||
g_free (fname);
|
||||
|
||||
g_list_foreach (seen_names, (GFunc)g_free, NULL);
|
||||
g_list_free (seen_names);
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
@ -184,15 +210,38 @@ bin_file_new (const char *filename)
|
||||
else
|
||||
{
|
||||
bf = g_new0 (BinFile, 1);
|
||||
bf->elf = elf_parser_new (filename, NULL);
|
||||
|
||||
if (strcmp (filename, "[vdso]") == 0)
|
||||
{
|
||||
gsize length;
|
||||
const guint8 *vdso_bytes;
|
||||
|
||||
vdso_bytes = process_get_vdso_bytes (&length);
|
||||
if (vdso_bytes)
|
||||
{
|
||||
bf->elf = elf_parser_new_from_data (vdso_bytes, length);
|
||||
#if 0
|
||||
g_print ("got vdso elf: %p (%d)\n", bf->elf, length);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
bf->elf = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
bf->elf = elf_parser_new (filename, NULL);
|
||||
}
|
||||
|
||||
/* We need the text offset of the actual binary, not the
|
||||
* (potential) debug binary
|
||||
*/
|
||||
if (bf->elf)
|
||||
{
|
||||
bf->text_offset = elf_parser_get_text_offset (bf->elf);
|
||||
|
||||
#if 0
|
||||
g_print ("text offset: %d\n", bf->text_offset);
|
||||
#endif
|
||||
|
||||
bf->elf = find_separate_debug_file (bf->elf, filename);
|
||||
}
|
||||
|
||||
@ -200,7 +249,7 @@ bin_file_new (const char *filename)
|
||||
bf->filename = g_strdup (filename);
|
||||
bf->undefined_name = g_strdup_printf ("In file %s", filename);
|
||||
bf->ref_count = 1;
|
||||
|
||||
|
||||
g_hash_table_insert (bin_files, bf->filename, bf);
|
||||
}
|
||||
|
||||
@ -229,12 +278,15 @@ bin_file_lookup_symbol (BinFile *bin_file,
|
||||
{
|
||||
if (bin_file->elf)
|
||||
{
|
||||
#if 0
|
||||
g_print ("bin file lookup lookup %d\n", address);
|
||||
#endif
|
||||
address -= bin_file->text_offset;
|
||||
|
||||
const ElfSym *sym = elf_parser_lookup_symbol (bin_file->elf, address);
|
||||
|
||||
#if 0
|
||||
g_print ("lookup in %s\n", bin_file->filename);
|
||||
g_print ("lookup %d in %s\n", address, bin_file->filename);
|
||||
#endif
|
||||
|
||||
if (sym)
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
AC_PREREQ(2.54)
|
||||
|
||||
AC_INIT([sysprof], [1.1.0.snap071806])
|
||||
AC_INIT([sysprof], [1.1.0])
|
||||
AC_CONFIG_SRCDIR(sysprof.glade)
|
||||
|
||||
AM_INIT_AUTOMAKE(no-define)
|
||||
@ -105,7 +105,7 @@ Makefile
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
if false; then
|
||||
if true; then
|
||||
echo
|
||||
echo "%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%@%"
|
||||
echo "@"
|
||||
@ -114,7 +114,7 @@ if false; then
|
||||
echo "% There are currently no known bugs in the kernel"
|
||||
echo "@ module in this version, but there could easily be"
|
||||
echo "% unknown ones. Please report any crashes or lockups"
|
||||
echo "@ that you experience."
|
||||
echo "@ that you experience to sandmann@daimi.au.dk."
|
||||
echo "%"
|
||||
echo "@"
|
||||
echo "% If you need a stable version of sysprof, either"
|
||||
|
||||
@ -126,8 +126,9 @@ find_section (ElfParser *parser,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static ElfParser *
|
||||
parser_new_from_data (const guchar *data, gsize length)
|
||||
ElfParser *
|
||||
elf_parser_new_from_data (const guchar *data,
|
||||
gsize length)
|
||||
{
|
||||
ElfParser *parser;
|
||||
gboolean is_64, is_big_endian;
|
||||
@ -214,7 +215,7 @@ elf_parser_new (const char *filename,
|
||||
g_print ("data %p: for %s\n", data, filename);
|
||||
#endif
|
||||
|
||||
parser = parser_new_from_data (data, length);
|
||||
parser = elf_parser_new_from_data (data, length);
|
||||
|
||||
if (!parser)
|
||||
{
|
||||
@ -550,7 +551,6 @@ elf_parser_lookup_symbol (ElfParser *parser,
|
||||
gulong address)
|
||||
{
|
||||
const ElfSym *result;
|
||||
gsize size;
|
||||
|
||||
if (!parser->symbols)
|
||||
read_symbols (parser);
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
typedef struct ElfSym ElfSym;
|
||||
typedef struct ElfParser ElfParser;
|
||||
|
||||
ElfParser * elf_parser_new_from_data (const guchar *data,
|
||||
gsize length);
|
||||
ElfParser * elf_parser_new (const char *filename,
|
||||
GError **err);
|
||||
void elf_parser_free (ElfParser *parser);
|
||||
|
||||
107
process.c
107
process.c
@ -25,6 +25,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "process.h"
|
||||
#include "binfile.h"
|
||||
@ -115,10 +116,24 @@ read_maps (int pid)
|
||||
map->start = start;
|
||||
map->end = end;
|
||||
|
||||
map->offset = offset;
|
||||
if (strcmp (map->filename, "[vdso]") == 0)
|
||||
{
|
||||
/* The kernel reports offset the same as the
|
||||
* mapping address, which doesn't make much sense
|
||||
* to me. So just zero it out here
|
||||
*/
|
||||
#if 0
|
||||
g_print ("fixing up\n");
|
||||
#endif
|
||||
map->offset = 0;
|
||||
map->inode = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
map->offset = offset;
|
||||
map->inode = inode;
|
||||
}
|
||||
|
||||
map->inode = inode;
|
||||
|
||||
map->bin_file = NULL;
|
||||
|
||||
result = g_list_prepend (result, map);
|
||||
@ -136,6 +151,61 @@ read_maps (int pid)
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
free_maps (GList *maps)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = maps; list != NULL; list = list->next)
|
||||
{
|
||||
Map *map = list->data;
|
||||
|
||||
if (map->filename)
|
||||
g_free (map->filename);
|
||||
|
||||
if (map->bin_file)
|
||||
bin_file_free (map->bin_file);
|
||||
|
||||
g_free (map);
|
||||
}
|
||||
|
||||
g_list_free (maps);
|
||||
}
|
||||
|
||||
const guint8 *
|
||||
process_get_vdso_bytes (gsize *length)
|
||||
{
|
||||
static gboolean has_data;
|
||||
static const guint8 *bytes = NULL;
|
||||
static gsize n_bytes = 0;
|
||||
|
||||
if (!has_data)
|
||||
{
|
||||
GList *maps = read_maps (getpid());
|
||||
GList *list;
|
||||
|
||||
for (list = maps; list != NULL; list = list->next)
|
||||
{
|
||||
Map *map = list->data;
|
||||
|
||||
if (strcmp (map->filename, "[vdso]") == 0)
|
||||
{
|
||||
bytes = (guint8 *)map->start;
|
||||
n_bytes = map->end - map->start;
|
||||
}
|
||||
}
|
||||
|
||||
has_data = TRUE;
|
||||
free_maps (maps);
|
||||
}
|
||||
|
||||
if (length)
|
||||
*length = n_bytes;
|
||||
|
||||
g_print ("the vdso is %p\n", bytes);
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static Process *
|
||||
create_process (const char *cmdline, int pid)
|
||||
@ -182,28 +252,6 @@ process_locate_map (Process *process, gulong addr)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
process_free_maps (Process *process)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
for (list = process->maps; list != NULL; list = list->next)
|
||||
{
|
||||
Map *map = list->data;
|
||||
|
||||
if (map->filename)
|
||||
g_free (map->filename);
|
||||
|
||||
if (map->bin_file)
|
||||
bin_file_free (map->bin_file);
|
||||
|
||||
g_free (map);
|
||||
}
|
||||
|
||||
g_list_free (process->maps);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
free_process (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
@ -218,7 +266,7 @@ free_process (gpointer key, gpointer value, gpointer data)
|
||||
#if 0
|
||||
process->cmdline = "You are using free()'d memory";
|
||||
#endif
|
||||
process_free_maps (process);
|
||||
free_maps (process->maps);
|
||||
g_list_free (process->bad_pages);
|
||||
g_free (cmdline);
|
||||
|
||||
@ -265,7 +313,7 @@ process_ensure_map (Process *process, int pid, gulong addr)
|
||||
|
||||
/* a map containing addr was not found */
|
||||
if (process->maps)
|
||||
process_free_maps (process);
|
||||
free_maps (process->maps);
|
||||
|
||||
process->maps = read_maps (pid);
|
||||
|
||||
@ -600,7 +648,7 @@ process_lookup_symbol (Process *process, gulong address)
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
if (strcmp (map->filename, "/home/ssp/sysprof/sysprof") == 0)
|
||||
if (strcmp (map->filename, "[vdso]") == 0)
|
||||
{
|
||||
g_print ("address after: %lx\n", address);
|
||||
}
|
||||
@ -618,7 +666,8 @@ process_lookup_symbol (Process *process, gulong address)
|
||||
* file has changed since the process started. Just return
|
||||
* the undefined symbol in that case.
|
||||
*/
|
||||
|
||||
g_print ("warning: %s has wrong inode (%d, should be %d)\n",
|
||||
map->filename, map->inode, bin_file_get_inode (map->bin_file));
|
||||
address = 0x0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user