summaryrefslogtreecommitdiff
path: root/util/cairo-trace/lookup-symbol.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/cairo-trace/lookup-symbol.c')
-rw-r--r--util/cairo-trace/lookup-symbol.c331
1 files changed, 0 insertions, 331 deletions
diff --git a/util/cairo-trace/lookup-symbol.c b/util/cairo-trace/lookup-symbol.c
deleted file mode 100644
index f9665b36f..000000000
--- a/util/cairo-trace/lookup-symbol.c
+++ /dev/null
@@ -1,331 +0,0 @@
-/* cairo-trace - a utility to record and replay calls to the Cairo library.
- *
- * Copyright © 2008 Chris Wilson
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-/*
- * A less hacky utility to lookup the debug strings for a particular
- * .text address.
- * Derived from backtrace-symbols.c in cairo by Chris Wilson.
- */
-
-/*
- A hacky replacement for backtrace_symbols in glibc
-
- backtrace_symbols in glibc looks up symbols using dladdr which is limited
- in the symbols that it sees. libbacktracesymbols opens the executable and
- shared libraries using libbfd and will look up backtrace information using
- the symbol table and the dwarf line information.
-
- It may make more sense for this program to use libelf instead of libbfd.
- However, I have not investigated that yet.
-
- Derived from addr2line.c from GNU Binutils by Jeff Muizelaar
-
- Copyright 2007 Jeff Muizelaar
- */
-
-/* addr2line.c -- convert addresses to line number and function name
- Copyright 1997, 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
- Contributed by Ulrich Lauther <Ulrich.Lauther@mchp.siemens.de>
-
- This file was part of GNU Binutils.
- */
-
-#define _GNU_SOURCE
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define true 1
-#define false 0
-
-#include "lookup-symbol.h"
-
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <link.h>
-#include <string.h>
-#include <pthread.h>
-
-#if HAVE_BFD
-#include <bfd.h>
-#include <libiberty.h>
-
-struct symtab {
- bfd *bfd;
- asymbol **syms;
-};
-
-struct symbol {
- int found;
- bfd_vma pc;
- struct symtab *symtab;
- const char *filename;
- const char *functionname;
- unsigned int line;
-};
-
-
-static void
-_symtab_fini (struct symtab *symtab)
-{
- free (symtab->syms);
- if (symtab->bfd != NULL)
- bfd_close (symtab->bfd);
-}
-
-/* Read in the symbol table. */
-static int
-_symtab_init (struct symtab *symtab, const char *filename)
-{
- char **matching;
- long symcount;
- unsigned int size;
-
- symtab->bfd = NULL;
- symtab->syms = NULL;
-
- symtab->bfd = bfd_openr (filename, NULL);
- if (symtab->bfd == NULL)
- goto BAIL;
-
- if (bfd_check_format (symtab->bfd, bfd_archive))
- goto BAIL;
-
- if (! bfd_check_format_matches (symtab->bfd, bfd_object, &matching))
- goto BAIL;
-
- symcount = bfd_read_minisymbols (symtab->bfd, false, (PTR) &symtab->syms, &size);
- if (symcount == 0) {
- symcount = bfd_read_minisymbols (symtab->bfd, true /* dynamic */ ,
- (PTR) &symtab->syms, &size);
- }
- if (symcount < 0)
- goto BAIL;
-
- if ((bfd_get_file_flags (symtab->bfd) & HAS_SYMS) == 0)
- goto BAIL;
-
- return 1;
-
-BAIL:
- _symtab_fini (symtab);
- return 0;
-}
-
-/* Look for an address in a section.
- * This is called via bfd_map_over_sections.
- */
-static void
-find_address_in_section (bfd *abfd,
- asection *section,
- void *data)
-{
- bfd_vma vma;
- bfd_size_type size;
- struct symbol *symbol = data;
- struct symtab *symtab = symbol->symtab;
-
- if (symbol->found)
- return;
-
- if ((bfd_get_section_flags (symtab->bfd, section) & SEC_ALLOC) == 0)
- return;
-
- vma = bfd_get_section_vma (symtab->bfd, section);
- if (symbol->pc < vma)
- return;
-
- size = bfd_section_size (symtab->bfd, section);
- if (symbol->pc >= vma + size)
- return;
-
- symbol->found = bfd_find_nearest_line (symtab->bfd, section,
- symtab->syms,
- symbol->pc - vma,
- &symbol->filename,
- &symbol->functionname,
- &symbol->line);
-}
-
-static void
-_symbol_fini (struct symbol *symbol)
-{
-}
-
-static void
-_symbol_init (struct symbol *symbol, struct symtab *symtab, bfd_vma addr)
-{
- symbol->found = false;
- symbol->symtab = symtab;
- symbol->pc = addr;
-}
-
-static void
-_symbol_print (struct symbol *symbol, char *buf, int buflen, const char *filename)
-{
- const char *name, *h;
- char path[1024];
-
- if (! symbol->found)
- return;
-
- name = symbol->functionname;
- if (name == NULL || *name == '\0')
- name = "??";
-
- if (symbol->filename != NULL)
- filename = symbol->filename;
- if (strcmp (filename, "/proc/self/exe") == 0) {
- int len = readlink ("/proc/self/exe", path, sizeof (path) - 1);
- if (len != -1) {
- path[len] = '\0';
- filename = path;
- }
- }
- h = strrchr (filename, '/');
- if (h != NULL)
- filename = h + 1;
-
- if (symbol->line) {
- snprintf (buf, buflen, "%s() [%s:%u]",
- name, filename, symbol->line);
- } else {
- snprintf (buf, buflen, "%s() [%s]", name, filename);
- }
-}
-#endif
-
-struct file_match {
- const char *file;
- ElfW(Addr) address;
- ElfW(Addr) base;
- void *hdr;
-};
-
-static int
-find_matching_file (struct dl_phdr_info *info, size_t size, void *data)
-{
- struct file_match *match = data;
- /* This code is modeled from Gfind_proc_info-lsb.c:callback() from libunwind */
- long n;
- const ElfW(Phdr) *phdr;
- ElfW(Addr) load_base = info->dlpi_addr;
-
- phdr = info->dlpi_phdr;
- for (n = info->dlpi_phnum; --n >= 0; phdr++) {
- if (phdr->p_type == PT_LOAD) {
- ElfW(Addr) vaddr = phdr->p_vaddr + load_base;
- if (match->address >= vaddr &&
- match->address < vaddr + phdr->p_memsz)
- {
- /* we found a match */
- match->file = info->dlpi_name;
- match->base = info->dlpi_addr;
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-struct symbol_cache_entry {
- const void *ptr;
- struct symbol_cache_entry *hash_prev, *hash_next;
- char name[0];
-};
-
-static struct symbol_cache_entry *symbol_cache_hash[13477];
-static pthread_mutex_t symbol_cache_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-char *
-lookup_symbol (char *buf, int buflen, const void *ptr)
-{
- struct file_match match;
-#if HAVE_BFD
- struct symtab symtab;
- struct symbol symbol;
-#endif
- struct symbol_cache_entry *cache;
- int bucket;
- int len;
-
- bucket = (unsigned long) ptr % (sizeof (symbol_cache_hash) / sizeof (symbol_cache_hash[0]));
- pthread_mutex_lock (&symbol_cache_mutex);
- for (cache = symbol_cache_hash[bucket];
- cache != NULL;
- cache = cache->hash_next)
- {
- if (cache->ptr == ptr) {
- if (cache->hash_prev != NULL) {
- cache->hash_prev->hash_next = cache->hash_next;
- if (cache->hash_next != NULL)
- cache->hash_next->hash_prev = cache->hash_prev;
- cache->hash_prev = NULL;
- cache->hash_next = symbol_cache_hash[bucket];
- symbol_cache_hash[bucket]->hash_prev = cache;
- symbol_cache_hash[bucket] = cache;
- }
-
- pthread_mutex_unlock (&symbol_cache_mutex);
- return cache->name;
- }
- }
- pthread_mutex_unlock (&symbol_cache_mutex);
-
- match.file = NULL;
- match.address = (ElfW(Addr)) ptr;
- dl_iterate_phdr (find_matching_file, &match);
-
- snprintf (buf, buflen, "0x%llx",
- (long long unsigned int) match.address);
-
- if (match.file == NULL || *match.file == '\0')
- match.file = "/proc/self/exe";
-
-#if HAVE_BFD
- if (_symtab_init (&symtab, match.file)) {
- _symbol_init (&symbol, &symtab, match.address - match.base);
- bfd_map_over_sections (symtab.bfd, find_address_in_section, &symbol);
- if (symbol.found)
- _symbol_print (&symbol, buf, buflen, match.file);
- _symbol_fini (&symbol);
-
- _symtab_fini (&symtab);
- }
-#endif
-
- len = strlen (buf);
- cache = malloc (sizeof (struct symbol_cache_entry) + len + 1);
- if (cache != NULL) {
- cache->ptr = ptr;
- memcpy (cache->name, buf, len + 1);
-
- pthread_mutex_lock (&symbol_cache_mutex);
- cache->hash_prev = NULL;
- cache->hash_next = symbol_cache_hash[bucket];
- if (symbol_cache_hash[bucket] != NULL)
- symbol_cache_hash[bucket]->hash_prev = cache;
- symbol_cache_hash[bucket] = cache;
- pthread_mutex_unlock (&symbol_cache_mutex);
- }
-
- return buf;
-}