blob: 708ded31d3918a1bacf1aaf8620f1558de448379 [file] [log] [blame]
Zonr Changbf6498e2012-04-13 14:35:45 +08001/*
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 "ObjectLoader.h"
18
19#include <utils/FileMap.h>
20
21#include "DebugHelper.h"
22#include "ELFObjectLoaderImpl.h"
23#include "FileBase.h"
24#include "GDBJITRegistrar.h"
25
26using namespace bcc;
27
28ObjectLoader *ObjectLoader::Load(void *pMemStart, size_t pMemSize,
29 const char *pName,
30 SymbolResolverInterface &pResolver,
31 bool pEnableGDBDebug) {
32 ObjectLoader *result = NULL;
33
34 // Check parameters.
35 if ((pMemStart == NULL) || (pMemSize <= 0)) {
36 ALOGE("Invalid memory '%s' was given to load (memory addr: %p, size: %u)",
37 pName, pMemStart, static_cast<unsigned>(pMemSize));
38 goto bail;
39 }
40
41 // Create result object
42 result = new (std::nothrow) ObjectLoader();
43 if (result == NULL) {
44 ALOGE("Out of memory when create object loader for %s!", pName);
45 goto bail;
46 }
47
48 // Currently, only ELF object loader is supported. Therefore, there's no codes
49 // to detect the object file type and to select the one appropriated. Directly
50 // try out the ELF object loader.
51 result->mImpl = new (std::nothrow) ELFObjectLoaderImpl();
52 if (result->mImpl == NULL) {
53 ALOGE("Out of memory when create ELF object loader for %s", pName);
54 goto bail;
55 }
56
57 // Load the object file.
58 if (!result->mImpl->load(pMemStart, pMemSize)) {
59 ALOGE("Failed to load %s!", pName);
60 goto bail;
61 }
62
63 // Perform relocation.
64 if (!result->mImpl->relocate(pResolver)) {
65 ALOGE("Error occurred when performs relocation on %s!", pName);
66 goto bail;
67 }
68
69 // GDB debugging is enabled. Note that error occurrs during the setup of
70 // debugging won't failed the object load. Only a warning is issued to notify
71 // that the debugging is disabled due to the failure.
72 if (pEnableGDBDebug) {
73 // GDB's JIT debugging requires the source object file corresponded to the
74 // process image desired to debug with. And some fields in the object file
75 // must be updated to record the runtime information after it's loaded into
76 // memory. For example, GDB's JIT debugging requires an ELF file with the
77 // value of sh_addr in the section header to be the memory address that the
78 // section lives in the process image. Therefore, a writable memory with its
79 // contents initialized to the contents of pFile is created.
80 result->mDebugImage = new (std::nothrow) uint8_t [ pMemSize ];
81 if (result->mDebugImage != NULL) {
82 ::memcpy(result->mDebugImage, pMemStart, pMemSize);
83 if (!result->mImpl->prepareDebugImage(result->mDebugImage, pMemSize)) {
84 ALOGW("GDB debug for %s is enabled by the user but won't work due to "
85 "failure debug image preparation!", pName);
86 } else {
87 registerObjectWithGDB(
88 reinterpret_cast<const ObjectBuffer *>(result->mDebugImage),
89 pMemSize);
90 }
91 }
92 }
93
94 return result;
95
96bail:
97 delete result;
98 return NULL;
99}
100
101ObjectLoader *ObjectLoader::Load(FileBase &pFile,
102 SymbolResolverInterface &pResolver,
103 bool pEnableGDBDebug) {
104 size_t file_size;
105 android::FileMap *file_map = NULL;
106 const char *input_filename = pFile.getName().c_str();
107 ObjectLoader *result = NULL;
108
109 // Check the inputs.
110 if (pFile.hasError()) {
111 ALOGE("Input file %s to the object loader is in the invalid state! (%s)",
112 input_filename, pFile.getErrorMessage().c_str());
113 return NULL;
114 }
115
116 // Get the file size.
117 file_size = pFile.getSize();
118 if (pFile.hasError()) {
119 ALOGE("Failed to get size of file %s! (%s)", input_filename,
120 pFile.getErrorMessage().c_str());
121 return NULL;
122 }
123
124 // Abort on empty file.
125 if (file_size <= 0) {
126 ALOGE("Empty file %s to the object loader.", input_filename);
127 return NULL;
128 }
129
130 // Create memory map for the input file.
131 file_map = pFile.createMap(0, file_size, /* pIsReadOnly */true);
132 if ((file_map == NULL) || pFile.hasError()) {
133 ALOGE("Failed to map the file %s to the memory! (%s)", input_filename,
134 pFile.getErrorMessage().c_str());
135 return NULL;
136 }
137
138 // Delegate the load request.
139 result = Load(file_map->getDataPtr(), file_size, input_filename, pResolver,
140 pEnableGDBDebug);
141
142 // No whether the load is successful or not, file_map is no longer needed. On
143 // success, there's a copy of the object corresponded to the pFile in the
144 // memory. Therefore, file_map can be safely released.
145 file_map->release();
146
147 return result;
148}
149
150void *ObjectLoader::getSymbolAddress(const char *pName) const {
151 return mImpl->getSymbolAddress(pName);
152}
153
154ObjectLoader::~ObjectLoader() {
155 delete mImpl;
156 delete [] reinterpret_cast<uint8_t *>(mDebugImage);
157}