blob: 1d0a950f10f96d9f6652cc5f39f752c7a8d6d60c [file] [log] [blame]
Stephen Hinesead5ccb2012-05-03 12:30:38 -07001/*
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>
Stephen Hines274926b2012-05-03 12:30:46 -070030#include <llvm/LLVMContext.h>
Stephen Hinesead5ccb2012-05-03 12:30:38 -070031#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
39namespace bcc {
40
41
42SourceInfo *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
76SourceInfo *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
98SourceInfo *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
Stephen Hines274926b2012-05-03 12:30:46 -0700124int SourceInfo::prepareModule(llvm::LLVMContext *context) {
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700125 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(
Stephen Hinese708ffe2012-05-03 15:18:49 -0700135 llvm::StringRef(buffer.bitcode, buffer.bitcodeSize), "", false));
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700136
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
Stephen Hines274926b2012-05-03 12:30:46 -0700160 if (context)
161 shared_context = true;
162 else
163 context = new llvm::LLVMContext();
164
165 module = llvm::ParseBitcodeFile(mem.get(), *context, &errmsg);
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700166 if (module == NULL) {
167 ALOGE("Unable to ParseBitcodeFile: %s\n", errmsg.c_str());
Stephen Hines274926b2012-05-03 12:30:46 -0700168 if (!shared_context)
169 delete context;
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700170 }
171
172 return (module == NULL);
173}
174
175SourceInfo::~SourceInfo() {
Stephen Hines274926b2012-05-03 12:30:46 -0700176 if (module != NULL) {
177 llvm::LLVMContext *context = &module->getContext();
178 delete module;
179 if (!shared_context)
180 delete context;
181 }
Stephen Hinesead5ccb2012-05-03 12:30:38 -0700182}
183
184template <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
203template void SourceInfo::introDependency<MCCacheWriter>(MCCacheWriter &);
204template void SourceInfo::introDependency<MCCacheReader>(MCCacheReader &);
205
206
207} // namespace bcc