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