Home | History | Annotate | Download | only in ExecutionEngine
      1 /*
      2  * Copyright 2010, 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 "SourceInfo.h"
     18 
     19 #include "MCCacheWriter.h"
     20 #include "MCCacheReader.h"
     21 
     22 #include "DebugHelper.h"
     23 #include "ScriptCompiled.h"
     24 #include "Sha1Helper.h"
     25 
     26 #include <bcc/bcc.h>
     27 
     28 #include <llvm/Bitcode/ReaderWriter.h>
     29 #include <llvm/Module.h>
     30 #include <llvm/LLVMContext.h>
     31 #include <llvm/ADT/OwningPtr.h>
     32 #include <llvm/ADT/StringRef.h>
     33 #include <llvm/Support/MemoryBuffer.h>
     34 #include <llvm/Support/system_error.h>
     35 
     36 #include <stddef.h>
     37 #include <string.h>
     38 
     39 namespace bcc {
     40 
     41 
     42 SourceInfo *SourceInfo::createFromBuffer(char const *resName,
     43                                          char const *bitcode,
     44                                          size_t bitcodeSize,
     45                                          unsigned long flags) {
     46   SourceInfo *result = new SourceInfo();
     47 
     48   if (!result) {
     49     return NULL;
     50   }
     51 
     52   result->type = SourceKind::Buffer;
     53   result->buffer.resName = resName;
     54   result->buffer.bitcode = bitcode;
     55   result->buffer.bitcodeSize = bitcodeSize;
     56   result->flags = flags;
     57 
     58   if (!resName && !(flags & BCC_SKIP_DEP_SHA1)) {
     59     result->flags |= BCC_SKIP_DEP_SHA1;
     60 
     61     ALOGW("It is required to give resName for sha1 dependency check.\n");
     62     ALOGW("Sha1sum dependency check will be skipped.\n");
     63     ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
     64   }
     65 
     66   if (result->flags & BCC_SKIP_DEP_SHA1) {
     67     memset(result->sha1, '\0', 20);
     68   } else {
     69     calcSHA1(result->sha1, bitcode, bitcodeSize);
     70   }
     71 
     72   return result;
     73 }
     74 
     75 
     76 SourceInfo *SourceInfo::createFromFile(char const *path,
     77                                        unsigned long flags) {
     78   SourceInfo *result = new SourceInfo();
     79 
     80   if (!result) {
     81     return NULL;
     82   }
     83 
     84   result->type = SourceKind::File;
     85   result->file.path = path;
     86   result->flags = flags;
     87 
     88   memset(result->sha1, '\0', 20);
     89 
     90   if (!(result->flags & BCC_SKIP_DEP_SHA1)) {
     91     calcFileSHA1(result->sha1, path);
     92   }
     93 
     94   return result;
     95 }
     96 
     97 
     98 SourceInfo *SourceInfo::createFromModule(llvm::Module *module,
     99                                          unsigned long flags) {
    100   SourceInfo *result = new SourceInfo();
    101 
    102   if (!result) {
    103     return NULL;
    104   }
    105 
    106   result->type = SourceKind::Module;
    107   result->module = module;
    108   result->flags = flags;
    109 
    110   if (! (flags & BCC_SKIP_DEP_SHA1)) {
    111     result->flags |= BCC_SKIP_DEP_SHA1;
    112 
    113     ALOGW("Unable to calculate sha1sum for llvm::Module.\n");
    114     ALOGW("Sha1sum dependency check will be skipped.\n");
    115     ALOGW("Set BCC_SKIP_DEP_SHA1 for flags to surpress this warning.\n");
    116   }
    117 
    118   memset(result->sha1, '\0', 20);
    119 
    120   return result;
    121 }
    122 
    123 
    124 int SourceInfo::prepareModule(llvm::LLVMContext *context) {
    125   if (module)
    126     return 0;
    127 
    128   llvm::OwningPtr<llvm::MemoryBuffer> mem;
    129   std::string errmsg;
    130 
    131   switch (type) {
    132   case SourceKind::Buffer:
    133     {
    134       mem.reset(llvm::MemoryBuffer::getMemBuffer(
    135           llvm::StringRef(buffer.bitcode, buffer.bitcodeSize), "", false));
    136 
    137       if (!mem.get()) {
    138         ALOGE("Unable to MemoryBuffer::getMemBuffer(addr=%p, size=%lu)\n",
    139               buffer.bitcode, (unsigned long)buffer.bitcodeSize);
    140         return 1;
    141       }
    142     }
    143     break;
    144 
    145   case SourceKind::File:
    146     {
    147       if (llvm::error_code ec = llvm::MemoryBuffer::getFile(file.path, mem)) {
    148         ALOGE("Unable to MemoryBuffer::getFile(path=%s, %s)\n",
    149               file.path, ec.message().c_str());
    150         return 1;
    151       }
    152     }
    153     break;
    154 
    155   default:
    156     return 0;
    157     break;
    158   }
    159 
    160   if (context)
    161     shared_context = true;
    162   else
    163     context = new llvm::LLVMContext();
    164 
    165   module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg);
    166   if (module == NULL) {
    167     ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
    168     if (!shared_context)
    169       delete context;
    170   }
    171 
    172   return (module == NULL);
    173 }
    174 
    175 SourceInfo::~SourceInfo() {
    176   if (module != NULL) {
    177     llvm::LLVMContext *context = &module->getContext();
    178     delete module;
    179     if (!shared_context)
    180       delete context;
    181   }
    182 }
    183 
    184 template <typename T> void SourceInfo::introDependency(T &checker) {
    185   if (flags & BCC_SKIP_DEP_SHA1) {
    186     return;
    187   }
    188 
    189   switch (type) {
    190   case SourceKind::Buffer:
    191     checker.addDependency(BCC_APK_RESOURCE, buffer.resName, sha1);
    192     break;
    193 
    194   case SourceKind::File:
    195     checker.addDependency(BCC_FILE_RESOURCE, file.path, sha1);
    196     break;
    197 
    198   default:
    199     break;
    200   }
    201 }
    202 
    203 template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
    204 template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
    205 
    206 
    207 } // namespace bcc
    208