1862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang/*
2862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Copyright 2012, The Android Open Source Project
3862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang *
4862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Licensed under the Apache License, Version 2.0 (the "License");
5862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * you may not use this file except in compliance with the License.
6862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * You may obtain a copy of the License at
7862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang *
8862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang *     http://www.apache.org/licenses/LICENSE-2.0
9862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang *
10862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Unless required by applicable law or agreed to in writing, software
11862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * distributed under the License is distributed on an "AS IS" BASIS,
12862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * See the License for the specific language governing permissions and
14862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * limitations under the License.
15862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang */
16862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
17862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#ifndef BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H
18862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#define BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H
19862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
20862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cstdlib>
21862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cstring>
22862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
23862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include "SymbolResolverInterface.h"
24862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
25862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changnamespace bcc {
26862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
27862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang/*
28862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Symbol lookup via dlopen()/dlsym().
29862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang */
30862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changclass DyldSymbolResolver : public SymbolResolverInterface {
31862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
32862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  typedef void *HandleTy;
33862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
34862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changprivate:
35862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  HandleTy mHandle;
36862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  char *mError;
37862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
38862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
39862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // If pFileName is NULL, it will search symbol in the current process image.
40862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  DyldSymbolResolver(const char *pFileName, bool pLazyBinding = true);
41862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
42862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  virtual void *getAddress(const char *pName);
43862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
44862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline bool hasError() const
45862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { return (mError != NULL); }
46862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline const char *getError() const
47862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { return mError; }
48862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
49862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  ~DyldSymbolResolver();
50862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang};
51862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
52862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang/*
53862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang * Symbol lookup by searching through an array of SymbolMap.
54862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang */
55862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changtemplate<typename Subclass>
56862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changclass ArraySymbolResolver : public SymbolResolverInterface {
57862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
58862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  typedef struct {
59862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    // Symbol name
60862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    const char *mName;
61862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    // Symbol address
62862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    void *mAddr;
63862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  } SymbolMap;
64862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
65862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changprivate:
66862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // True if the symbol name is sorted in the array.
67862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  bool mSorted;
68862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
69862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  static int CompareSymbolName(const void *pA, const void *pB) {
70862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    return ::strcmp(reinterpret_cast<const SymbolMap *>(pA)->mName,
71862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                    reinterpret_cast<const SymbolMap *>(pB)->mName);
72862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  }
73862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
74862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
75862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  ArraySymbolResolver(bool pSorted = false) : mSorted(pSorted) { }
76862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
77862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  virtual void *getAddress(const char *pName) {
78862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    const SymbolMap *result = NULL;
79862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
80862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    if (mSorted) {
81862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      // Use binary search.
82862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      const SymbolMap key = { pName, NULL };
83862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
84862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      result = reinterpret_cast<SymbolMap *>(
85862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                   ::bsearch(&key, Subclass::SymbolArray,
86862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                                   Subclass::NumSymbols,
87862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                                   sizeof(SymbolMap),
88862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                                   CompareSymbolName));
89862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    } else {
90862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      // Use linear search.
91862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      for (size_t i = 0; i < Subclass::NumSymbols; i++) {
92862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang        if (::strcmp(Subclass::SymbolArray[i].mName, pName) == 0) {
93862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang          result = &Subclass::SymbolArray[i];
94862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang          break;
95862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang        }
96862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      }
97862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    }
98862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
99862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    return ((result != NULL) ? result->mAddr : NULL);
100862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  }
101862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang};
102862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
103862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changtemplate<typename ContextTy = void *>
104862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changclass LookupFunctionSymbolResolver : public SymbolResolverInterface {
105862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
106862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  typedef void *(*LookupFunctionTy)(ContextTy pContext, const char *pName);
107862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
108862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changprivate:
109862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  LookupFunctionTy mLookupFunc;
110862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  ContextTy mContext;
111862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
112862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changpublic:
113862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  LookupFunctionSymbolResolver(LookupFunctionTy pLookupFunc = NULL,
114862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                               ContextTy pContext = NULL)
115862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    : mLookupFunc(pLookupFunc), mContext(pContext) { }
116862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
117862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  virtual void *getAddress(const char *pName) {
118862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    return ((mLookupFunc != NULL) ? mLookupFunc(mContext, pName) : NULL);
119862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  }
120862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
121862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline LookupFunctionTy getLookupFunction() const
122862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { return mLookupFunc; }
123862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline ContextTy getContext() const
124862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { return mContext; }
125862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
126862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline void setLookupFunction(LookupFunctionTy pLookupFunc)
127862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { mLookupFunc = pLookupFunc; }
128862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  inline void setContext(ContextTy pContext)
129862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  { mContext = pContext; }
130862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang};
131862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
132862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang} // end namespace bcc
133862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
134862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#endif // BCC_EXECUTION_ENGINE_SYMBOL_RESOLVERS_H
135