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