C++程序  |  135行  |  3.63 KB

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