/* * 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