Home | History | Annotate | Download | only in Renderscript
      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/Renderscript/RSExecutable.h"
     18 
     19 #include "bcc/Config/Config.h"
     20 #include "bcc/Support/Disassembler.h"
     21 #include "bcc/Support/FileBase.h"
     22 #include "bcc/Support/Log.h"
     23 #include "bcc/Support/OutputFile.h"
     24 #include "bcc/ExecutionEngine/SymbolResolverProxy.h"
     25 
     26 #include <utils/String8.h>
     27 
     28 using namespace bcc;
     29 
     30 const char *RSExecutable::SpecialFunctionNames[] = {
     31   "root",      // Graphics drawing function or compute kernel.
     32   "init",      // Initialization routine called implicitly on startup.
     33   ".rs.dtor",  // Static global destructor for a script instance.
     34   ".rs.info",  // Variable containing string of RS metadata info.
     35   NULL         // Must be NULL-terminated.
     36 };
     37 
     38 RSExecutable *RSExecutable::Create(RSInfo &pInfo,
     39                                    FileBase &pObjFile,
     40                                    SymbolResolverProxy &pResolver) {
     41   // Load the object file. Enable the GDB's JIT debugging if the script contains
     42   // debug information.
     43   ObjectLoader *loader = ObjectLoader::Load(pObjFile,
     44                                             pResolver,
     45                                             pInfo.hasDebugInformation());
     46   if (loader == NULL) {
     47     return NULL;
     48   }
     49 
     50   // Now, all things required to build a RSExecutable object are ready.
     51   RSExecutable *result = new (std::nothrow) RSExecutable(pInfo,
     52                                                          pObjFile,
     53                                                          *loader);
     54   if (result == NULL) {
     55     ALOGE("Out of memory when create object to hold RS result file for %s!",
     56           pObjFile.getName().c_str());
     57     return NULL;
     58   }
     59 
     60   unsigned idx;
     61   // Resolve addresses of RS export vars.
     62   idx = 0;
     63   const RSInfo::ExportVarNameListTy &export_var_names =
     64       pInfo.getExportVarNames();
     65   for (RSInfo::ExportVarNameListTy::const_iterator
     66            var_iter = export_var_names.begin(),
     67            var_end = export_var_names.end(); var_iter != var_end;
     68        var_iter++, idx++) {
     69     const char *name = *var_iter;
     70     void *addr = result->getSymbolAddress(name);
     71     if (addr == NULL) {
     72         //ALOGW("RS export var at entry #%u named %s cannot be found in the result "
     73         //"object!", idx, name);
     74     }
     75     result->mExportVarAddrs.push_back(addr);
     76   }
     77 
     78   // Resolve addresses of RS export functions.
     79   idx = 0;
     80   const RSInfo::ExportFuncNameListTy &export_func_names =
     81       pInfo.getExportFuncNames();
     82   for (RSInfo::ExportFuncNameListTy::const_iterator
     83            func_iter = export_func_names.begin(),
     84            func_end = export_func_names.end(); func_iter != func_end;
     85        func_iter++, idx++) {
     86     const char *name = *func_iter;
     87     void *addr = result->getSymbolAddress(name);
     88     if (addr == NULL) {
     89         //      ALOGW("RS export func at entry #%u named %s cannot be found in the result"
     90         //" object!", idx, name);
     91     }
     92     result->mExportFuncAddrs.push_back(addr);
     93   }
     94 
     95   // Resolve addresses of expanded RS foreach function.
     96   idx = 0;
     97   const RSInfo::ExportForeachFuncListTy &export_foreach_funcs =
     98       pInfo.getExportForeachFuncs();
     99   for (RSInfo::ExportForeachFuncListTy::const_iterator
    100            foreach_iter = export_foreach_funcs.begin(),
    101            foreach_end = export_foreach_funcs.end();
    102        foreach_iter != foreach_end; foreach_iter++, idx++) {
    103     const char *func_name = foreach_iter->first;
    104     android::String8 expanded_func_name(func_name);
    105     expanded_func_name.append(".expand");
    106     void *addr = result->getSymbolAddress(expanded_func_name.string());
    107     if (addr == NULL) {
    108         //      ALOGW("Expanded RS foreach at entry #%u named %s cannot be found in the "
    109         //            "result object!", idx, expanded_func_name.string());
    110     }
    111     result->mExportForeachFuncAddrs.push_back(addr);
    112   }
    113 
    114   // Copy pragma key/value pairs from RSInfo::getPragmas() into mPragmaKeys and
    115   // mPragmaValues, respectively.
    116   const RSInfo::PragmaListTy &pragmas = pInfo.getPragmas();
    117   for (RSInfo::PragmaListTy::const_iterator pragma_iter = pragmas.begin(),
    118           pragma_end = pragmas.end(); pragma_iter != pragma_end;
    119        pragma_iter++){
    120     result->mPragmaKeys.push_back(pragma_iter->first);
    121     result->mPragmaValues.push_back(pragma_iter->second);
    122   }
    123 
    124   return result;
    125 }
    126 
    127 bool RSExecutable::syncInfo(bool pForce) {
    128   if (!pForce && !mIsInfoDirty) {
    129     return true;
    130   }
    131 
    132   android::String8 info_path = RSInfo::GetPath(mObjFile->getName().c_str());
    133   OutputFile info_file(info_path.string(), FileBase::kTruncate);
    134 
    135   if (info_file.hasError()) {
    136     ALOGE("Failed to open the info file %s for write! (%s)", info_path.string(),
    137           info_file.getErrorMessage().c_str());
    138     return false;
    139   }
    140 
    141   // Operation to the RS info file need to acquire the lock on the output file
    142   // first.
    143   if (!mObjFile->lock(FileBase::kWriteLock)) {
    144     ALOGE("Write to RS info file %s required the acquisition of the write lock "
    145           "on %s but got failure! (%s)", info_path.string(),
    146           mObjFile->getName().c_str(), info_file.getErrorMessage().c_str());
    147     return false;
    148   }
    149 
    150   // Perform the write.
    151   if (!mInfo->write(info_file)) {
    152     ALOGE("Failed to sync the RS info file %s!", info_path.string());
    153     mObjFile->unlock();
    154     return false;
    155   }
    156 
    157   mObjFile->unlock();
    158   mIsInfoDirty = false;
    159   return true;
    160 }
    161 
    162 void RSExecutable::dumpDisassembly(OutputFile &pOutput) const {
    163 #if DEBUG_MC_DISASSEMBLER
    164   if (pOutput.hasError()) {
    165     return;
    166   }
    167 
    168   // Get MC codegen emitted function name list.
    169   android::Vector<const char *> func_list;
    170 
    171   if (!mLoader->getSymbolNameList(func_list, ObjectLoader::kFunctionType)) {
    172       ALOGW("Failed to get the list of function name in %s for disassembly!",
    173             mObjFile->getName().c_str());
    174   } else {
    175     // Disassemble each function
    176     for (size_t i = 0, e = func_list.size(); i != e; i++) {
    177       const char* func_name = func_list[i];
    178       void *func = mLoader->getSymbolAddress(func_name);
    179       size_t func_size = mLoader->getSymbolSize(func_name);
    180 
    181       if (func == NULL) {
    182         continue;
    183       }
    184       DisassembleResult result =
    185           Disassemble(pOutput, DEFAULT_TARGET_TRIPLE_STRING, func_name,
    186                       reinterpret_cast<const uint8_t *>(func), func_size);
    187 
    188       if (result != kDisassembleSuccess) {
    189           ALOGW("Failed to disassemble the function %s in %s (error code=%zu)!",
    190                 func_name, mObjFile->getName().c_str(), static_cast<size_t>(result));
    191 
    192         if (result != kDisassembleInvalidInstruction) {
    193             ALOGW("And the error occured in disassembler is fatal. Abort "
    194                   "disassembler on remaining functions!");
    195           break;
    196         }
    197       }
    198     }
    199   }
    200 #endif
    201   return;
    202 }
    203 
    204 RSExecutable::~RSExecutable() {
    205   syncInfo();
    206   delete mInfo;
    207   delete mObjFile;
    208   delete mLoader;
    209 }
    210