• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 using namespace bcc;
28 
Load(void * pMemStart,size_t pMemSize,const char * pName,SymbolResolverInterface & pResolver,bool pEnableGDBDebug)29 ObjectLoader *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 
97 bail:
98   delete result;
99   return NULL;
100 }
101 
Load(FileBase & pFile,SymbolResolverInterface & pResolver,bool pEnableGDBDebug)102 ObjectLoader *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 
getSymbolAddress(const char * pName) const151 void *ObjectLoader::getSymbolAddress(const char *pName) const {
152   return mImpl->getSymbolAddress(pName);
153 }
154 
getSymbolSize(const char * pName) const155 size_t ObjectLoader::getSymbolSize(const char *pName) const {
156   return mImpl->getSymbolSize(pName);
157 }
158 
getSymbolNameList(android::Vector<const char * > & pNameList,SymbolType pType) const159 bool ObjectLoader::getSymbolNameList(android::Vector<const char *>& pNameList,
160                                      SymbolType pType) const {
161   return mImpl->getSymbolNameList(pNameList, pType);
162 }
163 
~ObjectLoader()164 ObjectLoader::~ObjectLoader() {
165   delete mImpl;
166   delete [] reinterpret_cast<uint8_t *>(mDebugImage);
167 }
168