• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
createFromBuffer(char const * resName,char const * bitcode,size_t bitcodeSize,unsigned long flags)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 
createFromFile(char const * path,unsigned long flags)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 
createFromModule(llvm::Module * module,unsigned long flags)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 
prepareModule(llvm::LLVMContext * context)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 
~SourceInfo()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 
introDependency(T & checker)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