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