Zonr Chang | bf6498e | 2012-04-13 14:35:45 +0800 | [diff] [blame^] | 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 "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 | |
| 26 | using namespace bcc; |
| 27 | |
| 28 | ObjectLoader *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 | |
| 96 | bail: |
| 97 | delete result; |
| 98 | return NULL; |
| 99 | } |
| 100 | |
| 101 | ObjectLoader *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 | |
| 150 | void *ObjectLoader::getSymbolAddress(const char *pName) const { |
| 151 | return mImpl->getSymbolAddress(pName); |
| 152 | } |
| 153 | |
| 154 | ObjectLoader::~ObjectLoader() { |
| 155 | delete mImpl; |
| 156 | delete [] reinterpret_cast<uint8_t *>(mDebugImage); |
| 157 | } |