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