mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-11 07:30:54 +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>
|
2006-10-08 Soren Sandmann <sandmann@daimi.au.dk>
|
||||||
|
|
||||||
* Delete various debug spew
|
* 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
|
* Consider renaming sysprof-module.[ch] to sysprof.[ch] to move it closer to
|
||||||
kernel naming conventions.
|
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:
|
Before 1.2:
|
||||||
|
|
||||||
* Try reproducing crash when profiling xrender demo
|
|
||||||
|
|
||||||
* Fix (potential) performance issues in symbol lookup.
|
* Fix (potential) performance issues in symbol lookup.
|
||||||
|
|
||||||
* Elf bugs:
|
* 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.
|
- Also error handling for bin_parser is necessary.
|
||||||
|
|
||||||
- Can .gnu_debuglink recurse?
|
- don't loop infinitely if there are cycles in the debuglink graph.
|
||||||
yes, it can, and we should probably not crash if there are
|
|
||||||
cycles in the 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.
|
* Strategies for taking reliable stacktraces.
|
||||||
|
|
||||||
@ -656,6 +652,25 @@ Later:
|
|||||||
|
|
||||||
-=-=-=-=-=-=-=-=-=-=-=-=-=-=- ALREADY DONE -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
|
-=-=-=-=-=-=-=-=-=-=-=-=-=-=- 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
|
* Find out why we are getting bogus symbols reported for /usr/bin/Xorg
|
||||||
Like this:
|
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 const char *const debug_file_directory = "/usr/lib/debug";
|
||||||
|
|
||||||
static ElfParser *
|
static ElfParser *
|
||||||
find_separate_debug_file (ElfParser *elf,
|
get_debug_file (ElfParser *elf,
|
||||||
const char *filename)
|
const char *filename,
|
||||||
|
char **new_name)
|
||||||
{
|
{
|
||||||
const char *basename;
|
const char *basename;
|
||||||
char *dir;
|
char *dir;
|
||||||
@ -104,7 +105,7 @@ find_separate_debug_file (ElfParser *elf,
|
|||||||
basename = elf_parser_get_debug_link (elf, &crc32);
|
basename = elf_parser_get_debug_link (elf, &crc32);
|
||||||
|
|
||||||
if (!basename)
|
if (!basename)
|
||||||
return elf;
|
return NULL;
|
||||||
|
|
||||||
dir = g_path_get_dirname (filename);
|
dir = g_path_get_dirname (filename);
|
||||||
|
|
||||||
@ -116,7 +117,11 @@ find_separate_debug_file (ElfParser *elf,
|
|||||||
{
|
{
|
||||||
result = separate_debug_file_exists (tries[i], crc32);
|
result = separate_debug_file_exists (tries[i], crc32);
|
||||||
if (result)
|
if (result)
|
||||||
|
{
|
||||||
|
if (new_name)
|
||||||
|
*new_name = g_strdup (tries[i]);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (dir);
|
g_free (dir);
|
||||||
@ -124,15 +129,40 @@ find_separate_debug_file (ElfParser *elf,
|
|||||||
for (i = 0; i < 3; ++i)
|
for (i = 0; i < 3; ++i)
|
||||||
g_free (tries[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);
|
debug = get_debug_file (elf, fname, &debug_name);
|
||||||
return result;
|
|
||||||
}
|
if (debug)
|
||||||
else
|
{
|
||||||
{
|
elf_parser_free (elf);
|
||||||
return elf;
|
elf = debug;
|
||||||
|
|
||||||
|
g_free (fname);
|
||||||
|
fname = debug_name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while (debug);
|
||||||
|
|
||||||
|
g_free (fname);
|
||||||
|
|
||||||
|
return elf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GHashTable *bin_files;
|
static GHashTable *bin_files;
|
||||||
@ -163,7 +193,7 @@ bin_file_new (const char *filename)
|
|||||||
if (bf->elf)
|
if (bf->elf)
|
||||||
bf->text_offset = elf_parser_get_text_offset (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->inode = read_inode (filename);
|
||||||
bf->filename = g_strdup (filename);
|
bf->filename = g_strdup (filename);
|
||||||
bf->undefined_name = g_strdup_printf ("In file %s", filename);
|
bf->undefined_name = g_strdup_printf ("In file %s", filename);
|
||||||
@ -210,6 +240,14 @@ bin_file_lookup_symbol (BinFile *bin_file,
|
|||||||
return (const BinSymbol *)sym;
|
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;
|
return (const BinSymbol *)bin_file->undefined_name;
|
||||||
}
|
}
|
||||||
|
|||||||
77
elfparser.c
77
elfparser.c
@ -19,6 +19,7 @@ struct Section
|
|||||||
gsize size;
|
gsize size;
|
||||||
gboolean allocated;
|
gboolean allocated;
|
||||||
gulong load_address;
|
gulong load_address;
|
||||||
|
guint type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ElfParser
|
struct ElfParser
|
||||||
@ -80,6 +81,8 @@ section_new (BinRecord *record,
|
|||||||
else
|
else
|
||||||
section->load_address = 0;
|
section->load_address = 0;
|
||||||
|
|
||||||
|
section->type = bin_record_get_uint (record, "sh_type");
|
||||||
|
|
||||||
return section;
|
return section;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -91,7 +94,8 @@ section_free (Section *section)
|
|||||||
|
|
||||||
static const Section *
|
static const Section *
|
||||||
find_section (ElfParser *parser,
|
find_section (ElfParser *parser,
|
||||||
const char *name)
|
const char *name,
|
||||||
|
guint type)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -103,7 +107,7 @@ find_section (ElfParser *parser,
|
|||||||
{
|
{
|
||||||
Section *section = parser->sections[i];
|
Section *section = parser->sections[i];
|
||||||
|
|
||||||
if (strcmp (section->name, name) == 0)
|
if (strcmp (section->name, name) == 0 && section->type == type)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
g_print ("found it as number %d with offset %d\n", i, section->offset);
|
g_print ("found it as number %d with offset %d\n", i, section->offset);
|
||||||
@ -191,6 +195,10 @@ elf_parser_new (const char *filename,
|
|||||||
if (!file)
|
if (!file)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("elf parser new : %s\n", filename);
|
||||||
|
#endif
|
||||||
|
|
||||||
data = (guchar *)g_mapped_file_get_contents (file);
|
data = (guchar *)g_mapped_file_get_contents (file);
|
||||||
length = g_mapped_file_get_length (file);
|
length = g_mapped_file_get_length (file);
|
||||||
|
|
||||||
@ -200,6 +208,11 @@ elf_parser_new (const char *filename,
|
|||||||
|
|
||||||
parser = parser_new_from_data (data, length);
|
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;
|
parser->file = file;
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
@ -370,15 +383,29 @@ read_table (ElfParser *parser,
|
|||||||
{
|
{
|
||||||
guint info;
|
guint info;
|
||||||
gulong addr;
|
gulong addr;
|
||||||
const char *name;
|
|
||||||
gulong offset;
|
gulong offset;
|
||||||
|
#if 0
|
||||||
|
const char *name;
|
||||||
|
#endif
|
||||||
|
|
||||||
bin_record_index (symbol, i);
|
bin_record_index (symbol, i);
|
||||||
|
|
||||||
info = bin_record_get_uint (symbol, "st_info");
|
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");
|
addr = bin_record_get_uint (symbol, "st_value");
|
||||||
|
#if 0
|
||||||
name = bin_record_get_string_indirect (symbol, "st_name",
|
name = bin_record_get_string_indirect (symbol, "st_name",
|
||||||
str_table->offset);
|
str_table->offset);
|
||||||
|
#endif
|
||||||
offset = bin_record_get_offset (symbol);
|
offset = bin_record_get_offset (symbol);
|
||||||
|
|
||||||
if (addr != 0 &&
|
if (addr != 0 &&
|
||||||
@ -389,10 +416,22 @@ read_table (ElfParser *parser,
|
|||||||
parser->symbols[n_functions].address = addr;
|
parser->symbols[n_functions].address = addr;
|
||||||
parser->symbols[n_functions].offset = offset;
|
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++;
|
n_functions++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
g_print ("%d functions found \n", n_functions);
|
||||||
|
#endif
|
||||||
|
|
||||||
bin_record_free (symbol);
|
bin_record_free (symbol);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
@ -413,10 +452,10 @@ read_table (ElfParser *parser,
|
|||||||
static void
|
static void
|
||||||
read_symbols (ElfParser *parser)
|
read_symbols (ElfParser *parser)
|
||||||
{
|
{
|
||||||
const Section *symtab = find_section (parser, ".symtab");
|
const Section *symtab = find_section (parser, ".symtab", SHT_SYMTAB);
|
||||||
const Section *strtab = find_section (parser, ".strtab");
|
const Section *strtab = find_section (parser, ".strtab", SHT_STRTAB);
|
||||||
const Section *dynsym = find_section (parser, ".dynsym");
|
const Section *dynsym = find_section (parser, ".dynsym", SHT_SYMTAB);
|
||||||
const Section *dynstr = find_section (parser, ".dynstr");
|
const Section *dynstr = find_section (parser, ".dynstr", SHT_STRTAB);
|
||||||
|
|
||||||
if (symtab && strtab)
|
if (symtab && strtab)
|
||||||
{
|
{
|
||||||
@ -513,9 +552,13 @@ elf_parser_lookup_symbol (ElfParser *parser,
|
|||||||
if (parser->n_symbols == 0)
|
if (parser->n_symbols == 0)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
text = find_section (parser, ".text");
|
text = find_section (parser, ".text", SHT_PROGBITS);
|
||||||
if (!text)
|
if (!text)
|
||||||
return NULL;
|
{
|
||||||
|
text = find_section (parser, ".text", SHT_NOBITS);
|
||||||
|
if (!text)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
address += text->load_address;
|
address += text->load_address;
|
||||||
|
|
||||||
@ -558,10 +601,14 @@ elf_parser_get_text_offset (ElfParser *parser)
|
|||||||
|
|
||||||
g_return_val_if_fail (parser != NULL, (gulong)-1);
|
g_return_val_if_fail (parser != NULL, (gulong)-1);
|
||||||
|
|
||||||
text = find_section (parser, ".text");
|
text = find_section (parser, ".text", SHT_PROGBITS);
|
||||||
|
|
||||||
if (!text)
|
if (!text)
|
||||||
return (gulong)-1;
|
{
|
||||||
|
text = find_section (parser, ".text", SHT_NOBITS);
|
||||||
|
if (!text)
|
||||||
|
return (gulong)-1;
|
||||||
|
}
|
||||||
|
|
||||||
return text->offset;
|
return text->offset;
|
||||||
}
|
}
|
||||||
@ -569,7 +616,8 @@ elf_parser_get_text_offset (ElfParser *parser)
|
|||||||
const char *
|
const char *
|
||||||
elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
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;
|
const gchar *result;
|
||||||
|
|
||||||
if (!debug_link)
|
if (!debug_link)
|
||||||
@ -581,7 +629,8 @@ elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
|||||||
|
|
||||||
bin_parser_align (parser->parser, 4);
|
bin_parser_align (parser->parser, 4);
|
||||||
|
|
||||||
*crc32 = bin_parser_get_uint32 (parser->parser);
|
if (crc32)
|
||||||
|
*crc32 = bin_parser_get_uint32 (parser->parser);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -589,7 +638,7 @@ elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
|||||||
const guchar *
|
const guchar *
|
||||||
elf_parser_get_eh_frame (ElfParser *parser)
|
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)
|
if (eh_frame)
|
||||||
return bin_parser_get_data (parser->parser) + eh_frame->offset;
|
return bin_parser_get_data (parser->parser) + eh_frame->offset;
|
||||||
|
|||||||
@ -586,6 +586,11 @@ process_lookup_symbol (Process *process, gulong address)
|
|||||||
g_print ("address before: \n");
|
g_print ("address before: \n");
|
||||||
#endif
|
#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->start;
|
||||||
address += map->offset;
|
address += map->offset;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user