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