10f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang/* 20f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Copyright 2012, The Android Open Source Project 30f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * 40f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Licensed under the Apache License, Version 2.0 (the "License"); 50f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * you may not use this file except in compliance with the License. 60f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * You may obtain a copy of the License at 70f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * 80f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * http://www.apache.org/licenses/LICENSE-2.0 90f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * 100f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * Unless required by applicable law or agreed to in writing, software 110f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * distributed under the License is distributed on an "AS IS" BASIS, 120f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 130f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * See the License for the specific language governing permissions and 140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang * limitations under the License. 150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang */ 160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 17c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/ObjectLoader.h" 180f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 190f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include <utils/FileMap.h> 200f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 21c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/ExecutionEngine/GDBJITRegistrar.h" 22c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang#include "bcc/Support/FileBase.h" 23ef73a242762bcd8113b9b65ceccbe7d909b5acbcZonr Chang#include "bcc/Support/Log.h" 24c72c4ddfcd79c74f70713da91a69569451b5c19eZonr Chang 250f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang#include "ELFObjectLoaderImpl.h" 260f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 270f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changusing namespace bcc; 280f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 290f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr ChangObjectLoader *ObjectLoader::Load(void *pMemStart, size_t pMemSize, 300f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang const char *pName, 310f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang SymbolResolverInterface &pResolver, 320f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang bool pEnableGDBDebug) { 330f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ObjectLoader *result = NULL; 340f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 350f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Check parameters. 360f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if ((pMemStart == NULL) || (pMemSize <= 0)) { 370f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Invalid memory '%s' was given to load (memory addr: %p, size: %u)", 380f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang pName, pMemStart, static_cast<unsigned>(pMemSize)); 390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang goto bail; 400f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 420f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Create result object 430f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang result = new (std::nothrow) ObjectLoader(); 440f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (result == NULL) { 450f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Out of memory when create object loader for %s!", pName); 460f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang goto bail; 470f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 480f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 490f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Currently, only ELF object loader is supported. Therefore, there's no codes 500f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // to detect the object file type and to select the one appropriated. Directly 510f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // try out the ELF object loader. 520f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang result->mImpl = new (std::nothrow) ELFObjectLoaderImpl(); 530f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (result->mImpl == NULL) { 540f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Out of memory when create ELF object loader for %s", pName); 550f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang goto bail; 560f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 570f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 580f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Load the object file. 590f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (!result->mImpl->load(pMemStart, pMemSize)) { 600f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Failed to load %s!", pName); 610f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang goto bail; 620f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 630f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 640f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Perform relocation. 650f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (!result->mImpl->relocate(pResolver)) { 660f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Error occurred when performs relocation on %s!", pName); 670f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang goto bail; 680f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 690f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 700f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // GDB debugging is enabled. Note that error occurrs during the setup of 710f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // debugging won't failed the object load. Only a warning is issued to notify 720f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // that the debugging is disabled due to the failure. 730f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (pEnableGDBDebug) { 740f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // GDB's JIT debugging requires the source object file corresponded to the 750f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // process image desired to debug with. And some fields in the object file 760f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // must be updated to record the runtime information after it's loaded into 770f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // memory. For example, GDB's JIT debugging requires an ELF file with the 780f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // value of sh_addr in the section header to be the memory address that the 790f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // section lives in the process image. Therefore, a writable memory with its 800f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // contents initialized to the contents of pFile is created. 810f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang result->mDebugImage = new (std::nothrow) uint8_t [ pMemSize ]; 820f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (result->mDebugImage != NULL) { 830f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ::memcpy(result->mDebugImage, pMemStart, pMemSize); 840f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (!result->mImpl->prepareDebugImage(result->mDebugImage, pMemSize)) { 850f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGW("GDB debug for %s is enabled by the user but won't work due to " 860f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang "failure debug image preparation!", pName); 870f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } else { 880f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang registerObjectWithGDB( 890f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang reinterpret_cast<const ObjectBuffer *>(result->mDebugImage), 900f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang pMemSize); 910f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 920f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 930f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 940f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 950f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return result; 960f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 970f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changbail: 980f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang delete result; 990f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return NULL; 1000f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang} 1010f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1020f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr ChangObjectLoader *ObjectLoader::Load(FileBase &pFile, 1030f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang SymbolResolverInterface &pResolver, 1040f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang bool pEnableGDBDebug) { 1050f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang size_t file_size; 1060f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang android::FileMap *file_map = NULL; 1070f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang const char *input_filename = pFile.getName().c_str(); 1080f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ObjectLoader *result = NULL; 1090f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1100f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Check the inputs. 1110f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (pFile.hasError()) { 1120f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Input file %s to the object loader is in the invalid state! (%s)", 1130f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang input_filename, pFile.getErrorMessage().c_str()); 1140f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return NULL; 1150f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 1160f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1170f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Get the file size. 1180f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang file_size = pFile.getSize(); 1190f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (pFile.hasError()) { 1200f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Failed to get size of file %s! (%s)", input_filename, 1210f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang pFile.getErrorMessage().c_str()); 1220f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return NULL; 1230f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 1240f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1250f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Abort on empty file. 1260f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if (file_size <= 0) { 1270f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Empty file %s to the object loader.", input_filename); 1280f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return NULL; 1290f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 1300f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1310f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Create memory map for the input file. 1320f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang file_map = pFile.createMap(0, file_size, /* pIsReadOnly */true); 1330f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang if ((file_map == NULL) || pFile.hasError()) { 1340f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang ALOGE("Failed to map the file %s to the memory! (%s)", input_filename, 1350f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang pFile.getErrorMessage().c_str()); 1360f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return NULL; 1370f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang } 1380f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1390f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // Delegate the load request. 1400f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang result = Load(file_map->getDataPtr(), file_size, input_filename, pResolver, 1410f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang pEnableGDBDebug); 1420f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1430f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // No whether the load is successful or not, file_map is no longer needed. On 1440f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // success, there's a copy of the object corresponded to the pFile in the 1450f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang // memory. Therefore, file_map can be safely released. 1460f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang file_map->release(); 1470f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1480f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return result; 1490f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang} 1500f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1510f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Changvoid *ObjectLoader::getSymbolAddress(const char *pName) const { 1520f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang return mImpl->getSymbolAddress(pName); 1530f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang} 1540f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang 1559795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaosize_t ObjectLoader::getSymbolSize(const char *pName) const { 1569795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao return mImpl->getSymbolSize(pName); 1579795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao} 1589795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao 1599795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liaobool ObjectLoader::getSymbolNameList(android::Vector<const char *>& pNameList, 1609795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao SymbolType pType) const { 1619795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao return mImpl->getSymbolNameList(pNameList, pType); 1629795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao} 1639795754a34648d962f00ced51183b759b9eaf2b2Shih-wei Liao 1640f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr ChangObjectLoader::~ObjectLoader() { 1650f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang delete mImpl; 1660f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang delete [] reinterpret_cast<uint8_t *>(mDebugImage); 1670f9cad99f9e3c4db42e9836cc0e316c3a84448f5Zonr Chang} 168