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/BitcodeTranslator.h> 18 #include <bcinfo/BitcodeWrapper.h> 19 #include <bcinfo/MetadataExtractor.h> 20 21 #include <llvm/ADT/OwningPtr.h> 22 #include <llvm/ADT/StringRef.h> 23 #include <llvm/Assembly/AssemblyAnnotationWriter.h> 24 #include <llvm/Bitcode/ReaderWriter.h> 25 #include <llvm/IR/LLVMContext.h> 26 #include <llvm/IR/Module.h> 27 #include <llvm/Support/ManagedStatic.h> 28 #include <llvm/Support/MemoryBuffer.h> 29 #include <llvm/Support/ToolOutputFile.h> 30 31 #include <ctype.h> 32 #include <dlfcn.h> 33 #include <stdarg.h> 34 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <getopt.h> 39 40 #include <errno.h> 41 #include <sys/stat.h> 42 #include <sys/types.h> 43 44 #include <unistd.h> 45 46 #include <string> 47 #include <vector> 48 49 // This file corresponds to the standalone bcinfo tool. It prints a variety of 50 // information about a supplied bitcode input file. 51 52 std::string inFile; 53 std::string outFile; 54 std::string infoFile; 55 56 extern int opterr; 57 extern int optind; 58 59 bool translateFlag = false; 60 bool infoFlag = false; 61 bool verbose = true; 62 63 static int parseOption(int argc, char** argv) { 64 int c; 65 while ((c = getopt(argc, argv, "itv")) != -1) { 66 opterr = 0; 67 68 switch(c) { 69 case '?': 70 // ignore any error 71 break; 72 73 case 't': 74 translateFlag = true; 75 break; 76 77 case 'i': 78 // Turn off verbose so that we only generate the .info file. 79 infoFlag = true; 80 verbose = false; 81 break; 82 83 case 'v': 84 verbose = true; 85 break; 86 87 default: 88 // Critical error occurs 89 return 0; 90 break; 91 } 92 } 93 94 if(optind >= argc) { 95 fprintf(stderr, "input file required\n"); 96 return 0; 97 } 98 99 inFile = argv[optind]; 100 101 int l = inFile.length(); 102 if (l > 3 && inFile[l-3] == '.' && inFile[l-2] == 'b' && inFile[l-1] == 'c') { 103 outFile = std::string(inFile.begin(), inFile.end() - 3) + ".ll"; 104 infoFile = std::string(inFile.begin(), inFile.end() - 3) + ".bcinfo"; 105 } else { 106 outFile = inFile + ".ll"; 107 infoFile = inFile + ".bcinfo"; 108 } 109 return 1; 110 } 111 112 113 static int dumpInfo(bcinfo::MetadataExtractor *ME) { 114 if (!ME) { 115 return 1; 116 } 117 118 FILE *info = fopen(infoFile.c_str(), "w"); 119 if (!info) { 120 fprintf(stderr, "Could not open info file %s\n", infoFile.c_str()); 121 return 2; 122 } 123 124 fprintf(info, "exportVarCount: %u\n", ME->getExportVarCount()); 125 const char **varNameList = ME->getExportVarNameList(); 126 for (size_t i = 0; i < ME->getExportVarCount(); i++) { 127 fprintf(info, "%s\n", varNameList[i]); 128 } 129 130 fprintf(info, "exportFuncCount: %u\n", ME->getExportFuncCount()); 131 const char **funcNameList = ME->getExportFuncNameList(); 132 for (size_t i = 0; i < ME->getExportFuncCount(); i++) { 133 fprintf(info, "%s\n", funcNameList[i]); 134 } 135 136 fprintf(info, "exportForEachCount: %u\n", 137 ME->getExportForEachSignatureCount()); 138 const char **nameList = ME->getExportForEachNameList(); 139 const uint32_t *sigList = ME->getExportForEachSignatureList(); 140 for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { 141 fprintf(info, "%u - %s\n", sigList[i], nameList[i]); 142 } 143 144 fprintf(info, "objectSlotCount: %u\n", ME->getObjectSlotCount()); 145 const uint32_t *slotList = ME->getObjectSlotList(); 146 for (size_t i = 0; i < ME->getObjectSlotCount(); i++) { 147 fprintf(info, "%u\n", slotList[i]); 148 } 149 150 fclose(info); 151 return 0; 152 } 153 154 155 static void dumpMetadata(bcinfo::MetadataExtractor *ME) { 156 if (!ME) { 157 return; 158 } 159 160 printf("RSFloatPrecision: "); 161 switch (ME->getRSFloatPrecision()) { 162 case bcinfo::RS_FP_Full: 163 printf("Full\n\n"); 164 break; 165 case bcinfo::RS_FP_Relaxed: 166 printf("Relaxed\n\n"); 167 break; 168 case bcinfo::RS_FP_Imprecise: 169 printf("Imprecise\n\n"); 170 break; 171 default: 172 printf("UNKNOWN\n\n"); 173 break; 174 } 175 176 printf("exportVarCount: %u\n", ME->getExportVarCount()); 177 const char **varNameList = ME->getExportVarNameList(); 178 for (size_t i = 0; i < ME->getExportVarCount(); i++) { 179 printf("var[%u]: %s\n", i, varNameList[i]); 180 } 181 printf("\n"); 182 183 printf("exportFuncCount: %u\n", ME->getExportFuncCount()); 184 const char **funcNameList = ME->getExportFuncNameList(); 185 for (size_t i = 0; i < ME->getExportFuncCount(); i++) { 186 printf("func[%u]: %s\n", i, funcNameList[i]); 187 } 188 printf("\n"); 189 190 printf("exportForEachSignatureCount: %u\n", 191 ME->getExportForEachSignatureCount()); 192 const char **nameList = ME->getExportForEachNameList(); 193 const uint32_t *sigList = ME->getExportForEachSignatureList(); 194 for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { 195 printf("exportForEachSignatureList[%u]: %s - %u\n", i, nameList[i], 196 sigList[i]); 197 } 198 printf("\n"); 199 200 printf("pragmaCount: %u\n", ME->getPragmaCount()); 201 const char **keyList = ME->getPragmaKeyList(); 202 const char **valueList = ME->getPragmaValueList(); 203 for (size_t i = 0; i < ME->getPragmaCount(); i++) { 204 printf("pragma[%u]: %s - %s\n", i, keyList[i], valueList[i]); 205 } 206 printf("\n"); 207 208 printf("objectSlotCount: %u\n", ME->getObjectSlotCount()); 209 const uint32_t *slotList = ME->getObjectSlotList(); 210 for (size_t i = 0; i < ME->getObjectSlotCount(); i++) { 211 printf("objectSlotList[%u]: %u\n", i, slotList[i]); 212 } 213 printf("\n"); 214 215 return; 216 } 217 218 219 static size_t readBitcode(const char **bitcode) { 220 if (!inFile.length()) { 221 fprintf(stderr, "input file required\n"); 222 return 0; 223 } 224 225 struct stat statInFile; 226 if (stat(inFile.c_str(), &statInFile) < 0) { 227 fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno)); 228 return 0; 229 } 230 231 if (!S_ISREG(statInFile.st_mode)) { 232 fprintf(stderr, "Input file should be a regular file.\n"); 233 return 0; 234 } 235 236 FILE *in = fopen(inFile.c_str(), "r"); 237 if (!in) { 238 fprintf(stderr, "Could not open input file %s\n", inFile.c_str()); 239 return 0; 240 } 241 242 size_t bitcodeSize = statInFile.st_size; 243 244 *bitcode = (const char*) calloc(1, bitcodeSize + 1); 245 size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in); 246 247 if (nread != bitcodeSize) 248 fprintf(stderr, "Could not read all of file %s\n", inFile.c_str()); 249 250 fclose(in); 251 return nread; 252 } 253 254 255 static void releaseBitcode(const char **bitcode) { 256 if (bitcode && *bitcode) { 257 free((void*) *bitcode); 258 *bitcode = NULL; 259 } 260 return; 261 } 262 263 264 int main(int argc, char** argv) { 265 if(!parseOption(argc, argv)) { 266 fprintf(stderr, "failed to parse option\n"); 267 return 1; 268 } 269 270 const char *bitcode = NULL; 271 size_t bitcodeSize = readBitcode(&bitcode); 272 273 unsigned int version = 0; 274 275 bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize); 276 if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { 277 version = bcWrapper.getTargetAPI(); 278 if (verbose) { 279 printf("Found bitcodeWrapper\n"); 280 } 281 } else if (translateFlag) { 282 version = 12; 283 } 284 285 if (verbose) { 286 printf("targetAPI: %u\n", version); 287 printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion()); 288 printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel()); 289 } 290 291 llvm::OwningPtr<bcinfo::BitcodeTranslator> BT; 292 BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version)); 293 if (!BT->translate()) { 294 fprintf(stderr, "failed to translate bitcode\n"); 295 return 3; 296 } 297 298 llvm::OwningPtr<bcinfo::MetadataExtractor> ME; 299 ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(), 300 BT->getTranslatedBitcodeSize())); 301 if (!ME->extract()) { 302 fprintf(stderr, "failed to get metadata\n"); 303 return 4; 304 } 305 306 if (verbose) { 307 dumpMetadata(ME.get()); 308 309 const char *translatedBitcode = BT->getTranslatedBitcode(); 310 size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize(); 311 312 llvm::LLVMContext &ctx = llvm::getGlobalContext(); 313 llvm::llvm_shutdown_obj called_on_exit; 314 315 llvm::OwningPtr<llvm::MemoryBuffer> mem; 316 317 mem.reset(llvm::MemoryBuffer::getMemBuffer( 318 llvm::StringRef(translatedBitcode, translatedBitcodeSize), 319 inFile.c_str(), false)); 320 321 llvm::OwningPtr<llvm::Module> module; 322 std::string errmsg; 323 module.reset(llvm::ParseBitcodeFile(mem.get(), ctx, &errmsg)); 324 if (module.get() != 0 && module->MaterializeAllPermanently(&errmsg)) { 325 module.reset(); 326 } 327 328 if (module.get() == 0) { 329 if (errmsg.size()) { 330 fprintf(stderr, "error: %s\n", errmsg.c_str()); 331 } else { 332 fprintf(stderr, "error: failed to parse bitcode file\n"); 333 } 334 return 5; 335 } 336 337 llvm::OwningPtr<llvm::tool_output_file> tof( 338 new llvm::tool_output_file(outFile.c_str(), errmsg, 339 llvm::sys::fs::F_Binary)); 340 llvm::OwningPtr<llvm::AssemblyAnnotationWriter> ann; 341 module->print(tof->os(), ann.get()); 342 343 tof->keep(); 344 } 345 346 if (infoFlag) { 347 if (dumpInfo(ME.get()) != 0) { 348 fprintf(stderr, "Error dumping info file\n"); 349 return 6; 350 } 351 } 352 353 releaseBitcode(&bitcode); 354 355 return 0; 356 } 357