1 /*
2  * Copyright 2011-2012, 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 #include "bcinfo/BitcodeWrapper.h"
20 #include "rsDefines.h"
21 
22 #define LOG_TAG "bcinfo"
23 #include <cutils/log.h>
24 #ifdef HAVE_ANDROID_OS
25 #include <cutils/properties.h>
26 #endif
27 
28 #include "llvm/Bitcode/ReaderWriter.h"
29 #include "llvm/IR/Constants.h"
30 #include "llvm/IR/LLVMContext.h"
31 #include "llvm/IR/Module.h"
32 #include "llvm/IR/Function.h"
33 #include "llvm/Support/MemoryBuffer.h"
34 
35 #include <cstdlib>
36 
37 namespace bcinfo {
38 
39 namespace {
40 
getStringOperand(const llvm::Metadata * node)41 llvm::StringRef getStringOperand(const llvm::Metadata *node) {
42   if (auto *mds = llvm::dyn_cast_or_null<const llvm::MDString>(node)) {
43     return mds->getString();
44   }
45   return llvm::StringRef();
46 }
47 
extractUIntFromMetadataString(uint32_t * value,const llvm::Metadata * m)48 bool extractUIntFromMetadataString(uint32_t *value,
49     const llvm::Metadata *m) {
50   llvm::StringRef SigString = getStringOperand(m);
51   if (SigString != "") {
52     if (!SigString.getAsInteger(10, *value)) {
53       return true;
54     }
55   }
56   return false;
57 }
58 
59 }
60 
61 // Name of metadata node where pragma info resides (should be synced with
62 // slang.cpp)
63 static const llvm::StringRef PragmaMetadataName = "#pragma";
64 
65 // Name of metadata node where exported variable names reside (should be
66 // synced with slang_rs_metadata.h)
67 static const llvm::StringRef ExportVarMetadataName = "#rs_export_var";
68 
69 // Name of metadata node where exported function names reside (should be
70 // synced with slang_rs_metadata.h)
71 static const llvm::StringRef ExportFuncMetadataName = "#rs_export_func";
72 
73 // Name of metadata node where exported ForEach name information resides
74 // (should be synced with slang_rs_metadata.h)
75 static const llvm::StringRef ExportForEachNameMetadataName =
76     "#rs_export_foreach_name";
77 
78 // Name of metadata node where exported ForEach signature information resides
79 // (should be synced with slang_rs_metadata.h)
80 static const llvm::StringRef ExportForEachMetadataName = "#rs_export_foreach";
81 
82 // Name of metadata node where RS object slot info resides (should be
83 // synced with slang_rs_metadata.h)
84 static const llvm::StringRef ObjectSlotMetadataName = "#rs_object_slots";
85 
86 static const llvm::StringRef ThreadableMetadataName = "#rs_is_threadable";
87 
88 // Name of metadata node where the checksum for this build is stored.  (should
89 // be synced with libbcc/lib/Core/Source.cpp)
90 static const llvm::StringRef ChecksumMetadataName = "#rs_build_checksum";
91 
MetadataExtractor(const char * bitcode,size_t bitcodeSize)92 MetadataExtractor::MetadataExtractor(const char *bitcode, size_t bitcodeSize)
93     : mModule(nullptr), mBitcode(bitcode), mBitcodeSize(bitcodeSize),
94       mExportVarCount(0), mExportFuncCount(0), mExportForEachSignatureCount(0),
95       mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
96       mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
97       mExportForEachInputCountList(nullptr), mPragmaCount(0),
98       mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
99       mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
100       mIsThreadable(true), mBuildChecksum(nullptr) {
101   BitcodeWrapper wrapper(bitcode, bitcodeSize);
102   mTargetAPI = wrapper.getTargetAPI();
103   mCompilerVersion = wrapper.getCompilerVersion();
104   mOptimizationLevel = wrapper.getOptimizationLevel();
105 }
106 
107 
MetadataExtractor(const llvm::Module * module)108 MetadataExtractor::MetadataExtractor(const llvm::Module *module)
109     : mModule(module), mBitcode(nullptr), mBitcodeSize(0), mExportVarCount(0),
110       mExportFuncCount(0), mExportForEachSignatureCount(0),
111       mExportVarNameList(nullptr), mExportFuncNameList(nullptr),
112       mExportForEachNameList(nullptr), mExportForEachSignatureList(nullptr),
113       mExportForEachInputCountList(nullptr), mPragmaCount(0),
114       mPragmaKeyList(nullptr), mPragmaValueList(nullptr), mObjectSlotCount(0),
115       mObjectSlotList(nullptr), mRSFloatPrecision(RS_FP_Full),
116       mIsThreadable(true), mBuildChecksum(nullptr) {
117   mCompilerVersion = RS_VERSION;  // Default to the actual current version.
118   mOptimizationLevel = 3;
119 }
120 
121 
~MetadataExtractor()122 MetadataExtractor::~MetadataExtractor() {
123   if (mExportVarNameList) {
124     for (size_t i = 0; i < mExportVarCount; i++) {
125         delete [] mExportVarNameList[i];
126         mExportVarNameList[i] = nullptr;
127     }
128   }
129   delete [] mExportVarNameList;
130   mExportVarNameList = nullptr;
131 
132   if (mExportFuncNameList) {
133     for (size_t i = 0; i < mExportFuncCount; i++) {
134         delete [] mExportFuncNameList[i];
135         mExportFuncNameList[i] = nullptr;
136     }
137   }
138   delete [] mExportFuncNameList;
139   mExportFuncNameList = nullptr;
140 
141   if (mExportForEachNameList) {
142     for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
143         delete [] mExportForEachNameList[i];
144         mExportForEachNameList[i] = nullptr;
145     }
146   }
147   delete [] mExportForEachNameList;
148   mExportForEachNameList = nullptr;
149 
150   delete [] mExportForEachSignatureList;
151   mExportForEachSignatureList = nullptr;
152 
153   for (size_t i = 0; i < mPragmaCount; i++) {
154     if (mPragmaKeyList) {
155       delete [] mPragmaKeyList[i];
156       mPragmaKeyList[i] = nullptr;
157     }
158     if (mPragmaValueList) {
159       delete [] mPragmaValueList[i];
160       mPragmaValueList[i] = nullptr;
161     }
162   }
163   delete [] mPragmaKeyList;
164   mPragmaKeyList = nullptr;
165   delete [] mPragmaValueList;
166   mPragmaValueList = nullptr;
167 
168   delete [] mObjectSlotList;
169   mObjectSlotList = nullptr;
170 
171   delete [] mBuildChecksum;
172 
173   return;
174 }
175 
176 
populateObjectSlotMetadata(const llvm::NamedMDNode * ObjectSlotMetadata)177 bool MetadataExtractor::populateObjectSlotMetadata(
178     const llvm::NamedMDNode *ObjectSlotMetadata) {
179   if (!ObjectSlotMetadata) {
180     return true;
181   }
182 
183   mObjectSlotCount = ObjectSlotMetadata->getNumOperands();
184 
185   if (!mObjectSlotCount) {
186     return true;
187   }
188 
189   uint32_t *TmpSlotList = new uint32_t[mObjectSlotCount];
190   memset(TmpSlotList, 0, mObjectSlotCount * sizeof(*TmpSlotList));
191 
192   for (size_t i = 0; i < mObjectSlotCount; i++) {
193     llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
194     if (ObjectSlot != nullptr && ObjectSlot->getNumOperands() == 1) {
195       if (!extractUIntFromMetadataString(&TmpSlotList[i], ObjectSlot->getOperand(0))) {
196         ALOGE("Non-integer object slot value");
197         return false;
198       }
199     } else {
200       ALOGE("Corrupt object slot information");
201       return false;
202     }
203   }
204 
205   mObjectSlotList = TmpSlotList;
206 
207   return true;
208 }
209 
210 
createStringFromValue(llvm::Metadata * m)211 static const char *createStringFromValue(llvm::Metadata *m) {
212   auto ref = getStringOperand(m);
213   char *c = new char[ref.size() + 1];
214   memcpy(c, ref.data(), ref.size());
215   c[ref.size()] = '\0';
216   return c;
217 }
218 
219 
populatePragmaMetadata(const llvm::NamedMDNode * PragmaMetadata)220 void MetadataExtractor::populatePragmaMetadata(
221     const llvm::NamedMDNode *PragmaMetadata) {
222   if (!PragmaMetadata) {
223     return;
224   }
225 
226   mPragmaCount = PragmaMetadata->getNumOperands();
227   if (!mPragmaCount) {
228     return;
229   }
230 
231   const char **TmpKeyList = new const char*[mPragmaCount];
232   const char **TmpValueList = new const char*[mPragmaCount];
233 
234   for (size_t i = 0; i < mPragmaCount; i++) {
235     llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
236     if (Pragma != nullptr && Pragma->getNumOperands() == 2) {
237       llvm::Metadata *PragmaKeyMDS = Pragma->getOperand(0);
238       TmpKeyList[i] = createStringFromValue(PragmaKeyMDS);
239       llvm::Metadata *PragmaValueMDS = Pragma->getOperand(1);
240       TmpValueList[i] = createStringFromValue(PragmaValueMDS);
241     }
242   }
243 
244   mPragmaKeyList = TmpKeyList;
245   mPragmaValueList = TmpValueList;
246 
247   // Check to see if we have any FP precision-related pragmas.
248   std::string Relaxed("rs_fp_relaxed");
249   std::string Imprecise("rs_fp_imprecise");
250   std::string Full("rs_fp_full");
251   bool RelaxedPragmaSeen = false;
252   bool FullPragmaSeen = false;
253   for (size_t i = 0; i < mPragmaCount; i++) {
254     if (!Relaxed.compare(mPragmaKeyList[i])) {
255       RelaxedPragmaSeen = true;
256     } else if (!Imprecise.compare(mPragmaKeyList[i])) {
257       ALOGW("rs_fp_imprecise is deprecated.  Assuming rs_fp_relaxed instead.");
258       RelaxedPragmaSeen = true;
259     } else if (!Full.compare(mPragmaKeyList[i])) {
260       FullPragmaSeen = true;
261     }
262   }
263 
264   if (RelaxedPragmaSeen && FullPragmaSeen) {
265     ALOGE("Full and relaxed precision specified at the same time!");
266   }
267   mRSFloatPrecision = RelaxedPragmaSeen ? RS_FP_Relaxed : RS_FP_Full;
268 
269 #ifdef HAVE_ANDROID_OS
270   // Provide an override for precsiion via adb shell setprop
271   // adb shell setprop debug.rs.precision rs_fp_full
272   // adb shell setprop debug.rs.precision rs_fp_relaxed
273   // adb shell setprop debug.rs.precision rs_fp_imprecise
274   char PrecisionPropBuf[PROPERTY_VALUE_MAX];
275   const std::string PrecisionPropName("debug.rs.precision");
276   property_get("debug.rs.precision", PrecisionPropBuf, "");
277   if (PrecisionPropBuf[0]) {
278     if (!Relaxed.compare(PrecisionPropBuf)) {
279       ALOGI("Switching to RS FP relaxed mode via setprop");
280       mRSFloatPrecision = RS_FP_Relaxed;
281     } else if (!Imprecise.compare(PrecisionPropBuf)) {
282       ALOGW("Switching to RS FP relaxed mode via setprop. rs_fp_imprecise was "
283             "specified but is deprecated ");
284       mRSFloatPrecision = RS_FP_Relaxed;
285     } else if (!Full.compare(PrecisionPropBuf)) {
286       ALOGI("Switching to RS FP full mode via setprop");
287       mRSFloatPrecision = RS_FP_Full;
288     } else {
289       ALOGE("Unrecognized debug.rs.precision %s", PrecisionPropBuf);
290     }
291   }
292 #endif
293 }
294 
295 
populateVarNameMetadata(const llvm::NamedMDNode * VarNameMetadata)296 bool MetadataExtractor::populateVarNameMetadata(
297     const llvm::NamedMDNode *VarNameMetadata) {
298   if (!VarNameMetadata) {
299     return true;
300   }
301 
302   mExportVarCount = VarNameMetadata->getNumOperands();
303   if (!mExportVarCount) {
304     return true;
305   }
306 
307   const char **TmpNameList = new const char *[mExportVarCount];
308 
309   for (size_t i = 0; i < mExportVarCount; i++) {
310     llvm::MDNode *Name = VarNameMetadata->getOperand(i);
311     if (Name != nullptr && Name->getNumOperands() > 1) {
312       TmpNameList[i] = createStringFromValue(Name->getOperand(0));
313     }
314   }
315 
316   mExportVarNameList = TmpNameList;
317 
318   return true;
319 }
320 
321 
populateFuncNameMetadata(const llvm::NamedMDNode * FuncNameMetadata)322 bool MetadataExtractor::populateFuncNameMetadata(
323     const llvm::NamedMDNode *FuncNameMetadata) {
324   if (!FuncNameMetadata) {
325     return true;
326   }
327 
328   mExportFuncCount = FuncNameMetadata->getNumOperands();
329   if (!mExportFuncCount) {
330     return true;
331   }
332 
333   const char **TmpNameList = new const char*[mExportFuncCount];
334 
335   for (size_t i = 0; i < mExportFuncCount; i++) {
336     llvm::MDNode *Name = FuncNameMetadata->getOperand(i);
337     if (Name != nullptr && Name->getNumOperands() == 1) {
338       TmpNameList[i] = createStringFromValue(Name->getOperand(0));
339     }
340   }
341 
342   mExportFuncNameList = TmpNameList;
343 
344   return true;
345 }
346 
347 
calculateNumInputs(const llvm::Function * Function,uint32_t Signature)348 uint32_t MetadataExtractor::calculateNumInputs(const llvm::Function *Function,
349                                                uint32_t Signature) {
350 
351   if (hasForEachSignatureIn(Signature)) {
352     uint32_t OtherCount = 0;
353 
354     OtherCount += hasForEachSignatureUsrData(Signature);
355     OtherCount += hasForEachSignatureX(Signature);
356     OtherCount += hasForEachSignatureY(Signature);
357     OtherCount += hasForEachSignatureZ(Signature);
358     OtherCount += hasForEachSignatureCtxt(Signature);
359     OtherCount += hasForEachSignatureOut(Signature) &&
360                   Function->getReturnType()->isVoidTy();
361 
362     return Function->arg_size() - OtherCount;
363 
364   } else {
365     return 0;
366   }
367 }
368 
369 
populateForEachMetadata(const llvm::NamedMDNode * Names,const llvm::NamedMDNode * Signatures)370 bool MetadataExtractor::populateForEachMetadata(
371     const llvm::NamedMDNode *Names,
372     const llvm::NamedMDNode *Signatures) {
373   if (!Names && !Signatures && mCompilerVersion == 0) {
374     // Handle legacy case for pre-ICS bitcode that doesn't contain a metadata
375     // section for ForEach. We generate a full signature for a "root" function
376     // which means that we need to set the bottom 5 bits in the mask.
377     mExportForEachSignatureCount = 1;
378     char **TmpNameList = new char*[mExportForEachSignatureCount];
379     size_t RootLen = strlen(kRoot) + 1;
380     TmpNameList[0] = new char[RootLen];
381     strncpy(TmpNameList[0], kRoot, RootLen);
382 
383     uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
384     TmpSigList[0] = 0x1f;
385 
386     mExportForEachNameList = (const char**)TmpNameList;
387     mExportForEachSignatureList = TmpSigList;
388     return true;
389   }
390 
391   if (Signatures) {
392     mExportForEachSignatureCount = Signatures->getNumOperands();
393     if (!mExportForEachSignatureCount) {
394       return true;
395     }
396   } else {
397     mExportForEachSignatureCount = 0;
398     mExportForEachSignatureList = nullptr;
399     return true;
400   }
401 
402   uint32_t *TmpSigList = new uint32_t[mExportForEachSignatureCount];
403   const char **TmpNameList = new const char*[mExportForEachSignatureCount];
404   uint32_t *TmpInputCountList = new uint32_t[mExportForEachSignatureCount];
405 
406   for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
407     llvm::MDNode *SigNode = Signatures->getOperand(i);
408     if (SigNode != nullptr && SigNode->getNumOperands() == 1) {
409       if (!extractUIntFromMetadataString(&TmpSigList[i], SigNode->getOperand(0))) {
410         ALOGE("Non-integer signature value");
411         return false;
412       }
413     } else {
414       ALOGE("Corrupt signature information");
415       return false;
416     }
417   }
418 
419   if (Names) {
420     for (size_t i = 0; i < mExportForEachSignatureCount; i++) {
421       llvm::MDNode *Name = Names->getOperand(i);
422       if (Name != nullptr && Name->getNumOperands() == 1) {
423         TmpNameList[i] = createStringFromValue(Name->getOperand(0));
424 
425         llvm::Function *Func =
426             mModule->getFunction(llvm::StringRef(TmpNameList[i]));
427 
428         TmpInputCountList[i] = (Func != nullptr) ?
429           calculateNumInputs(Func, TmpSigList[i]) : 0;
430       }
431     }
432   } else {
433     if (mExportForEachSignatureCount != 1) {
434       ALOGE("mExportForEachSignatureCount = %zu, but should be 1",
435             mExportForEachSignatureCount);
436     }
437     char *RootName = new char[5];
438     strncpy(RootName, "root", 5);
439     TmpNameList[0] = RootName;
440   }
441 
442   mExportForEachNameList = TmpNameList;
443   mExportForEachSignatureList = TmpSigList;
444   mExportForEachInputCountList = TmpInputCountList;
445 
446   return true;
447 }
448 
449 
readThreadableFlag(const llvm::NamedMDNode * ThreadableMetadata)450 void MetadataExtractor::readThreadableFlag(
451     const llvm::NamedMDNode *ThreadableMetadata) {
452 
453   // Scripts are threadable by default.  If we read a valid metadata value for
454   // 'ThreadableMetadataName' and it is set to 'no', we mark script as non
455   // threadable.  All other exception paths retain the default value.
456 
457   mIsThreadable = true;
458   if (ThreadableMetadata == nullptr)
459     return;
460 
461   llvm::MDNode *mdNode = ThreadableMetadata->getOperand(0);
462   if (mdNode == nullptr)
463     return;
464 
465   llvm::Metadata *mdValue = mdNode->getOperand(0);
466   if (mdValue == nullptr)
467     return;
468 
469   if (getStringOperand(mdValue) == "no")
470     mIsThreadable = false;
471 }
472 
readBuildChecksumMetadata(const llvm::NamedMDNode * ChecksumMetadata)473 void MetadataExtractor::readBuildChecksumMetadata(
474     const llvm::NamedMDNode *ChecksumMetadata) {
475 
476   if (ChecksumMetadata == nullptr)
477     return;
478 
479   llvm::MDNode *mdNode = ChecksumMetadata->getOperand(0);
480   if (mdNode == nullptr)
481     return;
482 
483   llvm::Metadata *mdValue = mdNode->getOperand(0);
484   if (mdValue == nullptr)
485     return;
486 
487   mBuildChecksum = createStringFromValue(mdValue);
488 }
489 
extract()490 bool MetadataExtractor::extract() {
491   if (!(mBitcode && mBitcodeSize) && !mModule) {
492     ALOGE("Invalid/empty bitcode/module");
493     return false;
494   }
495 
496   std::unique_ptr<llvm::LLVMContext> mContext;
497 
498   if (!mModule) {
499     mContext.reset(new llvm::LLVMContext());
500     std::unique_ptr<llvm::MemoryBuffer> MEM(
501       llvm::MemoryBuffer::getMemBuffer(
502         llvm::StringRef(mBitcode, mBitcodeSize), "", false));
503     std::string error;
504 
505     // Module ownership is handled by the context, so we don't need to free it.
506     llvm::ErrorOr<llvm::Module* > errval = llvm::parseBitcodeFile(MEM.get()->getMemBufferRef(),
507                                                                   *mContext);
508     if (std::error_code ec = errval.getError()) {
509         ALOGE("Could not parse bitcode file");
510         ALOGE("%s", ec.message().c_str());
511         return false;
512     }
513     mModule = errval.get();
514   }
515 
516   const llvm::NamedMDNode *ExportVarMetadata =
517       mModule->getNamedMetadata(ExportVarMetadataName);
518   const llvm::NamedMDNode *ExportFuncMetadata =
519       mModule->getNamedMetadata(ExportFuncMetadataName);
520   const llvm::NamedMDNode *ExportForEachNameMetadata =
521       mModule->getNamedMetadata(ExportForEachNameMetadataName);
522   const llvm::NamedMDNode *ExportForEachMetadata =
523       mModule->getNamedMetadata(ExportForEachMetadataName);
524   const llvm::NamedMDNode *PragmaMetadata =
525       mModule->getNamedMetadata(PragmaMetadataName);
526   const llvm::NamedMDNode *ObjectSlotMetadata =
527       mModule->getNamedMetadata(ObjectSlotMetadataName);
528   const llvm::NamedMDNode *ThreadableMetadata =
529       mModule->getNamedMetadata(ThreadableMetadataName);
530   const llvm::NamedMDNode *ChecksumMetadata =
531       mModule->getNamedMetadata(ChecksumMetadataName);
532 
533 
534   if (!populateVarNameMetadata(ExportVarMetadata)) {
535     ALOGE("Could not populate export variable metadata");
536     return false;
537   }
538 
539   if (!populateFuncNameMetadata(ExportFuncMetadata)) {
540     ALOGE("Could not populate export function metadata");
541     return false;
542   }
543 
544   if (!populateForEachMetadata(ExportForEachNameMetadata,
545                                ExportForEachMetadata)) {
546     ALOGE("Could not populate ForEach signature metadata");
547     return false;
548   }
549 
550   populatePragmaMetadata(PragmaMetadata);
551 
552   if (!populateObjectSlotMetadata(ObjectSlotMetadata)) {
553     ALOGE("Could not populate object slot metadata");
554     return false;
555   }
556 
557   readThreadableFlag(ThreadableMetadata);
558   readBuildChecksumMetadata(ChecksumMetadata);
559 
560   return true;
561 }
562 
563 }  // namespace bcinfo
564