diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2007-12-05 18:19:14 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2007-12-05 18:19:14 +0000 |
commit | 62eebdabc278dfd3440ba6032c10b2c2c1f95081 (patch) | |
tree | 9ff38fa88341fbbd441694430c74a222de58116f /src/shared-objects.c | |
parent | 7b9e77319d9affab4d3d4831b0845ff1715788ea (diff) |
Import a mini bfd and elf reader from sysprof.
Use a glib based minibfd - better caching and avoids a massive memory
leak with libbfd. However we loose filenames and line numbers temporarily.
Diffstat (limited to 'src/shared-objects.c')
-rw-r--r-- | src/shared-objects.c | 201 |
1 files changed, 20 insertions, 181 deletions
diff --git a/src/shared-objects.c b/src/shared-objects.c index 27f1434..9ec738d 100644 --- a/src/shared-objects.c +++ b/src/shared-objects.c @@ -21,7 +21,6 @@ #define _GNU_SOURCE #include <stdlib.h> -#include <bfd.h> #include <link.h> #include <string.h> @@ -29,6 +28,8 @@ #include "client.h" #include "shared-objects.h" +#include "minibfd/binfile.h" + struct _shared_object { SharedObjects *objects; SharedObject *ht_next; @@ -36,151 +37,10 @@ struct _shared_object { guint key; const char *name; - bfd *abfd; - asymbol **syms; + BinFile *bin_file; }; -struct find_symbol { - Client *client; - - asymbol **syms; - gulong offset; - - const char *path; - const char *function; - guint line; -}; - -#if 0 -static void -describe_symbol (bfd *abfd, - const char *filename, - const char *functionname, - unsigned int line) -{ - char *demangled_functionname = NULL; - gint len; - char *s; - - len = 0; - - if (object != NULL && *object != '\0') - len += strlen (object) + 1; - - if (functionname != NULL && *functionname != '\0') { - demangled_functionname = bfd_demangle (abfd, functionname, 3); - if (demangled_functionname != NULL) - len += strlen (demangled_functionname) + 1; - else - len += strlen (functionname) + 1; - } - - if (filename != NULL && *filename != '\0') { - const char *h; - - len += strlen (filename) + 1; - - h = strrchr (filename, '/'); - if (h != NULL) - len += strlen (h + 1) + 1; - else - len += strlen (filename) + 1; - } - - s = symbol->strings = malloc (len); - if (s == NULL) - return; - - if (object != NULL && *object != '\0') { - symbol->object = s - symbol->strings; - strcpy (s, object); - s += strlen (object) + 1; - } - - if (demangled_functionname != NULL) { - symbol->function = s - symbol->strings; - strcpy (s, demangled_functionname); - s += strlen (demangled_functionname) + 1; - free (demangled_functionname); - } else if (functionname != NULL && *functionname != '\0') { - symbol->function = s - symbol->strings; - strcpy (s, functionname); - s += strlen (functionname) + 1; - } - - if (filename != NULL && *filename != '\0') { - const char *h; - - symbol->path = s - symbol->strings; - strcpy (s, filename); - s += strlen (filename) + 1; - - symbol->filename = s - symbol->strings; - h = strrchr (filename, '/'); - if (h != NULL) - strcpy (s, h + 1); - else - strcpy (s, filename); - } - - symbol->lineno = line; -} -#endif - -static void -find_symbol_in_section (bfd *abfd, asection *section, void *data) -{ - struct find_symbol *fa = data; - ElfW (Addr) vma, pc; - bfd_size_type size; - - if (fa->offset == (gulong) -1) - return; - - if ((bfd_get_section_flags (abfd, section) & SEC_ALLOC) == 0) - return; - - vma = bfd_get_section_vma (abfd, section); - size = bfd_section_size (abfd, section); - - pc = fa->offset - vma; - if (pc < size) { - if (bfd_find_nearest_line (abfd, section, fa->syms, pc, - &fa->path, - &fa->function, - &fa->line)) - { - if (fa->function != NULL) { - char *demangled_functionname; - - demangled_functionname = bfd_demangle (abfd, fa->function, 3); - if (demangled_functionname != NULL) { - fa->function = client_add_string (fa->client, - demangled_functionname); - free (demangled_functionname); - } - } - } - fa->offset = -1; - } -} - -static gboolean -slurp_symtab (bfd *abfd, asymbol ***syms) -{ - long symcount; - unsigned int size; - - if ((bfd_get_file_flags (abfd) & HAS_SYMS) == 0) - return FALSE; - - symcount = bfd_read_minisymbols (abfd, FALSE, (PTR) syms, &size); - if (symcount == 0) - symcount = bfd_read_minisymbols (abfd, TRUE /* dynamic */ , - (PTR) syms, &size); - - return symcount > 0; -} +extern char *minibfd_demangle (const char *mangled, int options); gboolean shared_object_describe_offset (SharedObject *so, @@ -190,45 +50,25 @@ shared_object_describe_offset (SharedObject *so, const char **path, guint *line) { - struct find_symbol fa; - *object = so->name; *function = NULL; *path = NULL; *line = 0; - if (so->abfd == NULL) { - bfd *abfd; - - abfd = bfd_openr (so->name, NULL); - if (abfd == NULL) - return FALSE; - - if (bfd_check_format (abfd, bfd_archive) || - ! bfd_check_format_matches (abfd, bfd_object, NULL) || - ! slurp_symtab (abfd, &so->syms)) - { - bfd_close (abfd); - return FALSE; + if (so->bin_file == NULL) + so->bin_file = bin_file_new (so->name); + + *function = bin_symbol_get_name (so->bin_file, + bin_file_lookup_symbol (so->bin_file, + offset)); + if (*function != NULL) { + char *demangled = minibfd_demangle (*function, 3); + if (demangled != NULL) { + *function = client_add_string (so->objects->client, demangled); + g_free (demangled); } - - so->abfd = abfd; } - fa.client = so->objects->client; - - fa.function = NULL; - fa.path = NULL; - fa.line = 0; - - fa.syms = so->syms; - fa.offset = offset; - bfd_map_over_sections (so->abfd, find_symbol_in_section, &fa); - - *function = fa.function; - *path = fa.path; - *line = fa.line; - return TRUE; } @@ -238,6 +78,8 @@ shared_object_add (SharedObjects *objects, guint key, const char *name) SharedObject *so; guint index; + g_assert (shared_object_get (objects, key) == NULL); + if (++objects->ht.nnodes > 3 * objects->ht.size) { SharedObject **new_nodes; SharedObject *node, *next; @@ -265,8 +107,7 @@ shared_object_add (SharedObjects *objects, guint key, const char *name) so->objects = objects; so->key = key; so->name = client_add_string (objects->client, name); - so->abfd = NULL; - so->syms = NULL; + so->bin_file = NULL; index = key % objects->ht.size; so->ht_next = objects->ht.nodes[index]; @@ -295,8 +136,6 @@ shared_object_get (SharedObjects *objects, void shared_objects_init (SharedObjects *objects, Client *client) { - bfd_init (); - objects->client = client; objects->ht.size = 673; @@ -312,8 +151,8 @@ shared_objects_fini (SharedObjects *objects) for (index = 0; index < objects->ht.size; index++) { for (so = objects->ht.nodes[index]; so != NULL; so = so->ht_next) { - if (so->abfd != NULL) - bfd_close (so->abfd); + if (so->bin_file != NULL) + bin_file_free (so->bin_file); } } g_free (objects->ht.nodes); |