• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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