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/StringRef.h> 22#include <llvm/Bitcode/ReaderWriter.h> 23#include <llvm/IR/AssemblyAnnotationWriter.h> 24#include <llvm/IR/LLVMContext.h> 25#include <llvm/IR/Module.h> 26#include <llvm/Support/FileSystem.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 52std::string inFile; 53std::string outFile; 54std::string infoFile; 55 56extern int opterr; 57extern int optind; 58 59bool translateFlag = false; 60bool infoFlag = false; 61bool verbose = true; 62 63static 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 113static 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 155static 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 default: 169 printf("UNKNOWN\n\n"); 170 break; 171 } 172 173 printf("exportVarCount: %u\n", ME->getExportVarCount()); 174 const char **varNameList = ME->getExportVarNameList(); 175 for (size_t i = 0; i < ME->getExportVarCount(); i++) { 176 printf("var[%u]: %s\n", i, varNameList[i]); 177 } 178 printf("\n"); 179 180 printf("exportFuncCount: %u\n", ME->getExportFuncCount()); 181 const char **funcNameList = ME->getExportFuncNameList(); 182 for (size_t i = 0; i < ME->getExportFuncCount(); i++) { 183 printf("func[%u]: %s\n", i, funcNameList[i]); 184 } 185 printf("\n"); 186 187 printf("exportForEachSignatureCount: %u\n", 188 ME->getExportForEachSignatureCount()); 189 const char **nameList = ME->getExportForEachNameList(); 190 const uint32_t *sigList = ME->getExportForEachSignatureList(); 191 for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { 192 printf("exportForEachSignatureList[%u]: %s - %u\n", i, nameList[i], 193 sigList[i]); 194 } 195 printf("\n"); 196 197 printf("pragmaCount: %u\n", ME->getPragmaCount()); 198 const char **keyList = ME->getPragmaKeyList(); 199 const char **valueList = ME->getPragmaValueList(); 200 for (size_t i = 0; i < ME->getPragmaCount(); i++) { 201 printf("pragma[%u]: %s - %s\n", i, keyList[i], valueList[i]); 202 } 203 printf("\n"); 204 205 printf("objectSlotCount: %u\n", ME->getObjectSlotCount()); 206 const uint32_t *slotList = ME->getObjectSlotList(); 207 for (size_t i = 0; i < ME->getObjectSlotCount(); i++) { 208 printf("objectSlotList[%u]: %u\n", i, slotList[i]); 209 } 210 printf("\n"); 211 212 return; 213} 214 215 216static size_t readBitcode(const char **bitcode) { 217 if (!inFile.length()) { 218 fprintf(stderr, "input file required\n"); 219 return 0; 220 } 221 222 struct stat statInFile; 223 if (stat(inFile.c_str(), &statInFile) < 0) { 224 fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno)); 225 return 0; 226 } 227 228 if (!S_ISREG(statInFile.st_mode)) { 229 fprintf(stderr, "Input file should be a regular file.\n"); 230 return 0; 231 } 232 233 FILE *in = fopen(inFile.c_str(), "r"); 234 if (!in) { 235 fprintf(stderr, "Could not open input file %s\n", inFile.c_str()); 236 return 0; 237 } 238 239 size_t bitcodeSize = statInFile.st_size; 240 241 *bitcode = (const char*) calloc(1, bitcodeSize + 1); 242 size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in); 243 244 if (nread != bitcodeSize) 245 fprintf(stderr, "Could not read all of file %s\n", inFile.c_str()); 246 247 fclose(in); 248 return nread; 249} 250 251 252static void releaseBitcode(const char **bitcode) { 253 if (bitcode && *bitcode) { 254 free((void*) *bitcode); 255 *bitcode = NULL; 256 } 257 return; 258} 259 260 261int main(int argc, char** argv) { 262 if(!parseOption(argc, argv)) { 263 fprintf(stderr, "failed to parse option\n"); 264 return 1; 265 } 266 267 const char *bitcode = NULL; 268 size_t bitcodeSize = readBitcode(&bitcode); 269 270 unsigned int version = 0; 271 272 bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize); 273 if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { 274 version = bcWrapper.getTargetAPI(); 275 if (verbose) { 276 printf("Found bitcodeWrapper\n"); 277 } 278 } else if (translateFlag) { 279 version = 12; 280 } 281 282 if (verbose) { 283 printf("targetAPI: %u\n", version); 284 printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion()); 285 printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel()); 286 } 287 288 std::unique_ptr<bcinfo::BitcodeTranslator> BT; 289 BT.reset(new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version)); 290 if (!BT->translate()) { 291 fprintf(stderr, "failed to translate bitcode\n"); 292 return 3; 293 } 294 295 std::unique_ptr<bcinfo::MetadataExtractor> ME; 296 ME.reset(new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(), 297 BT->getTranslatedBitcodeSize())); 298 if (!ME->extract()) { 299 fprintf(stderr, "failed to get metadata\n"); 300 return 4; 301 } 302 303 if (verbose) { 304 dumpMetadata(ME.get()); 305 306 const char *translatedBitcode = BT->getTranslatedBitcode(); 307 size_t translatedBitcodeSize = BT->getTranslatedBitcodeSize(); 308 309 llvm::LLVMContext &ctx = llvm::getGlobalContext(); 310 llvm::llvm_shutdown_obj called_on_exit; 311 312 std::unique_ptr<llvm::MemoryBuffer> mem; 313 314 mem.reset(llvm::MemoryBuffer::getMemBuffer( 315 llvm::StringRef(translatedBitcode, translatedBitcodeSize), 316 inFile.c_str(), false)); 317 318 std::unique_ptr<llvm::Module> module; 319 llvm::ErrorOr<llvm::Module*> moduleOrError = llvm::parseBitcodeFile(mem.get(), ctx); 320 std::error_code ec = moduleOrError.getError(); 321 if (!ec) { 322 module.reset(moduleOrError.get()); 323 ec = module->materializeAllPermanently(); 324 } 325 std::string errmsg; 326 if (ec) { 327 errmsg = ec.message(); 328 module.reset(); 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 std::unique_ptr<llvm::tool_output_file> tof( 338 new llvm::tool_output_file(outFile.c_str(), errmsg, 339 llvm::sys::fs::F_None)); 340 std::unique_ptr<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