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
19862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <dlfcn.h>
20862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
21862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cassert>
22862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <cstdio>
23862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#include <new>
24862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
25862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changusing namespace bcc;
26862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
27862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang//===----------------------------------------------------------------------===//
28862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang// DyldSymbolResolver
29862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang//===----------------------------------------------------------------------===//
30862f3ba997e14b61dce9d341a75688951e67fd1bZonr ChangDyldSymbolResolver::DyldSymbolResolver(const char *pFileName,
31862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                                       bool pLazyBinding) : mError(NULL) {
32862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  int flags = (pLazyBinding) ? RTLD_LAZY : RTLD_NOW;
33862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
34862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // Make the symbol within the given library to be local such that it won't
35862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  // be available for symbol resolution of subsequently loaded libraries.
36862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  flags |= RTLD_LOCAL;
37862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
38862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  mHandle = ::dlopen(pFileName, flags);
39862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  if (mHandle == NULL) {
40862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    const char *err = ::dlerror();
41862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
42862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#define DYLD_ERROR_MSG_PATTERN  "Failed to load %s! (%s)"
43862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    size_t error_length = ::strlen(DYLD_ERROR_MSG_PATTERN) +
44862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                          ::strlen(pFileName) + 1;
45862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    if (err != NULL) {
46862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      error_length += ::strlen(err);
47862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    }
48862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
49862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    mError = new (std::nothrow) char [error_length];
50862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    if (mError != NULL) {
51862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang      ::snprintf(mError, error_length, DYLD_ERROR_MSG_PATTERN, pFileName,
52862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang                 ((err != NULL) ? err : ""));
53862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang    }
54862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  }
55862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang#undef DYLD_ERROR_MSG_PATTERN
56862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
57862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
58862f3ba997e14b61dce9d341a75688951e67fd1bZonr Changvoid *DyldSymbolResolver::getAddress(const char *pName) {
59862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  assert((mHandle != NULL) && "Invalid DyldSymbolResolver!");
60862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  return ::dlsym(mHandle, pName);
61862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
62862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang
63862f3ba997e14b61dce9d341a75688951e67fd1bZonr ChangDyldSymbolResolver::~DyldSymbolResolver() {
64862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  ::dlclose(mHandle);
65862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang  delete [] mError;
66862f3ba997e14b61dce9d341a75688951e67fd1bZonr Chang}
67