OSet-ify m_redir.c.
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@4930 a5019735-40e9-0310-863c-91ae7b9d1cf9
diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
index 0590233..a20574f 100644
--- a/coregrind/m_redir.c
+++ b/coregrind/m_redir.c
@@ -38,8 +38,8 @@
#include "pub_core_libcprint.h"
#include "pub_core_mallocfree.h"
#include "pub_core_options.h"
+#include "pub_core_oset.h"
#include "pub_core_redir.h"
-#include "pub_core_skiplist.h"
#include "pub_core_trampoline.h"
#include "pub_core_transtab.h"
@@ -65,6 +65,8 @@
function's arguments and return value.
*/
struct _CodeRedirect {
+ Addr from_addr; /* old addr -- MUST BE THE FIRST WORD! */
+
enum redir_type {
R_REDIRECT, /* plain redirection */
R_WRAPPER, /* wrap with valgrind-internal code */
@@ -73,7 +75,6 @@
const Char *from_lib; /* library qualifier pattern */
const Char *from_sym; /* symbol */
- Addr from_addr; /* old addr */
Addr to_addr; /* used for redirection -- new addr */
const FuncWrapper *wrapper; /* used for wrapping */
@@ -81,17 +82,11 @@
CodeRedirect *next; /* next pointer on unresolved list */
};
-static Char *straddr(void *p)
-{
- static Char buf[16];
- VG_(sprintf)(buf, "%p", *(Addr *)p);
- return buf;
-}
+static OSet* resolved_redirs;
-static SkipList sk_resolved_redirs =
- VG_SKIPLIST_INIT(CodeRedirect, from_addr, VG_(cmp_Addr),
- straddr, VG_AR_SYMTAB);
-
+// We use a linked list here rather than an OSet, because we want to
+// traverse it and possibly remove elements as we look at them. OSet
+// doesn't support this very well.
static CodeRedirect *unresolved_redirs = NULL;
static Bool soname_matches(const Char *pattern, const Char* soname)
@@ -124,8 +119,6 @@
switch (redir->type) {
case R_REDIRECT: {
- CodeRedirect* r;
-
TRACE_REDIR(" redir resolved (%s:%s=%p -> %p)",
redir->from_lib, redir->from_sym, redir->from_addr,
redir->to_addr);
@@ -156,15 +149,16 @@
"add_redir_to_resolved_list");
}
- r = VG_(SkipList_Find_Exact)(&sk_resolved_redirs, &redir->from_addr);
-
- if (r == NULL) {
- VG_(SkipList_Insert)(&sk_resolved_redirs, redir);
+ // This entails a possible double OSet lookup -- one for Contains(),
+ // one for Insert(). If we had OSet_InsertIfNonDup() we could do it
+ // with one lookup.
+ if ( ! VG_(OSet_Contains)(resolved_redirs, &redir->from_addr) ) {
+ VG_(OSet_Insert)(resolved_redirs, redir);
} else {
- /* XXX leak redir */
TRACE_REDIR(" redir %s:%s:%p->%p duplicated\n",
redir->from_lib, redir->from_sym, redir->from_addr,
redir->to_addr);
+ VG_(arena_free)(VG_AR_SYMTAB, redir);
}
break;
}
@@ -253,8 +247,8 @@
__attribute__((unused)) // It is used, but not on all platforms...
static void add_redirect_addr_to_addr( Addr from_addr, Addr to_addr )
{
- CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
-
+ CodeRedirect* redir = VG_(OSet_AllocNode)(resolved_redirs,
+ sizeof(CodeRedirect));
vg_assert(0 != from_addr && 0 != to_addr);
redir->type = R_REDIRECT;
@@ -277,8 +271,8 @@
const Char *from_lib, const Char *from_sym, Addr to_addr
)
{
- CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
-
+ CodeRedirect* redir = VG_(OSet_AllocNode)(resolved_redirs,
+ sizeof(CodeRedirect));
vg_assert(from_lib && from_sym && 0 != to_addr);
redir->type = R_REDIRECT;
@@ -304,8 +298,8 @@
CodeRedirect *VG_(add_wrapper)(const Char *from_lib, const Char *from_sym,
const FuncWrapper *wrapper)
{
- CodeRedirect *redir = VG_(SkipNode_Alloc)(&sk_resolved_redirs);
-
+ CodeRedirect* redir = VG_(OSet_AllocNode)(resolved_redirs,
+ sizeof(CodeRedirect));
redir->type = R_WRAPPER;
redir->from_lib = VG_(arena_strdup)(VG_AR_SYMTAB, from_lib);
redir->from_sym = VG_(arena_strdup)(VG_AR_SYMTAB, from_sym);
@@ -331,9 +325,7 @@
address. */
Addr VG_(code_redirect)(Addr a)
{
- CodeRedirect* r;
-
- r = VG_(SkipList_Find_Exact)(&sk_resolved_redirs, &a);
+ CodeRedirect* r = VG_(OSet_Lookup)(resolved_redirs, &a);
if (r == NULL)
return a;
@@ -342,8 +334,24 @@
return r->to_addr;
}
+static void* symtab_alloc(SizeT n)
+{
+ return VG_(arena_malloc)(VG_AR_SYMTAB, n);
+}
+
+static void symtab_free(void* p)
+{
+ return VG_(arena_free)(VG_AR_SYMTAB, p);
+}
+
void VG_(setup_code_redirect_table) ( void )
{
+ // Initialise resolved_redirs list.
+ resolved_redirs = VG_(OSet_Create)(offsetof(CodeRedirect, from_addr),
+ NULL, // Use fast comparison
+ symtab_alloc,
+ symtab_free);
+
#if defined(VGP_x86_linux)
/* Redirect _dl_sysinfo_int80, which is glibc's default system call
routine, to our copy so that the special sysinfo unwind hack in
@@ -375,10 +383,6 @@
"soname:ld.so.1", "strcmp",
(Addr)&VG_(ppc32_linux_REDIR_FOR_strcmp)
);
- add_redirect_sym_to_addr(
- "soname:ld.so.1", "index",
- (Addr)&VG_(ppc32_linux_REDIR_FOR_strchr)
- );
#else
# error Unknown platform