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:
Soren Sandmann
2006-10-08 17:45:09 +00:00
committed by Søren Sandmann Pedersen
parent 29a4acaa94
commit c27e5debc5
5 changed files with 154 additions and 39 deletions

View File

@ -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
View File

@ -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:

View File

@ -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;
}

View File

@ -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;

View File

@ -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;