summaryrefslogtreecommitdiff
path: root/src/shared-objects.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2007-12-05 18:19:14 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2007-12-05 18:19:14 +0000
commit62eebdabc278dfd3440ba6032c10b2c2c1f95081 (patch)
tree9ff38fa88341fbbd441694430c74a222de58116f /src/shared-objects.c
parent7b9e77319d9affab4d3d4831b0845ff1715788ea (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.c201
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);