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:
Soren Sandmann
2006-10-09 21:32:24 +00:00
committed by Søren Sandmann Pedersen
parent 4050648b0e
commit b54b0809b6
8 changed files with 190 additions and 55 deletions

View File

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