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
17c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/SymbolResolvers.h"
18862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
1948cd745480738c026312931877ecb8ebecb1c64eStephen Hines#if !defined(_WIN32)  /* TODO create a HAVE_DLFCN_H */
20862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <dlfcn.h>
2148cd745480738c026312931877ecb8ebecb1c64eStephen Hines#else
2248cd745480738c026312931877ecb8ebecb1c64eStephen Hines/* TODO hack: definitions from bionic/libc/include/dlfcn.h */
2348cd745480738c026312931877ecb8ebecb1c64eStephen Hinesvoid* dlopen(const char*  filename, int flag) {
2448cd745480738c026312931877ecb8ebecb1c64eStephen Hines  return NULL;
2548cd745480738c026312931877ecb8ebecb1c64eStephen Hines}
2648cd745480738c026312931877ecb8ebecb1c64eStephen Hines
2748cd745480738c026312931877ecb8ebecb1c64eStephen Hinesint dlclose(void*  handle) {
2848cd745480738c026312931877ecb8ebecb1c64eStephen Hines  return -1;
2948cd745480738c026312931877ecb8ebecb1c64eStephen Hines}
3048cd745480738c026312931877ecb8ebecb1c64eStephen Hines
3148cd745480738c026312931877ecb8ebecb1c64eStephen Hinesconst char* dlerror(void) {
3248cd745480738c026312931877ecb8ebecb1c64eStephen Hines  return "Unspecified error!";
3348cd745480738c026312931877ecb8ebecb1c64eStephen Hines}
3448cd745480738c026312931877ecb8ebecb1c64eStephen Hines
3548cd745480738c026312931877ecb8ebecb1c64eStephen Hinesvoid* dlsym(void*  handle, const char*  symbol) {
3648cd745480738c026312931877ecb8ebecb1c64eStephen Hines  return NULL;
3748cd745480738c026312931877ecb8ebecb1c64eStephen Hines}
3848cd745480738c026312931877ecb8ebecb1c64eStephen Hines
3948cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_NOW    0
4048cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_LAZY   1
4148cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_LOCAL  0
4248cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_GLOBAL 2
4348cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_DEFAULT  ((void*) 0xffffffff)
4448cd745480738c026312931877ecb8ebecb1c64eStephen Hines#define RTLD_NEXT     ((void*) 0xfffffffe)
4548cd745480738c026312931877ecb8ebecb1c64eStephen Hines#endif
46862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
47862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cassert>
48862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cstdio>
49862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <new>
50862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
51862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changusing namespace bcc;
52862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
53862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang//===----------------------------------------------------------------------===//
54862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang// DyldSymbolResolver
55862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang//===----------------------------------------------------------------------===//
56862f3ba997e14b61dce9d341a75688951e67fd1bZonr ChangDyldSymbolResolver::DyldSymbolResolver(const char *pFileName,
57862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                                       bool pLazyBinding) : mError(NULL) {
58862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  int flags = (pLazyBinding) ? RTLD_LAZY : RTLD_NOW;
59862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
60862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // Make the symbol within the given library to be local such that it won't
61862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // be available for symbol resolution of subsequently loaded libraries.
62862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  flags |= RTLD_LOCAL;
63862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
64862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  mHandle = ::dlopen(pFileName, flags);
65862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  if (mHandle == NULL) {
66862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    const char *err = ::dlerror();
67862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
68862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#define DYLD_ERROR_MSG_PATTERN  "Failed to load %s! (%s)"
69862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    size_t error_length = ::strlen(DYLD_ERROR_MSG_PATTERN) +
70862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                          ::strlen(pFileName) + 1;
71862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    if (err != NULL) {
72862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      error_length += ::strlen(err);
73862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    }
74862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
75862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    mError = new (std::nothrow) char [error_length];
76862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    if (mError != NULL) {
77862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      ::snprintf(mError, error_length, DYLD_ERROR_MSG_PATTERN, pFileName,
78862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                 ((err != NULL) ? err : ""));
79862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    }
80862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  }
81862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#undef DYLD_ERROR_MSG_PATTERN
82862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
83862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
84862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changvoid *DyldSymbolResolver::getAddress(const char *pName) {
85862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  assert((mHandle != NULL) && "Invalid DyldSymbolResolver!");
86862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  return ::dlsym(mHandle, pName);
87862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
88862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
89862f3ba997e14b61dce9d341a75688951e67fd1bZonr ChangDyldSymbolResolver::~DyldSymbolResolver() {
90bae0ae1794b07482c85211c3b4d8f5e8e4da8f69Stephen Hines  if (mHandle != NULL) {
91bae0ae1794b07482c85211c3b4d8f5e8e4da8f69Stephen Hines    ::dlclose(mHandle);
92bae0ae1794b07482c85211c3b4d8f5e8e4da8f69Stephen Hines    mHandle = NULL;
93bae0ae1794b07482c85211c3b4d8f5e8e4da8f69Stephen Hines  }
94862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  delete [] mError;
95862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
96