1 /*
2 * Copyright 2011, 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 "bcinfo/MetadataExtractor.h"
18
19 #define LOG_TAG "bcinfo"
20 #include <cutils/log.h>
21
22 #include "llvm/ADT/OwningPtr.h"
23 #include "llvm/Bitcode/ReaderWriter.h"
24 #include "llvm/LLVMContext.h"
25 #include "llvm/Module.h"
26 #include "llvm/Support/MemoryBuffer.h"
27
28 #include <cstdlib>
29
30 namespace bcinfo {
31
32 // Name of metadata node where pragma info resides (should be synced with
33 // slang.cpp)
34 static const llvm::StringRef PragmaMetadataName = "#pragma";
35
36 // Name of metadata node where exported variable names reside (should be
37 // synced with slang_rs_metadata.h)
38 static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
39
40 // Name of metadata node where exported function names reside (should be
41 // synced with slang_rs_metadata.h)
42 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
43
44 // Name of metadata node where exported ForEach signature information resides
45 // (should be synced with slang_rs_metadata.h)
46 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
47
48 // Name of metadata node where RS object slot info resides (should be
49 // synced with slang_rs_metadata.h)
50 static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
51
52
MetadataExtractor(const char * bitcode,size_t bitcodeSize)53 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
54 : mBitcode(bitcode), mBitcodeSize(bitcodeSize), mExportVarCount(0),
55 mExportFuncCount(0), mExportForEachSignatureCount(0),
56 mExportForEachSignatureList(NULL), mPragmaCount(0), mPragmaKeyList(NULL),
57 mPragmaValueList(NULL), mObjectSlotCount(0), mObjectSlotList(NULL) {
58 }
59
60
~MetadataExtractor()61 MetadataExtractor::~MetadataExtractor() {
62 delete [] mExportForEachSignatureList;
63 mExportForEachSignatureList = NULL;
64
65 if (mPragmaCount > 0) {
66 for (size_t i = 0; i < mPragmaCount; i++) {
67 if (mPragmaKeyList) {
68 delete [] mPragmaKeyList[i];
69 mPragmaKeyList[i] = NULL;
70 }
71 if (mPragmaValueList) {
72 delete [] mPragmaValueList[i];
73 mPragmaValueList[i] = NULL;
74 }
75 }
76 }
77 delete [] mPragmaKeyList;
78 mPragmaKeyList = NULL;
79 delete [] mPragmaValueList;
80 mPragmaValueList = NULL;
81
82 delete [] mObjectSlotList;
83 mObjectSlotList = NULL;
84
85 return;
86 }
87
88
populateObjectSlotMetadata(const llvm::NamedMDNode * ObjectSlotMetadata)89 bool MetadataExtractor::populateObjectSlotMetadata(
90 const llvm::NamedMDNode *ObjectSlotMetadata) {
91 if (!ObjectSlotMetadata) {
92 return true;
93 }
94
95 mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
96
97 if (!mObjectSlotCount) {
98 return true;
99 }
100
101 uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
102 memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
103
104 for (size_t i = 0; i < mObjectSlotCount; i++) {
105 llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
106 if (ObjectSlot != NULL && ObjectSlot->getNumOperands() == 1) {
107 llvm::Value *SlotMDS = ObjectSlot->getOperand(0);
108 if (SlotMDS->getValueID() == llvm::Value::MDStringVal) {
109 llvm::StringRef Slot =
110 static_cast<llvm::MDString*>(SlotMDS)->getString();
111 uint32_t USlot = 0;
112 if (Slot.getAsInteger(10, USlot)) {
113 LOGE("Non-integer object slot value '%s'", Slot.str().c_str());
114 return false;
115 }
116 TmpSlotList[i] = USlot;
117 }
118 }
119 }
120
121 mObjectSlotList = TmpSlotList;
122
123 return true;
124 }
125
126
createStringFromValue(llvm::Value * v)127 static const char *createStringFromValue(llvm::Value *v) {
128 if (v->getValueID() != llvm::Value::MDStringVal) {
129 return NULL;
130 }
131
132 llvm::StringRef ref = static_cast<llvm::MDString*>(v)->getString();
133
134 char *c = new char[ref.size() + 1];
135 memcpy(c, ref.data(), ref.size());
136 c[ref.size()] = '\0';
137
138 return c;
139 }
140
141
populatePragmaMetadata(const llvm::NamedMDNode * PragmaMetadata)142 void MetadataExtractor::populatePragmaMetadata(
143 const llvm::NamedMDNode *PragmaMetadata) {
144 if (!PragmaMetadata) {
145 return;
146 }
147
148 mPragmaCount = PragmaMetadata->getNumOperands();
149 if (!mPragmaCount) {
150 return;
151 }
152
153 mPragmaKeyList = new const char*[mPragmaCount];
154 mPragmaValueList = new const char*[mPragmaCount];
155
156 for (size_t i = 0; i < mPragmaCount; i++) {
157 llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
158 if (Pragma != NULL && Pragma->getNumOperands() == 2) {
159 llvm::Value *PragmaKeyMDS = Pragma->getOperand(0);
160 mPragmaKeyList[i] = createStringFromValue(PragmaKeyMDS);
161 llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
162 mPragmaValueList[i] = createStringFromValue(PragmaValueMDS);
163 }
164 }
165
166 return;
167 }
168
169
populateForEachMetadata(const llvm::NamedMDNode * ExportForEachMetadata)170 bool MetadataExtractor::populateForEachMetadata(
171 const llvm::NamedMDNode *ExportForEachMetadata) {
172 if (!ExportForEachMetadata) {
173 // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
174 // section for ForEach. We generate a full signature for a "root" function
175 // which means that we need to set the bottom 5 bits in the mask.
176 mExportForEachSignatureCount = 1;
177 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
178 TmpSigList[0] = 0x1f;
179 mExportForEachSignatureList = TmpSigList;
180 return true;
181 }
182
183 mExportForEachSignatureCount = ExportForEachMetadata->getNumOperands();
184 if (!mExportForEachSignatureCount) {
185 return true;
186 }
187
188 uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
189
190 for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
191 llvm::MDNode *SigNode = ExportForEachMetadata->getOperand(i);
192 if (SigNode != NULL && SigNode->getNumOperands() == 1) {
193 llvm::Value *SigVal = SigNode->getOperand(0);
194 if (SigVal->getValueID() == llvm::Value::MDStringVal) {
195 llvm::StringRef SigString =
196 static_cast<llvm::MDString*>(SigVal)->getString();
197 uint32_t Signature = 0;
198 if (SigString.getAsInteger(10, Signature)) {
199 LOGE("Non-integer signature value '%s'", SigString.str().c_str());
200 return false;
201 }
202 TmpSigList[i] = Signature;
203 }
204 }
205 }
206
207 mExportForEachSignatureList = TmpSigList;
208
209 return true;
210 }
211
212
213
extract()214 bool MetadataExtractor::extract() {
215 if (!mBitcode || !mBitcodeSize) {
216 LOGE("Invalid/empty bitcode");
217 return false;
218 }
219
220 llvm::OwningPtr<llvm::LLVMContext> mContext(new llvm::LLVMContext());
221 llvm::OwningPtr<llvm::MemoryBuffer> MEM(
222 llvm::MemoryBuffer::getMemBuffer(
223 llvm::StringRef(mBitcode, mBitcodeSize)));
224 std::string error;
225
226 // Module ownership is handled by the context, so we don't need to free it.
227 llvm::Module *module = llvm::ParseBitcodeFile(MEM.get(), *mContext, &error);
228 if (!module) {
229 LOGE("Could not parse bitcode file");
230 LOGE("%s", error.c_str());
231 return false;
232 }
233
234 const llvm::NamedMDNode *ExportVarMetadata =
235 module->getNamedMetadata(ExportVarMetadataName);
236 const llvm::NamedMDNode *ExportFuncMetadata =
237 module->getNamedMetadata(ExportFuncMetadataName);
238 const llvm::NamedMDNode *ExportForEachMetadata =
239 module->getNamedMetadata(ExportForEachMetadataName);
240 const llvm::NamedMDNode *PragmaMetadata =
241 module->getNamedMetadata(PragmaMetadataName);
242 const llvm::NamedMDNode *ObjectSlotMetadata =
243 module->getNamedMetadata(ObjectSlotMetadataName);
244
245 if (ExportVarMetadata) {
246 mExportVarCount = ExportVarMetadata->getNumOperands();
247 }
248
249 if (ExportFuncMetadata) {
250 mExportFuncCount = ExportFuncMetadata->getNumOperands();
251 }
252
253 if (!populateForEachMetadata(ExportForEachMetadata)) {
254 LOGE("Could not populate ForEach signature metadata");
255 return false;
256 }
257
258 populatePragmaMetadata(PragmaMetadata);
259
260 if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
261 LOGE("Could not populate object slot metadata");
262 return false;
263 }
264
265 return true;
266 }
267
268 } // namespace bcinfo
269
270