sysprof r410 - trunk



Author: ssp
Date: Sun Apr 20 20:58:11 2008
New Revision: 410
URL: http://svn.gnome.org/viewvc/sysprof?rev=410&view=rev

Log:
Initial build id support

Modified:
   trunk/ChangeLog
   trunk/TODO
   trunk/binfile.c
   trunk/binparser.c
   trunk/elfparser.c
   trunk/elfparser.h
   trunk/testelf.c

Modified: trunk/TODO
==============================================================================
--- trunk/TODO	(original)
+++ trunk/TODO	Sun Apr 20 20:58:11 2008
@@ -169,6 +169,9 @@
 	- "native endian" is probably not useful. Maybe go back to just
 	  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(),
   or maybe not ...
 

Modified: trunk/binfile.c
==============================================================================
--- trunk/binfile.c	(original)
+++ trunk/binfile.c	Sun Apr 20 20:58:11 2008
@@ -127,9 +127,9 @@
 static const char *const debug_file_directory = DEBUGDIR;
 
 static ElfParser *
-get_debug_file (ElfParser *elf,
-		const char *filename,
-		char **new_name)
+get_debuglink_file (ElfParser *elf,
+		    const char *filename,
+		    char **new_name)
 {
 #define N_TRIES 4
     const char *basename;
@@ -184,6 +184,27 @@
 }
 
 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 *
 find_separate_debug_file (ElfParser *elf,
 			  const char *filename)
 {

Modified: trunk/binparser.c
==============================================================================
--- trunk/binparser.c	(original)
+++ trunk/binparser.c	Sun Apr 20 20:58:11 2008
@@ -324,7 +324,6 @@
     parser->offset += strlen (result) + 1;
 
     return result;
-    
 }
 
 static const Field *

Modified: trunk/elfparser.c
==============================================================================
--- trunk/elfparser.c	(original)
+++ trunk/elfparser.c	Sun Apr 20 20:58:11 2008
@@ -48,6 +48,7 @@
     BinRecord *		strtab_format;
     BinRecord *		shn_entry;
     BinRecord *		sym_format;
+    BinRecord *		note_format;
     
     int			n_sections;
     Section **		sections;
@@ -59,6 +60,9 @@
     GMappedFile *	file;
 
     char *		filename;
+
+    gboolean		checked_build_id;
+    char *		build_id;
     
     const Section *	text_section;
 };
@@ -217,6 +221,7 @@
 	parser->text_section = find_section (parser, ".text", SHT_NOBITS);
 
     parser->filename = NULL;
+    parser->build_id = NULL;
     
     return parser;
 }
@@ -365,6 +370,9 @@
 
     if (parser->filename)
 	g_free (parser->filename);
+
+    if (parser->build_id)
+	g_free (parser->build_id);
     
     g_free (parser);
 }
@@ -468,7 +476,7 @@
 	    parser->symbols[n_functions].offset = offset;
 
 	    n_functions++;
-
+	    
 #if 0
 	    g_print ("    symbol: %s:   %lx\n",
 		     get_string_indirect (parser->parser,
@@ -634,6 +642,53 @@
     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 *
 elf_parser_get_debug_link (ElfParser *parser, guint32 *crc32)
 {
@@ -745,7 +800,8 @@
 get_formats (gboolean is_64,
 	     const BinField **elf_header,
 	     const BinField **shn_entry,
-	     const BinField **sym_format)
+	     const BinField **sym_format,
+	     const BinField **note_format_out)
 {
     static const BinField elf64_header[] = {
 	{ "e_ident",		BIN_UNINTERPRETED, EI_NIDENT },
@@ -831,6 +887,12 @@
 	{ "" },
     };
 
+    static const BinField note_format[] = {
+	{ "name_size",		BIN_UINT,	4 },
+	{ "desc_size",		BIN_UINT,	4 },
+	{ "type",		BIN_UINT,	4 },
+    };
+
     if (is_64)
     {
 	*elf_header = elf64_header;
@@ -843,17 +905,20 @@
 	*shn_entry  = shn32_entry;
 	*sym_format = sym32_format;
     }
+
+    *note_format_out = note_format;
 }
 
 static void
 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, &note_format);
 
     parser->header = bin_parser_create_record (parser->parser, elf_header);
     parser->shn_entry = bin_parser_create_record (parser->parser, shn_entry);
     parser->sym_format = bin_parser_create_record (parser->parser, sym_format);
+    parser->note_format = bin_parser_create_record (parser->parser, note_format);
 }
 

Modified: trunk/elfparser.h
==============================================================================
--- trunk/elfparser.h	(original)
+++ trunk/elfparser.h	Sun Apr 20 20:58:11 2008
@@ -27,11 +27,11 @@
 void          elf_parser_free           (ElfParser   *parser);
 const char *  elf_parser_get_debug_link (ElfParser   *parser,
 					 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_debug_frame (ElfParser   *parser);
 gulong	      elf_parser_get_text_offset (ElfParser  *parser);
 
-
 /* Lookup a symbol in the file.
  *
  * The symbol returned is const, so don't free it it or anything. It

Modified: trunk/testelf.c
==============================================================================
--- trunk/testelf.c	(original)
+++ trunk/testelf.c	Sun Apr 20 20:58:11 2008
@@ -31,12 +31,19 @@
 }
 
 int
-main ()
+main (int argc, char **argv)
 {
     ElfParser *elf;
     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)
     {
@@ -44,6 +51,10 @@
 	return -1;
     }
 
+    build_id = elf_parser_get_build_id (elf);
+
+    g_print ("build ID: %s\n", build_id);
+    
     elf_parser_get_crc32 (elf);
     
     for (i = 0; i < 5000000; ++i)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]