mirror of
https://github.com/varun-r-mallya/sysprof.git
synced 2026-02-12 16:10:54 +00:00
Initial build id support
svn path=/trunk/; revision=410
This commit is contained in:
@ -1,3 +1,7 @@
|
|||||||
|
Sun Apr 20 16:55:47 2008 Søren Sandmann <sandmann@redhat.com>
|
||||||
|
|
||||||
|
* elfparser.c (elf_parser_new_from_data): Initial build-id support
|
||||||
|
|
||||||
2008-04-01 Owen Taylor <otaylor@redhat.com>
|
2008-04-01 Owen Taylor <otaylor@redhat.com>
|
||||||
|
|
||||||
* sysprof.c (on_samples_label_size_request): Constrain the
|
* sysprof.c (on_samples_label_size_request): Constrain the
|
||||||
|
|||||||
3
TODO
3
TODO
@ -169,6 +169,9 @@ Before 1.2:
|
|||||||
- "native endian" is probably not useful. Maybe go back to just
|
- "native endian" is probably not useful. Maybe go back to just
|
||||||
having big/little endian.
|
having big/little endian.
|
||||||
|
|
||||||
|
Should probably rethink the whole thing. It's just not very convenient to use, even
|
||||||
|
for simple things like ELF files.
|
||||||
|
|
||||||
* Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique(),
|
* Rename stack_stash_foreach_by_address() to stack_stash_foreach_unique(),
|
||||||
or maybe not ...
|
or maybe not ...
|
||||||
|
|
||||||
|
|||||||
27
binfile.c
27
binfile.c
@ -127,9 +127,9 @@ separate_debug_file_exists (const char *name, guint32 crc)
|
|||||||
static const char *const debug_file_directory = DEBUGDIR;
|
static const char *const debug_file_directory = DEBUGDIR;
|
||||||
|
|
||||||
static ElfParser *
|
static ElfParser *
|
||||||
get_debug_file (ElfParser *elf,
|
get_debuglink_file (ElfParser *elf,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
char **new_name)
|
char **new_name)
|
||||||
{
|
{
|
||||||
#define N_TRIES 4
|
#define N_TRIES 4
|
||||||
const char *basename;
|
const char *basename;
|
||||||
@ -183,6 +183,27 @@ get_debug_file (ElfParser *elf,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ElfParser *
|
||||||
|
get_build_id_file (ElfParser *elf,
|
||||||
|
const char *filename,
|
||||||
|
char **new_name)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ElfParser *
|
||||||
|
get_debug_file (ElfParser *elf,
|
||||||
|
const char *filename,
|
||||||
|
char **new_name)
|
||||||
|
{
|
||||||
|
ElfParser *t;
|
||||||
|
|
||||||
|
if ((t = get_build_id_file (elf, filename, new_name)))
|
||||||
|
return t;
|
||||||
|
else
|
||||||
|
return get_debuglink_file (elf, filename, new_name);
|
||||||
|
}
|
||||||
|
|
||||||
static ElfParser *
|
static ElfParser *
|
||||||
find_separate_debug_file (ElfParser *elf,
|
find_separate_debug_file (ElfParser *elf,
|
||||||
const char *filename)
|
const char *filename)
|
||||||
|
|||||||
@ -324,7 +324,6 @@ bin_parser_get_string (BinParser *parser)
|
|||||||
parser->offset += strlen (result) + 1;
|
parser->offset += strlen (result) + 1;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Field *
|
static const Field *
|
||||||
|
|||||||
71
elfparser.c
71
elfparser.c
@ -48,6 +48,7 @@ struct ElfParser
|
|||||||
BinRecord * strtab_format;
|
BinRecord * strtab_format;
|
||||||
BinRecord * shn_entry;
|
BinRecord * shn_entry;
|
||||||
BinRecord * sym_format;
|
BinRecord * sym_format;
|
||||||
|
BinRecord * note_format;
|
||||||
|
|
||||||
int n_sections;
|
int n_sections;
|
||||||
Section ** sections;
|
Section ** sections;
|
||||||
@ -60,6 +61,9 @@ struct ElfParser
|
|||||||
|
|
||||||
char * filename;
|
char * filename;
|
||||||
|
|
||||||
|
gboolean checked_build_id;
|
||||||
|
char * build_id;
|
||||||
|
|
||||||
const Section * text_section;
|
const Section * text_section;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -217,6 +221,7 @@ elf_parser_new_from_data (const guchar *data,
|
|||||||
parser->text_section = find_section (parser, ".text", SHT_NOBITS);
|
parser->text_section = find_section (parser, ".text", SHT_NOBITS);
|
||||||
|
|
||||||
parser->filename = NULL;
|
parser->filename = NULL;
|
||||||
|
parser->build_id = NULL;
|
||||||
|
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
@ -366,6 +371,9 @@ elf_parser_free (ElfParser *parser)
|
|||||||
if (parser->filename)
|
if (parser->filename)
|
||||||
g_free (parser->filename);
|
g_free (parser->filename);
|
||||||
|
|
||||||
|
if (parser->build_id)
|
||||||
|
g_free (parser->build_id);
|
||||||
|
|
||||||
g_free (parser);
|
g_free (parser);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -634,6 +642,53 @@ elf_parser_get_text_offset (ElfParser *parser)
|
|||||||
return parser->text_section->offset;
|
return parser->text_section->offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const gchar *
|
||||||
|
elf_parser_get_build_id (ElfParser *parser)
|
||||||
|
{
|
||||||
|
if (!parser->checked_build_id)
|
||||||
|
{
|
||||||
|
const Section *build_id = find_section (parser, ".note.gnu.build-id", SHT_NOTE);
|
||||||
|
guint64 name_size;
|
||||||
|
guint64 desc_size;
|
||||||
|
guint64 type;
|
||||||
|
const char *name;
|
||||||
|
const char *desc;
|
||||||
|
GString *string;
|
||||||
|
int i;
|
||||||
|
const char hex_digits[] = { '0', '1', '2', '3', '4', '5', '6', '7',
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f' };
|
||||||
|
|
||||||
|
parser->checked_build_id = TRUE;
|
||||||
|
|
||||||
|
if (!build_id)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
bin_parser_set_offset (parser->parser, build_id->offset);
|
||||||
|
|
||||||
|
name_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "name_size");
|
||||||
|
desc_size = bin_parser_get_uint_field (parser->parser, parser->note_format, "desc_size");
|
||||||
|
type = bin_parser_get_uint_field (parser->parser, parser->note_format, "type");
|
||||||
|
|
||||||
|
name = bin_parser_get_string (parser->parser);
|
||||||
|
|
||||||
|
bin_parser_align (parser->parser, 4);
|
||||||
|
|
||||||
|
desc = bin_parser_get_string (parser->parser);
|
||||||
|
|
||||||
|
string = g_string_new (NULL);
|
||||||
|
|
||||||
|
for (i = 0; i < desc_size; ++i)
|
||||||
|
{
|
||||||
|
g_string_append_c (string, hex_digits[desc[i] & 0xf0]);
|
||||||
|
g_string_append_c (string, hex_digits[desc[i] & 0x0f]);
|
||||||
|
}
|
||||||
|
|
||||||
|
parser->build_id = g_string_free (string, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return parser->build_id;
|
||||||
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
|
||||||
{
|
{
|
||||||
@ -745,7 +800,8 @@ static void
|
|||||||
get_formats (gboolean is_64,
|
get_formats (gboolean is_64,
|
||||||
const BinField **elf_header,
|
const BinField **elf_header,
|
||||||
const BinField **shn_entry,
|
const BinField **shn_entry,
|
||||||
const BinField **sym_format)
|
const BinField **sym_format,
|
||||||
|
const BinField **note_format_out)
|
||||||
{
|
{
|
||||||
static const BinField elf64_header[] = {
|
static const BinField elf64_header[] = {
|
||||||
{ "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
|
{ "e_ident", BIN_UNINTERPRETED, EI_NIDENT },
|
||||||
@ -831,6 +887,12 @@ get_formats (gboolean is_64,
|
|||||||
{ "" },
|
{ "" },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const BinField note_format[] = {
|
||||||
|
{ "name_size", BIN_UINT, 4 },
|
||||||
|
{ "desc_size", BIN_UINT, 4 },
|
||||||
|
{ "type", BIN_UINT, 4 },
|
||||||
|
};
|
||||||
|
|
||||||
if (is_64)
|
if (is_64)
|
||||||
{
|
{
|
||||||
*elf_header = elf64_header;
|
*elf_header = elf64_header;
|
||||||
@ -843,17 +905,20 @@ get_formats (gboolean is_64,
|
|||||||
*shn_entry = shn32_entry;
|
*shn_entry = shn32_entry;
|
||||||
*sym_format = sym32_format;
|
*sym_format = sym32_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*note_format_out = note_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
make_formats (ElfParser *parser, gboolean is_64)
|
make_formats (ElfParser *parser, gboolean is_64)
|
||||||
{
|
{
|
||||||
const BinField *elf_header, *shn_entry, *sym_format;
|
const BinField *elf_header, *shn_entry, *sym_format, *note_format;
|
||||||
|
|
||||||
get_formats (is_64, &elf_header, &shn_entry, &sym_format);
|
get_formats (is_64, &elf_header, &shn_entry, &sym_format, ¬e_format);
|
||||||
|
|
||||||
parser->header = bin_parser_create_record (parser->parser, elf_header);
|
parser->header = bin_parser_create_record (parser->parser, elf_header);
|
||||||
parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry);
|
parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry);
|
||||||
parser->sym_format = bin_parser_create_record (parser->parser, sym_format);
|
parser->sym_format = bin_parser_create_record (parser->parser, sym_format);
|
||||||
|
parser->note_format = bin_parser_create_record (parser->parser, note_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,11 +27,11 @@ ElfParser * elf_parser_new (const char *filename,
|
|||||||
void elf_parser_free (ElfParser *parser);
|
void elf_parser_free (ElfParser *parser);
|
||||||
const char * elf_parser_get_debug_link (ElfParser *parser,
|
const char * elf_parser_get_debug_link (ElfParser *parser,
|
||||||
guint32 *crc32);
|
guint32 *crc32);
|
||||||
|
const gchar *elf_parser_get_build_id (ElfParser *parser);
|
||||||
const guchar *elf_parser_get_eh_frame (ElfParser *parser);
|
const guchar *elf_parser_get_eh_frame (ElfParser *parser);
|
||||||
const guchar *elf_parser_get_debug_frame (ElfParser *parser);
|
const guchar *elf_parser_get_debug_frame (ElfParser *parser);
|
||||||
gulong elf_parser_get_text_offset (ElfParser *parser);
|
gulong elf_parser_get_text_offset (ElfParser *parser);
|
||||||
|
|
||||||
|
|
||||||
/* Lookup a symbol in the file.
|
/* Lookup a symbol in the file.
|
||||||
*
|
*
|
||||||
* The symbol returned is const, so don't free it it or anything. It
|
* The symbol returned is const, so don't free it it or anything. It
|
||||||
|
|||||||
15
testelf.c
15
testelf.c
@ -31,12 +31,19 @@ check (ElfParser *elf, gulong addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main (int argc, char **argv)
|
||||||
{
|
{
|
||||||
ElfParser *elf;
|
ElfParser *elf;
|
||||||
int i;
|
int i;
|
||||||
|
const char *build_id;
|
||||||
|
const char *filename;
|
||||||
|
|
||||||
elf = elf_parser_new ("/usr/lib/libgtk-x11-2.0.so", NULL);
|
if (argc == 1)
|
||||||
|
filename = "/usr/lib/libgtk-x11-2.0.so";
|
||||||
|
else
|
||||||
|
filename = argv[0];
|
||||||
|
|
||||||
|
elf = elf_parser_new (filename, NULL);
|
||||||
|
|
||||||
if (!elf)
|
if (!elf)
|
||||||
{
|
{
|
||||||
@ -44,6 +51,10 @@ main ()
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
build_id = elf_parser_get_build_id (elf);
|
||||||
|
|
||||||
|
g_print ("build ID: %s\n", build_id);
|
||||||
|
|
||||||
elf_parser_get_crc32 (elf);
|
elf_parser_get_crc32 (elf);
|
||||||
|
|
||||||
for (i = 0; i < 5000000; ++i)
|
for (i = 0; i < 5000000; ++i)
|
||||||
|
|||||||
Reference in New Issue
Block a user