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