mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2025-12-31 20:36:25 +00:00
Support _debuglink recursions.
2006-10-08 Soren Sandmann <sandmann@daimi.au.dk> * binfile.c (find_separate_debug_file): Support _debuglink recursions. * elfparser.c: Check that the sections have valid types before using them.
This commit is contained in:
committed by
Søren Sandmann Pedersen
parent
29a4acaa94
commit
c27e5debc5
@ -1,3 +1,11 @@
|
||||
2006-10-08 Soren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* binfile.c (find_separate_debug_file): Support _debuglink
|
||||
recursions.
|
||||
|
||||
* elfparser.c: Check that the sections have valid types before
|
||||
using them.
|
||||
|
||||
2006-10-08 Soren Sandmann <sandmann@daimi.au.dk>
|
||||
|
||||
* Delete various debug spew
|
||||
|
||||
37
TODO
37
TODO
@ -28,25 +28,21 @@ Before 1.0.4:
|
||||
* Consider renaming sysprof-module.[ch] to sysprof.[ch] to move it closer to
|
||||
kernel naming conventions.
|
||||
|
||||
* Get rid of include of "../config.h" as that won't work in the kernel.
|
||||
* Get rid of include of "../config.h" as that won't work in the latest
|
||||
kernel. done in HEAD, need to check what if anything breaks with older
|
||||
kernels.
|
||||
|
||||
Before 1.2:
|
||||
|
||||
* Try reproducing crash when profiling xrender demo
|
||||
|
||||
* Fix (potential) performance issues in symbol lookup.
|
||||
|
||||
* Elf bugs:
|
||||
|
||||
- when an elf file is read, it should be checked that the various
|
||||
sections are of the right type. For example the debug information
|
||||
for emacs is just a stub file where all the sections are NOBITS.
|
||||
|
||||
- Also error handling for bin_parser is necessary.
|
||||
|
||||
- Can .gnu_debuglink recurse?
|
||||
yes, it can, and we should probably not crash if there are
|
||||
cycles in the graph.
|
||||
- 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.
|
||||
|
||||
* Strategies for taking reliable stacktraces.
|
||||
|
||||
@ -656,6 +652,25 @@ Later:
|
||||
|
||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ALREADY DONE -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
||||
|
||||
|
||||
- when an elf file is read, it should be checked that the various
|
||||
sections are of the right type. For example the debug information
|
||||
for emacs is just a stub file where all the sections are NOBITS.
|
||||
|
||||
* Try reproducing crash when profiling xrender demo
|
||||
- it looks like it crashes when it attempts to read /usr/bin/python
|
||||
- apparently what's going on is that one of the symbols in python's
|
||||
dynamic symbol table has a completely crazy 'st_name' offset.
|
||||
DONE: we didn't actually need to read the name at all,
|
||||
but still should find out why that value is so weird.
|
||||
It looks like there is something strange going on with that file.
|
||||
All the dynsyms have weird info/type values, yet nm and readelf
|
||||
have no problems displaying it.
|
||||
|
||||
- Can .gnu_debuglink recurse?
|
||||
yes, it can, and we should probably not crash if there are
|
||||
cycles in the graph.
|
||||
|
||||
* Find out why we are getting bogus symbols reported for /usr/bin/Xorg
|
||||
Like this:
|
||||
|
||||
|
||||
60
binfile.c
60
binfile.c
@ -88,8 +88,9 @@ separate_debug_file_exists (const char *name, guint32 crc)
|
||||
static const char *const debug_file_directory = "/usr/lib/debug";
|
||||
|
||||
static ElfParser *
|
||||
find_separate_debug_file (ElfParser *elf,
|
||||
const char *filename)
|
||||
get_debug_file (ElfParser *elf,
|
||||
const char *filename,
|
||||
char **new_name)
|
||||
{
|
||||
const char *basename;
|
||||
char *dir;
|
||||
@ -104,7 +105,7 @@ find_separate_debug_file (ElfParser *elf,
|
||||
basename = elf_parser_get_debug_link (elf, &crc32);
|
||||
|
||||
if (!basename)
|
||||
return elf;
|
||||
return NULL;
|
||||
|
||||
dir = g_path_get_dirname (filename);
|
||||
|
||||
@ -116,7 +117,11 @@ find_separate_debug_file (ElfParser *elf,
|
||||
{
|
||||
result = separate_debug_file_exists (tries[i], crc32);
|
||||
if (result)
|
||||
{
|
||||
if (new_name)
|
||||
*new_name = g_strdup (tries[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_free (dir);
|
||||
@ -124,15 +129,40 @@ find_separate_debug_file (ElfParser *elf,
|
||||
for (i = 0; i < 3; ++i)
|
||||
g_free (tries[i]);
|
||||
|
||||
if (result)
|
||||
return result;
|
||||
}
|
||||
|
||||
static ElfParser *
|
||||
find_separate_debug_file (ElfParser *elf,
|
||||
const char *filename)
|
||||
{
|
||||
ElfParser *debug;
|
||||
char *debug_name = NULL;
|
||||
char *fname;
|
||||
|
||||
fname = g_strdup (filename);
|
||||
|
||||
/* FIXME: there is an infinite loop if there are cycles in
|
||||
* the debug_link graph
|
||||
*/
|
||||
do
|
||||
{
|
||||
elf_parser_free (elf);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
return elf;
|
||||
debug = get_debug_file (elf, fname, &debug_name);
|
||||
|
||||
if (debug)
|
||||
{
|
||||
elf_parser_free (elf);
|
||||
elf = debug;
|
||||
|
||||
g_free (fname);
|
||||
fname = debug_name;
|
||||
}
|
||||
}
|
||||
while (debug);
|
||||
|
||||
g_free (fname);
|
||||
|
||||
return elf;
|
||||
}
|
||||
|
||||
static GHashTable *bin_files;
|
||||
@ -163,7 +193,7 @@ bin_file_new (const char *filename)
|
||||
if (bf->elf)
|
||||
bf->text_offset = elf_parser_get_text_offset (bf->elf);
|
||||
|
||||
bf->elf = find_separate_debug_file (bf->elf, filename);
|
||||
bf->elf = find_separate_debug_file (bf->elf, filename); /* find_separate_debug_file (bf->elf, filename); */
|
||||
bf->inode = read_inode (filename);
|
||||
bf->filename = g_strdup (filename);
|
||||
bf->undefined_name = g_strdup_printf ("In file %s", filename);
|
||||
@ -210,7 +240,15 @@ bin_file_lookup_symbol (BinFile *bin_file,
|
||||
return (const BinSymbol *)sym;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
g_print ("no elf file for %s\n", bin_file->filename);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
g_print ("%lx undefined in %s (textoffset %d)\n", address + bin_file->text_offset, bin_file->filename, bin_file->text_offset);
|
||||
#endif
|
||||
|
||||
return (const BinSymbol *)bin_file->undefined_name;
|
||||
}
|
||||
|
||||
|
||||
83
elfparser.c
83
elfparser.c
@ -19,6 +19,7 @@ struct Section
|
||||
gsize size;
|
||||
gboolean allocated;
|
||||
gulong load_address;
|
||||
guint type;
|
||||
};
|
||||
|
||||
struct ElfParser
|
||||
@ -79,7 +80,9 @@ section_new (BinRecord *record,
|
||||
section->load_address = bin_record_get_uint (record, "sh_addr");
|
||||
else
|
||||
section->load_address = 0;
|
||||
|
||||
|
||||
section->type = bin_record_get_uint (record, "sh_type");
|
||||
|
||||
return section;
|
||||
}
|
||||
|
||||
@ -91,7 +94,8 @@ section_free (Section *section)
|
||||
|
||||
static const Section *
|
||||
find_section (ElfParser *parser,
|
||||
const char *name)
|
||||
const char *name,
|
||||
guint type)
|
||||
{
|
||||
int i;
|
||||
|
||||
@ -103,7 +107,7 @@ find_section (ElfParser *parser,
|
||||
{
|
||||
Section *section = parser->sections[i];
|
||||
|
||||
if (strcmp (section->name, name) == 0)
|
||||
if (strcmp (section->name, name) == 0 && section->type == type)
|
||||
{
|
||||
#if 0
|
||||
g_print ("found it as number %d with offset %d\n", i, section->offset);
|
||||
@ -190,6 +194,10 @@ elf_parser_new (const char *filename,
|
||||
|
||||
if (!file)
|
||||
return NULL;
|
||||
|
||||
#if 0
|
||||
g_print ("elf parser new : %s\n", filename);
|
||||
#endif
|
||||
|
||||
data = (guchar *)g_mapped_file_get_contents (file);
|
||||
length = g_mapped_file_get_length (file);
|
||||
@ -197,9 +205,14 @@ elf_parser_new (const char *filename,
|
||||
#if 0
|
||||
g_print ("data %p: for %s\n", data, filename);
|
||||
#endif
|
||||
|
||||
|
||||
parser = parser_new_from_data (data, length);
|
||||
|
||||
#if 0
|
||||
g_print ("Elf file: %s (debug: %s)\n",
|
||||
filename, elf_parser_get_debug_link (parser, NULL));
|
||||
#endif
|
||||
|
||||
parser->file = file;
|
||||
|
||||
return parser;
|
||||
@ -370,15 +383,29 @@ read_table (ElfParser *parser,
|
||||
{
|
||||
guint info;
|
||||
gulong addr;
|
||||
const char *name;
|
||||
gulong offset;
|
||||
|
||||
#if 0
|
||||
const char *name;
|
||||
#endif
|
||||
|
||||
bin_record_index (symbol, i);
|
||||
|
||||
info = bin_record_get_uint (symbol, "st_info");
|
||||
|
||||
#if 0
|
||||
g_print ("info: %d => %d %d\n", info, info & 0xf, info >> 4);
|
||||
#endif
|
||||
#if 0
|
||||
g_print ("func: %d global %d local: %d\n", STT_FUNC, STB_GLOBAL, STB_LOCAL);
|
||||
#endif
|
||||
#if 0
|
||||
g_print ("%d, name off: %d\n", i, bin_record_get_uint (symbol, "st_name"));
|
||||
#endif
|
||||
addr = bin_record_get_uint (symbol, "st_value");
|
||||
#if 0
|
||||
name = bin_record_get_string_indirect (symbol, "st_name",
|
||||
str_table->offset);
|
||||
#endif
|
||||
offset = bin_record_get_offset (symbol);
|
||||
|
||||
if (addr != 0 &&
|
||||
@ -388,10 +415,22 @@ read_table (ElfParser *parser,
|
||||
{
|
||||
parser->symbols[n_functions].address = addr;
|
||||
parser->symbols[n_functions].offset = offset;
|
||||
|
||||
#if 0
|
||||
g_print ("name: %s\n",
|
||||
bin_record_get_string_indirect (symbol, "st_name",
|
||||
str_table->offset));
|
||||
|
||||
g_print ("%lx\n", parser->symbols[n_functions].address);
|
||||
#endif
|
||||
|
||||
n_functions++;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
g_print ("%d functions found \n", n_functions);
|
||||
#endif
|
||||
|
||||
bin_record_free (symbol);
|
||||
|
||||
@ -413,10 +452,10 @@ read_table (ElfParser *parser,
|
||||
static void
|
||||
read_symbols (ElfParser *parser)
|
||||
{
|
||||
const Section *symtab = find_section (parser, ".symtab");
|
||||
const Section *strtab = find_section (parser, ".strtab");
|
||||
const Section *dynsym = find_section (parser, ".dynsym");
|
||||
const Section *dynstr = find_section (parser, ".dynstr");
|
||||
const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB);
|
||||
const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB);
|
||||
const Section *dynsym = find_section (parser, ".dynsym", SHT_SYMTAB);
|
||||
const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB);
|
||||
|
||||
if (symtab && strtab)
|
||||
{
|
||||
@ -513,9 +552,13 @@ elf_parser_lookup_symbol (ElfParser *parser,
|
||||
if (parser->n_symbols == 0)
|
||||
return NULL;
|
||||
|
||||
text = find_section (parser, ".text");
|
||||
text = find_section (parser, ".text", SHT_PROGBITS);
|
||||
if (!text)
|
||||
return NULL;
|
||||
{
|
||||
text = find_section (parser, ".text", SHT_NOBITS);
|
||||
if (!text)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
address += text->load_address;
|
||||
|
||||
@ -558,10 +601,14 @@ elf_parser_get_text_offset (ElfParser *parser)
|
||||
|
||||
g_return_val_if_fail (parser != NULL, (gulong)-1);
|
||||
|
||||
text = find_section (parser, ".text");
|
||||
text = find_section (parser, ".text", SHT_PROGBITS);
|
||||
|
||||
if (!text)
|
||||
return (gulong)-1;
|
||||
{
|
||||
text = find_section (parser, ".text", SHT_NOBITS);
|
||||
if (!text)
|
||||
return (gulong)-1;
|
||||
}
|
||||
|
||||
return text->offset;
|
||||
}
|
||||
@ -569,7 +616,8 @@ elf_parser_get_text_offset (ElfParser *parser)
|
||||
const char *
|
||||
elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
||||
{
|
||||
const Section *debug_link = find_section (parser, ".gnu_debuglink");
|
||||
const Section *debug_link = find_section (parser, ".gnu_debuglink",
|
||||
SHT_PROGBITS);
|
||||
const gchar *result;
|
||||
|
||||
if (!debug_link)
|
||||
@ -581,7 +629,8 @@ elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
||||
|
||||
bin_parser_align (parser->parser, 4);
|
||||
|
||||
*crc32 = bin_parser_get_uint32 (parser->parser);
|
||||
if (crc32)
|
||||
*crc32 = bin_parser_get_uint32 (parser->parser);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -589,7 +638,7 @@ elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
||||
const guchar *
|
||||
elf_parser_get_eh_frame (ElfParser *parser)
|
||||
{
|
||||
const Section *eh_frame = find_section (parser, ".eh_frame");
|
||||
const Section *eh_frame = find_section (parser, ".eh_frame", SHT_PROGBITS);
|
||||
|
||||
if (eh_frame)
|
||||
return bin_parser_get_data (parser->parser) + eh_frame->offset;
|
||||
|
||||
@ -585,6 +585,11 @@ process_lookup_symbol (Process *process, gulong address)
|
||||
|
||||
g_print ("address before: \n");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
g_print ("%s is mapped at %lx + %lx\n", map->filename, map->start, map->offset);
|
||||
g_print ("incoming address: %lx\n", address);
|
||||
#endif
|
||||
|
||||
address -= map->start;
|
||||
address += map->offset;
|
||||
|
||||
Reference in New Issue
Block a user