summaryrefslogtreecommitdiff
path: root/demangle.c
diff options
context:
space:
mode:
Diffstat (limited to 'demangle.c')
-rw-r--r--demangle.c50
1 files changed, 35 insertions, 15 deletions
diff --git a/demangle.c b/demangle.c
index 5147367..5b9dcfc 100644
--- a/demangle.c
+++ b/demangle.c
@@ -1,5 +1,6 @@
/*
* This file is part of ltrace.
+ * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
* Copyright (C) 1998,1999,2003,2004,2008,2009 Juan Cespedes
* Copyright (C) 2006 Ian Wienand
*
@@ -25,40 +26,59 @@
#include <stdlib.h>
#include <stdio.h>
-#include "common.h"
+#include "demangle.h"
+#include "dict.h"
+#include "debug.h"
#ifdef USE_DEMANGLE
/*****************************************************************************/
-static Dict *d = NULL;
+static struct dict *name_cache = NULL;
const char *
my_demangle(const char *function_name) {
- const char *tmp, *fn_copy;
#ifdef USE_CXA_DEMANGLE
extern char *__cxa_demangle(const char *, char *, size_t *, int *);
#endif
debug(DEBUG_FUNCTION, "my_demangle(name=%s)", function_name);
- if (!d)
- d = dict_init(dict_key2hash_string, dict_key_cmp_string);
+ if (name_cache == NULL) {
+ name_cache = malloc(sizeof(*name_cache));
+ if (name_cache != NULL)
+ DICT_INIT(name_cache, char *, const char *,
+ dict_hash_string, dict_eq_string, NULL);
+ }
+
+ const char *tmp = NULL;
+ if (name_cache != NULL
+ && DICT_FIND_VAL(name_cache, &function_name, &tmp) == 0)
+ return tmp;
- tmp = dict_find_entry(d, (void *)function_name);
- if (!tmp) {
- fn_copy = strdup(function_name);
#ifdef HAVE_LIBIBERTY
- tmp = cplus_demangle(function_name, DMGL_ANSI | DMGL_PARAMS);
+ tmp = cplus_demangle(function_name,
+ DMGL_ANSI | DMGL_PARAMS);
#elif defined USE_CXA_DEMANGLE
- int status = 0;
- tmp = __cxa_demangle(function_name, NULL, NULL, &status);
+ int status = 0;
+ tmp = __cxa_demangle(function_name, NULL, NULL, &status);
#endif
- if (!tmp)
- tmp = fn_copy;
- if (tmp)
- dict_enter(d, (void *)fn_copy, (void *)tmp);
+ if (name_cache == NULL || tmp == NULL) {
+ fail:
+ if (tmp == NULL)
+ return function_name;
+ return tmp;
+ }
+
+ const char *fn_copy = strdup(function_name);
+ if (fn_copy == NULL)
+ goto fail;
+
+ if (DICT_INSERT(name_cache, &fn_copy, &tmp) < 0) {
+ free((char *)fn_copy);
+ goto fail;
}
+
return tmp;
}