Introduce SymbolResolver and its subclasses.

SymbolResolver provides a clean way to do the symbol lookup at
runtime.

LookupFunctionSymbolResolver searches a symbol through a given
function with context supplied.

BCCRuntimeSymbolResolver searches symbol from a predefined symbol-to-
address array which replaces the FindRuntime() function defined in
Runtime.c previously.

SymbolResolverProxy chains the SymbolResolvers and searches the symbol
one by one following the chain until it founds the definition of the
symbol.
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index ae6352c..c3566e5 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -25,6 +25,7 @@
 libbcc_executionengine_SRC_FILES := \
   BCCContext.cpp \
   BCCContextImpl.cpp \
+  BCCRuntimeSymbolResolver.cpp \
   Compiler.cpp \
   FileBase.cpp \
   GDBJIT.cpp \
@@ -34,13 +35,14 @@
   MCCacheReader.cpp \
   OutputFile.cpp \
   RSScript.cpp \
-  Runtime.c \
-  RuntimeStub.c \
+  BCCRuntimeStub.c \
   Script.cpp \
   ScriptCached.cpp \
   ScriptCompiled.cpp \
   Sha1Helper.cpp \
-  Source.cpp
+  Source.cpp \
+  SymbolResolverProxy.cpp \
+  SymbolResolvers.cpp
 
 
 #=====================================================================
diff --git a/lib/ExecutionEngine/Runtime.def b/lib/ExecutionEngine/BCCRuntime.def
similarity index 100%
rename from lib/ExecutionEngine/Runtime.def
rename to lib/ExecutionEngine/BCCRuntime.def
diff --git a/lib/ExecutionEngine/RuntimeStub.c b/lib/ExecutionEngine/BCCRuntimeStub.c
similarity index 98%
rename from lib/ExecutionEngine/RuntimeStub.c
rename to lib/ExecutionEngine/BCCRuntimeStub.c
index d38f68d..fc78c71 100644
--- a/lib/ExecutionEngine/RuntimeStub.c
+++ b/lib/ExecutionEngine/BCCRuntimeStub.c
@@ -1,4 +1,4 @@
-#include "RuntimeStub.h"
+#include "BCCRuntimeStub.h"
 
 #include "runtime/lib/int_lib.h"
 
diff --git a/lib/ExecutionEngine/RuntimeStub.h b/lib/ExecutionEngine/BCCRuntimeStub.h
similarity index 100%
rename from lib/ExecutionEngine/RuntimeStub.h
rename to lib/ExecutionEngine/BCCRuntimeStub.h
diff --git a/lib/ExecutionEngine/BCCRuntimeSymbolResolver.cpp b/lib/ExecutionEngine/BCCRuntimeSymbolResolver.cpp
new file mode 100644
index 0000000..1059d85
--- /dev/null
+++ b/lib/ExecutionEngine/BCCRuntimeSymbolResolver.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "BCCRuntimeSymbolResolver.h"
+
+// int_lib.h included by BCCRuntimeStub.h has the following line:
+//
+//            typedef      int si_int;
+//
+// However, there's already a macro also named "si_int" defined in siginfo.h
+// bionic/libc/kernel/common/asm-generic/. This is #undef is a hack to avoid
+// compiler mistakenly recognize the identifier "si_int" as a macro and abort
+// the compilation.
+//
+// This line of hack should put in the header file since it invalidate a
+// "system" scope macro definition.
+#undef si_int
+#include "BCCRuntimeStub.h"
+
+using namespace bcc;
+
+#if defined(__arm__) || defined(__mips__)
+  #define DEF_GENERIC_RUNTIME(func)   \
+    extern void *func;
+  #define DEF_VFP_RUNTIME(func) \
+    extern void *func ## vfp;
+  #define DEF_LLVM_RUNTIME(func)
+  #define DEF_BCC_RUNTIME(func)
+#include "BCCRuntime.def"
+#endif
+
+const BCCRuntimeSymbolResolver::SymbolMap BCCRuntimeSymbolResolver::SymbolArray[] = {
+#if defined(__arm__) || defined(__mips__)
+  #define DEF_GENERIC_RUNTIME(func)   \
+    { #func, (void*) &func },
+  // TODO: enable only when target support VFP
+  #define DEF_VFP_RUNTIME(func) \
+    { #func, (void*) &func ## vfp },
+#else
+  // host compiler library must contain generic runtime
+  #define DEF_GENERIC_RUNTIME(func)
+  #define DEF_VFP_RUNTIME(func)
+#endif
+#define DEF_LLVM_RUNTIME(func)   \
+  { #func, (void*) &func },
+#define DEF_BCC_RUNTIME(func) \
+  { #func, &func ## _bcc },
+#include "BCCRuntime.def"
+};
+
+const size_t BCCRuntimeSymbolResolver::NumSymbols =
+  sizeof(BCCRuntimeSymbolResolver::SymbolArray) /
+    sizeof(BCCRuntimeSymbolResolver::SymbolArray[0]);
diff --git a/lib/ExecutionEngine/BCCRuntimeSymbolResolver.h b/lib/ExecutionEngine/BCCRuntimeSymbolResolver.h
new file mode 100644
index 0000000..e48a4d8
--- /dev/null
+++ b/lib/ExecutionEngine/BCCRuntimeSymbolResolver.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_BCC_RUNTIME_SYMBOL_RESOLVERS_H
+#define BCC_EXECUTION_ENGINE_BCC_RUNTIME_SYMBOL_RESOLVERS_H
+
+#include "SymbolResolvers.h"
+
+namespace bcc {
+
+class BCCRuntimeSymbolResolver :
+  public ArraySymbolResolver<BCCRuntimeSymbolResolver> {
+  typedef ArraySymbolResolver<BCCRuntimeSymbolResolver> super;
+public:
+  // SymbolArray and NumSymbols are required to be define in the
+  // subclass of ArraySymbolResolver.
+  static const SymbolMap SymbolArray[];
+  static const size_t NumSymbols;
+
+  BCCRuntimeSymbolResolver() : super(/* pSorted */true) { }
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_BCC_RUNTIME_SYMBOL_RESOLVERS_H
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index a56c11c..c4a0870 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -23,11 +23,13 @@
 #include "Disassembler/Disassembler.h"
 #endif
 
+#include "BCCRuntimeSymbolResolver.h"
 #include "DebugHelper.h"
-#include "Runtime.h"
 #include "ScriptCompiled.h"
 #include "Sha1Helper.h"
 #include "CompilerOption.h"
+#include "SymbolResolverProxy.h"
+#include "SymbolResolvers.h"
 
 #include "librsloader.h"
 
@@ -402,10 +404,20 @@
     return 0;
 
   // Load the ELF Object
-  mRSExecutable =
-      rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
-                         mEmittedELFExecutable.size(),
-                         &resolveSymbolAdapter, this);
+  {
+    BCCRuntimeSymbolResolver BCCRuntimesResolver;
+    LookupFunctionSymbolResolver<void*> RSSymbolResolver(mpSymbolLookupFn,
+                                                         mpSymbolLookupContext);
+
+    SymbolResolverProxy Resolver;
+    Resolver.chainResolver(BCCRuntimesResolver);
+    Resolver.chainResolver(RSSymbolResolver);
+
+    mRSExecutable =
+        rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
+                           mEmittedELFExecutable.size(),
+                           SymbolResolverProxy::LookupFunction, &Resolver);
+  }
 
   if (!mRSExecutable) {
     setError("Fail to load emitted ELF relocatable file");
@@ -652,25 +664,6 @@
   return rsloaderGetSymbolAddress(mRSExecutable, name);
 }
 
-
-void *Compiler::resolveSymbolAdapter(void *context, char const *name) {
-  Compiler *self = reinterpret_cast<Compiler *>(context);
-
-  if (void *Addr = FindRuntimeFunction(name)) {
-    return Addr;
-  }
-
-  if (self->mpSymbolLookupFn) {
-    if (void *Addr = self->mpSymbolLookupFn(self->mpSymbolLookupContext, name)) {
-      return Addr;
-    }
-  }
-
-  ALOGE("Unable to resolve symbol: %s\n", name);
-  return NULL;
-}
-
-
 Compiler::~Compiler() {
   rsloaderDisposeExec(mRSExecutable);
 
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 8fee17c..b5872d6 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -139,8 +139,6 @@
 
     int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM);
 
-    static void *resolveSymbolAdapter(void *context, char const *name);
-
     int runInternalPasses(std::vector<std::string>& Names,
                           std::vector<uint32_t>& Signatures);
 
diff --git a/lib/ExecutionEngine/MCCacheReader.cpp b/lib/ExecutionEngine/MCCacheReader.cpp
index 0a70ff6..1a74ed3 100644
--- a/lib/ExecutionEngine/MCCacheReader.cpp
+++ b/lib/ExecutionEngine/MCCacheReader.cpp
@@ -16,10 +16,12 @@
 
 #include "MCCacheReader.h"
 
+#include "BCCRuntimeSymbolResolver.h"
 #include "DebugHelper.h"
 #include "InputFile.h"
 #include "ScriptCached.h"
-#include "Runtime.h"
+#include "SymbolResolverProxy.h"
+#include "SymbolResolvers.h"
 
 #include <bcc/bcc_mccache.h>
 
@@ -428,24 +430,6 @@
   return true;
 }
 
-void *MCCacheReader::resolveSymbolAdapter(void *context, char const *name) {
-  MCCacheReader *self = reinterpret_cast<MCCacheReader *>(context);
-
-  if (void *Addr = FindRuntimeFunction(name)) {
-    return Addr;
-  }
-
-  if (self->mpSymbolLookupFn) {
-    if (void *Addr =
-        self->mpSymbolLookupFn(self->mpSymbolLookupContext, name)) {
-      return Addr;
-    }
-  }
-
-  ALOGE("Unable to resolve symbol: %s\n", name);
-  return NULL;
-}
-
 bool MCCacheReader::readObjFile() {
   if (mpResult->mCachedELFExecutable.size() != 0) {
     ALOGE("Attempted to read cached object into a non-empty script");
@@ -461,10 +445,19 @@
     return false;
   }
   ALOGD("Read object file size %d", (int)mpResult->mCachedELFExecutable.size());
+
+  BCCRuntimeSymbolResolver bccRuntimesResolver;
+  LookupFunctionSymbolResolver<void *> rsSymbolResolver(mpSymbolLookupFn,
+                                                        mpSymbolLookupContext);
+
+  SymbolResolverProxy resolver;
+  resolver.chainResolver(bccRuntimesResolver);
+  resolver.chainResolver(rsSymbolResolver);
+
   mpResult->mRSExecutable =
   rsloaderCreateExec((unsigned char *)&*(mpResult->mCachedELFExecutable.begin()),
                      mpResult->mCachedELFExecutable.size(),
-                     &resolveSymbolAdapter, this);
+                     SymbolResolverProxy::LookupFunction, &resolver);
 
   // Point ELF section headers to location of executable code, otherwise
   // execution through GDB stops unexpectedly as GDB translates breakpoints
diff --git a/lib/ExecutionEngine/MCCacheReader.h b/lib/ExecutionEngine/MCCacheReader.h
index 972f0c8..39e438b 100644
--- a/lib/ExecutionEngine/MCCacheReader.h
+++ b/lib/ExecutionEngine/MCCacheReader.h
@@ -109,9 +109,6 @@
     bool checkContext();
 
     bool relocate();
-
-    static void *resolveSymbolAdapter(void *context, char const *name);
-
   };
 
 } // namespace bcc
diff --git a/lib/ExecutionEngine/Runtime.c b/lib/ExecutionEngine/Runtime.c
deleted file mode 100644
index 6b9e20d..0000000
--- a/lib/ExecutionEngine/Runtime.c
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "RuntimeStub.h"
-
-#include <bcc/bcc_assert.h>
-
-#include <stdbool.h>
-#include <string.h>
-#include <stdlib.h>
-
-typedef struct {
-  const char *mName;
-  void *mPtr;
-} RuntimeFunction;
-
-#if defined(__arm__) || defined(__mips__)
-  #define DEF_GENERIC_RUNTIME(func)   \
-    extern void *func;
-  #define DEF_VFP_RUNTIME(func) \
-    extern void *func ## vfp;
-  #define DEF_LLVM_RUNTIME(func)
-  #define DEF_BCC_RUNTIME(func)
-#include "Runtime.def"
-#endif
-
-static const RuntimeFunction gRuntimes[] = {
-#if defined(__arm__) || defined(__mips__)
-  #define DEF_GENERIC_RUNTIME(func)   \
-    { #func, (void*) &func },
-  // TODO: enable only when target support VFP
-  #define DEF_VFP_RUNTIME(func) \
-    { #func, (void*) &func ## vfp },
-#else
-  // host compiler library must contain generic runtime
-  #define DEF_GENERIC_RUNTIME(func)
-  #define DEF_VFP_RUNTIME(func)
-#endif
-#define DEF_LLVM_RUNTIME(func)   \
-  { #func, (void*) &func },
-#define DEF_BCC_RUNTIME(func) \
-  { #func, &func ## _bcc },
-#include "Runtime.def"
-};
-
-static int CompareRuntimeFunction(const void *a, const void *b) {
-  return strcmp(((const RuntimeFunction*) a)->mName,
-               ((const RuntimeFunction*) b)->mName);
-}
-
-void *FindRuntimeFunction(const char *Name) {
-  // binary search
-  const RuntimeFunction Key = { Name, NULL };
-  const RuntimeFunction *R =
-      bsearch(&Key,
-              gRuntimes,
-              sizeof(gRuntimes) / sizeof(RuntimeFunction),
-              sizeof(RuntimeFunction),
-              CompareRuntimeFunction);
-
-  return ((R) ? R->mPtr : NULL);
-}
-
-void VerifyRuntimesTable() {
-  unsigned N = sizeof(gRuntimes) / sizeof(RuntimeFunction), i;
-  for(i = 0; i < N; i++) {
-    const char *Name = gRuntimes[i].mName;
-    int *Ptr = FindRuntimeFunction(Name);
-
-    if (Ptr != (int*) gRuntimes[i].mPtr)
-      bccAssert(false && "Table is corrupted (runtime name should be sorted "
-                         "in Runtime.def).");
-  }
-}
diff --git a/lib/ExecutionEngine/Runtime.h b/lib/ExecutionEngine/Runtime.h
deleted file mode 100644
index c0b7ad8..0000000
--- a/lib/ExecutionEngine/Runtime.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_RUNTIME_H
-#define BCC_RUNTIME_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-void *FindRuntimeFunction(const char *Name);
-void VerifyRuntimesTable();
-
-#ifdef __cplusplus
-};
-#endif
-
-#endif  /* BCC_RUNTIME_H */
diff --git a/lib/ExecutionEngine/SymbolResolverInterface.h b/lib/ExecutionEngine/SymbolResolverInterface.h
new file mode 100644
index 0000000..c80073d
--- /dev/null
+++ b/lib/ExecutionEngine/SymbolResolverInterface.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_INTERFACE_H
+#define BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_INTERFACE_H
+
+#include <cstddef>
+
+namespace bcc {
+
+class SymbolResolverInterface {
+public:
+  static void *LookupFunction(void *pResolver, const char *pName) {
+    SymbolResolverInterface *resolver =
+        reinterpret_cast<SymbolResolverInterface*>(pResolver);
+    return ((resolver != NULL) ? resolver->getAddress(pName) : NULL);
+  }
+
+  // Should this be a const method?
+  virtual void *getAddress(const char *pName) = 0;
+
+  virtual ~SymbolResolverInterface() { }
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_INTERFACE_H
diff --git a/lib/ExecutionEngine/SymbolResolverProxy.cpp b/lib/ExecutionEngine/SymbolResolverProxy.cpp
new file mode 100644
index 0000000..29929d9
--- /dev/null
+++ b/lib/ExecutionEngine/SymbolResolverProxy.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SymbolResolverProxy.h"
+
+using namespace bcc;
+
+void *SymbolResolverProxy::getAddress(const char *pName) {
+  // Search the address of the symbol by following the chain of resolvers.
+  for (size_t i = 0; i < mChain.size(); i++) {
+    void *addr = mChain[i]->getAddress(pName);
+    if (addr != NULL) {
+      return addr;
+    }
+  }
+  // Symbol not found or there's no resolver containing in the chain.
+  return NULL;
+}
+
+void SymbolResolverProxy::chainResolver(SymbolResolverInterface &pResolver) {
+  mChain.push_back(&pResolver);
+}
diff --git a/lib/ExecutionEngine/SymbolResolverProxy.h b/lib/ExecutionEngine/SymbolResolverProxy.h
new file mode 100644
index 0000000..7bbdac5
--- /dev/null
+++ b/lib/ExecutionEngine/SymbolResolverProxy.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_PROXY_H
+#define BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_PROXY_H
+
+#include "DebugHelper.h"
+#include "SymbolResolverInterface.h"
+
+#include <utils/Vector.h>
+
+namespace bcc {
+
+class SymbolResolverProxy : public SymbolResolverInterface {
+private:
+  android::Vector<SymbolResolverInterface *> mChain;
+
+public:
+  SymbolResolverProxy() { }
+
+  void chainResolver(SymbolResolverInterface &pResolver);
+
+  virtual void *getAddress(const char *pName);
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_SYMBOL_RESOLVER_PROXY_H
diff --git a/lib/ExecutionEngine/SymbolResolvers.cpp b/lib/ExecutionEngine/SymbolResolvers.cpp
new file mode 100644
index 0000000..26941f2
--- /dev/null
+++ b/lib/ExecutionEngine/SymbolResolvers.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "SymbolResolvers.h"
+
+#include <dlfcn.h>
+
+#include <cassert>
+#include <cstdio>
+#include <new>
+
+using namespace bcc;
+
+//===----------------------------------------------------------------------===//
+// DyldSymbolResolver
+//===----------------------------------------------------------------------===//
+DyldSymbolResolver::DyldSymbolResolver(const char *pFileName,
+                                       bool pLazyBinding) : mError(NULL) {
+  int flags = (pLazyBinding) ? RTLD_LAZY : RTLD_NOW;
+
+  // Make the symbol within the given library to be local such that it won't
+  // be available for symbol resolution of subsequently loaded libraries.
+  flags |= RTLD_LOCAL;
+
+  mHandle = ::dlopen(pFileName, flags);
+  if (mHandle == NULL) {
+    const char *err = ::dlerror();
+
+#define DYLD_ERROR_MSG_PATTERN  "Failed to load %s! (%s)"
+    size_t error_length = ::strlen(DYLD_ERROR_MSG_PATTERN) +
+                          ::strlen(pFileName) + 1;
+    if (err != NULL) {
+      error_length += ::strlen(err);
+    }
+
+    mError = new (std::nothrow) char [error_length];
+    if (mError != NULL) {
+      ::snprintf(mError, error_length, DYLD_ERROR_MSG_PATTERN, pFileName,
+                 ((err != NULL) ? err : ""));
+    }
+  }
+#undef DYLD_ERROR_MSG_PATTERN
+}
+
+void *DyldSymbolResolver::getAddress(const char *pName) {
+  assert((mHandle != NULL) && "Invalid DyldSymbolResolver!");
+  return ::dlsym(mHandle, pName);
+}
+
+DyldSymbolResolver::~DyldSymbolResolver() {
+  ::dlclose(mHandle);
+  delete [] mError;
+}
diff --git a/lib/ExecutionEngine/SymbolResolvers.h b/lib/ExecutionEngine/SymbolResolvers.h
new file mode 100644
index 0000000..909211f
--- /dev/null
+++ b/lib/ExecutionEngine/SymbolResolvers.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright 2012, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H
+#define BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H
+
+#include <cstdlib>
+#include <cstring>
+
+#include "SymbolResolverInterface.h"
+
+namespace bcc {
+
+/*
+ * Symbol lookup via dlopen()/dlsym().
+ */
+class DyldSymbolResolver : public SymbolResolverInterface {
+public:
+  typedef void *HandleTy;
+
+private:
+  HandleTy mHandle;
+  char *mError;
+
+public:
+  // If pFileName is NULL, it will search symbol in the current process image.
+  DyldSymbolResolver(const char *pFileName, bool pLazyBinding = true);
+
+  virtual void *getAddress(const char *pName);
+
+  inline bool hasError() const
+  { return (mError != NULL); }
+  inline const char *getError() const
+  { return mError; }
+
+  ~DyldSymbolResolver();
+};
+
+/*
+ * Symbol lookup by searching through an array of SymbolMap.
+ */
+template<typename Subclass>
+class ArraySymbolResolver : public SymbolResolverInterface {
+public:
+  typedef struct {
+    // Symbol name
+    const char *mName;
+    // Symbol address
+    void *mAddr;
+  } SymbolMap;
+
+private:
+  // True if the symbol name is sorted in the array.
+  bool mSorted;
+
+  static int CompareSymbolName(const void *pA, const void *pB) {
+    return ::strcmp(reinterpret_cast<const SymbolMap *>(pA)->mName,
+                    reinterpret_cast<const SymbolMap *>(pB)->mName);
+  }
+
+public:
+  ArraySymbolResolver(bool pSorted = false) : mSorted(pSorted) { }
+
+  virtual void *getAddress(const char *pName) {
+    const SymbolMap *result = NULL;
+
+    if (mSorted) {
+      // Use binary search.
+      const SymbolMap key = { pName, NULL };
+
+      result = reinterpret_cast<SymbolMap *>(
+                   ::bsearch(&key, Subclass::SymbolArray,
+                                   Subclass::NumSymbols,
+                                   sizeof(SymbolMap),
+                                   CompareSymbolName));
+    } else {
+      // Use linear search.
+      for (size_t i = 0; i < Subclass::NumSymbols; i++) {
+        if (::strcmp(Subclass::SymbolArray[i].mName, pName) == 0) {
+          result = &Subclass::SymbolArray[i];
+          break;
+        }
+      }
+    }
+
+    return ((result != NULL) ? result->mAddr : NULL);
+  }
+};
+
+template<typename ContextTy = void *>
+class LookupFunctionSymbolResolver : public SymbolResolverInterface {
+public:
+  typedef void *(*LookupFunctionTy)(ContextTy pContext, const char *pName);
+
+private:
+  LookupFunctionTy mLookupFunc;
+  ContextTy mContext;
+
+public:
+  LookupFunctionSymbolResolver(LookupFunctionTy pLookupFunc = NULL,
+                               ContextTy pContext = NULL)
+    : mLookupFunc(pLookupFunc), mContext(pContext) { }
+
+  virtual void *getAddress(const char *pName) {
+    return ((mLookupFunc != NULL) ? mLookupFunc(mContext, pName) : NULL);
+  }
+
+  inline LookupFunctionTy getLookupFunction() const
+  { return mLookupFunc; }
+  inline ContextTy getContext() const
+  { return mContext; }
+
+  inline void setLookupFunction(LookupFunctionTy pLookupFunc)
+  { mLookupFunc = pLookupFunc; }
+  inline void setContext(ContextTy pContext)
+  { mContext = pContext; }
+};
+
+} // end namespace bcc
+
+#endif // BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H