1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "bcc/ExecutionEngine/ObjectLoader.h"
18
19#include <utils/FileMap.h>
20
21#include "bcc/ExecutionEngine/GDBJITRegistrar.h"
22#include "bcc/Support/FileBase.h"
23#include "bcc/Support/Log.h"
24
25#include "ELFObjectLoaderImpl.h"
26
27using namespace bcc;
28
29ObjectLoader *ObjectLoader::Load(void *pMemStart, size_t pMemSize,
30                                 const char *pName,
31                                 SymbolResolverInterface &pResolver,
32                                 bool pEnableGDBDebug) {
33  ObjectLoader *result = NULL;
34
35  // Check parameters.
36  if ((pMemStart == NULL) || (pMemSize <= 0)) {
37    ALOGE("Invalid memory '%s' was given to load (memory addr: %p, size: %u)",
38          pName, pMemStart, static_cast<unsigned>(pMemSize));
39    goto bail;
40  }
41
42  // Create result object
43  result = new (std::nothrow) ObjectLoader();
44  if (result == NULL) {
45    ALOGE("Out of memory when create object loader for %s!", pName);
46    goto bail;
47  }
48
49  // Currently, only ELF object loader is supported. Therefore, there's no codes
50  // to detect the object file type and to select the one appropriated. Directly
51  // try out the ELF object loader.
52  result->mImpl = new (std::nothrow) ELFObjectLoaderImpl();
53  if (result->mImpl == NULL) {
54    ALOGE("Out of memory when create ELF object loader for %s", pName);
55    goto bail;
56  }
57
58  // Load the object file.
59  if (!result->mImpl->load(pMemStart, pMemSize)) {
60    ALOGE("Failed to load %s!", pName);
61    goto bail;
62  }
63
64  // Perform relocation.
65  if (!result->mImpl->relocate(pResolver)) {
66    ALOGE("Error occurred when performs relocation on %s!", pName);
67    goto bail;
68  }
69
70  // GDB debugging is enabled. Note that error occurrs during the setup of
71  // debugging won't failed the object load. Only a warning is issued to notify
72  // that the debugging is disabled due to the failure.
73  if (pEnableGDBDebug) {
74    // GDB's JIT debugging requires the source object file corresponded to the
75    // process image desired to debug with. And some fields in the object file
76    // must be updated to record the runtime information after it's loaded into
77    // memory. For example, GDB's JIT debugging requires an ELF file with the
78    // value of sh_addr in the section header to be the memory address that the
79    // section lives in the process image. Therefore, a writable memory with its
80    // contents initialized to the contents of pFile is created.
81    result->mDebugImage = new (std::nothrow) uint8_t [ pMemSize ];
82    if (result->mDebugImage != NULL) {
83      ::memcpy(result->mDebugImage, pMemStart, pMemSize);
84      if (!result->mImpl->prepareDebugImage(result->mDebugImage, pMemSize)) {
85        ALOGW("GDB debug for %s is enabled by the user but won't work due to "
86              "failure debug image preparation!", pName);
87      } else {
88        registerObjectWithGDB(
89            reinterpret_cast<const ObjectBuffer *>(result->mDebugImage),
90            pMemSize);
91      }
92    }
93  }
94
95  return result;
96
97bail:
98  delete result;
99  return NULL;
100}
101
102ObjectLoader *ObjectLoader::Load(FileBase &pFile,
103                                 SymbolResolverInterface &pResolver,
104                                 bool pEnableGDBDebug) {
105  size_t file_size;
106  android::FileMap *file_map = NULL;
107  const char *input_filename = pFile.getName().c_str();
108  ObjectLoader *result = NULL;
109
110  // Check the inputs.
111  if (pFile.hasError()) {
112    ALOGE("Input file %s to the object loader is in the invalid state! (%s)",
113          input_filename, pFile.getErrorMessage().c_str());
114    return NULL;
115  }
116
117  // Get the file size.
118  file_size = pFile.getSize();
119  if (pFile.hasError()) {
120    ALOGE("Failed to get size of file %s! (%s)", input_filename,
121          pFile.getErrorMessage().c_str());
122    return NULL;
123  }
124
125  // Abort on empty file.
126  if (file_size <= 0) {
127    ALOGE("Empty file %s to the object loader.", input_filename);
128    return NULL;
129  }
130
131  // Create memory map for the input file.
132  file_map = pFile.createMap(0, file_size, /* pIsReadOnly */true);
133  if ((file_map == NULL) || pFile.hasError())  {
134    ALOGE("Failed to map the file %s to the memory! (%s)", input_filename,
135          pFile.getErrorMessage().c_str());
136    return NULL;
137  }
138
139  // Delegate the load request.
140  result = Load(file_map->getDataPtr(), file_size, input_filename, pResolver,
141                pEnableGDBDebug);
142
143  // No whether the load is successful or not, file_map is no longer needed. On
144  // success, there's a copy of the object corresponded to the pFile in the
145  // memory. Therefore, file_map can be safely released.
146  file_map->release();
147
148  return result;
149}
150
151void *ObjectLoader::getSymbolAddress(const char *pName) const {
152  return mImpl->getSymbolAddress(pName);
153}
154
155size_t ObjectLoader::getSymbolSize(const char *pName) const {
156  return mImpl->getSymbolSize(pName);
157}
158
159bool ObjectLoader::getSymbolNameList(android::Vector<const char *>& pNameList,
160                                     SymbolType pType) const {
161  return mImpl->getSymbolNameList(pNameList, pType);
162}
163
164ObjectLoader::~ObjectLoader() {
165  delete mImpl;
166  delete [] reinterpret_cast<uint8_t *>(mDebugImage);
167}
168