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 <ctype.h> 22#include <dlfcn.h> 23#include <stdarg.h> 24#include <stdint.h> 25#include <stdio.h> 26#include <stdlib.h> 27#include <string.h> 28#include <getopt.h> 29 30#include <errno.h> 31#include <sys/stat.h> 32#include <sys/types.h> 33 34#include <unistd.h> 35 36#include <vector> 37 38// This file corresponds to the standalone bcinfo tool. It prints a variety of 39// information about a supplied bitcode input file. 40 41const char* inFile = NULL; 42 43extern int opterr; 44extern int optind; 45 46bool translateFlag = false; 47 48static int parseOption(int argc, char** argv) { 49 int c; 50 while ((c = getopt(argc, argv, "t")) != -1) { 51 opterr = 0; 52 53 switch(c) { 54 case '?': 55 // ignore any error 56 break; 57 58 case 't': 59 translateFlag = true; 60 break; 61 62 default: 63 // Critical error occurs 64 return 0; 65 break; 66 } 67 } 68 69 if(optind >= argc) { 70 fprintf(stderr, "input file required\n"); 71 return 0; 72 } 73 74 inFile = argv[optind]; 75 return 1; 76} 77 78 79static void dumpMetadata(bcinfo::MetadataExtractor *ME) { 80 if (!ME) { 81 return; 82 } 83 84 printf("RSFloatPrecision: "); 85 switch (ME->getRSFloatPrecision()) { 86 case bcinfo::RS_FP_Full: 87 printf("Full\n\n"); 88 break; 89 case bcinfo::RS_FP_Relaxed: 90 printf("Relaxed\n\n"); 91 break; 92 case bcinfo::RS_FP_Imprecise: 93 printf("Imprecise\n\n"); 94 break; 95 default: 96 printf("UNKNOWN\n\n"); 97 break; 98 } 99 100 printf("exportVarCount: %u\n", ME->getExportVarCount()); 101 const char **varNameList = ME->getExportVarNameList(); 102 for (size_t i = 0; i < ME->getExportVarCount(); i++) { 103 printf("var[%u]: %s\n", i, varNameList[i]); 104 } 105 printf("\n"); 106 107 printf("exportFuncCount: %u\n", ME->getExportFuncCount()); 108 const char **funcNameList = ME->getExportFuncNameList(); 109 for (size_t i = 0; i < ME->getExportFuncCount(); i++) { 110 printf("func[%u]: %s\n", i, funcNameList[i]); 111 } 112 printf("\n"); 113 114 printf("exportForEachSignatureCount: %u\n", 115 ME->getExportForEachSignatureCount()); 116 const char **nameList = ME->getExportForEachNameList(); 117 const uint32_t *sigList = ME->getExportForEachSignatureList(); 118 for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) { 119 printf("exportForEachSignatureList[%u]: %s - %u\n", i, nameList[i], 120 sigList[i]); 121 } 122 printf("\n"); 123 124 printf("pragmaCount: %u\n", ME->getPragmaCount()); 125 const char **keyList = ME->getPragmaKeyList(); 126 const char **valueList = ME->getPragmaValueList(); 127 for (size_t i = 0; i < ME->getPragmaCount(); i++) { 128 printf("pragma[%u]: %s - %s\n", i, keyList[i], valueList[i]); 129 } 130 printf("\n"); 131 132 printf("objectSlotCount: %u\n", ME->getObjectSlotCount()); 133 const uint32_t *slotList = ME->getObjectSlotList(); 134 for (size_t i = 0; i < ME->getObjectSlotCount(); i++) { 135 printf("objectSlotList[%u]: %u\n", i, slotList[i]); 136 } 137 printf("\n"); 138 139 return; 140} 141 142 143static size_t readBitcode(const char **bitcode) { 144 if (!inFile) { 145 fprintf(stderr, "input file required\n"); 146 return NULL; 147 } 148 149 struct stat statInFile; 150 if (stat(inFile, &statInFile) < 0) { 151 fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno)); 152 return NULL; 153 } 154 155 if (!S_ISREG(statInFile.st_mode)) { 156 fprintf(stderr, "Input file should be a regular file.\n"); 157 return NULL; 158 } 159 160 FILE *in = fopen(inFile, "r"); 161 if (!in) { 162 fprintf(stderr, "Could not open input file %s\n", inFile); 163 return NULL; 164 } 165 166 size_t bitcodeSize = statInFile.st_size; 167 168 *bitcode = (const char*) calloc(1, bitcodeSize + 1); 169 size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in); 170 171 if (nread != bitcodeSize) 172 fprintf(stderr, "Could not read all of file %s\n", inFile); 173 174 fclose(in); 175 return nread; 176} 177 178 179static void releaseBitcode(const char **bitcode) { 180 if (bitcode && *bitcode) { 181 free((void*) *bitcode); 182 *bitcode = NULL; 183 } 184 return; 185} 186 187 188int main(int argc, char** argv) { 189 if(!parseOption(argc, argv)) { 190 fprintf(stderr, "failed to parse option\n"); 191 return 1; 192 } 193 194 const char *bitcode = NULL; 195 const char *translatedBitcode = NULL; 196 size_t bitcodeSize = readBitcode(&bitcode); 197 198 unsigned int version = 0; 199 200 bcinfo::BitcodeWrapper bcWrapper((const char *)bitcode, bitcodeSize); 201 if (bcWrapper.getBCFileType() == bcinfo::BC_WRAPPER) { 202 version = bcWrapper.getTargetAPI(); 203 printf("Found bitcodeWrapper\n"); 204 } else if (translateFlag) { 205 version = 12; 206 } 207 208 printf("targetAPI: %u\n", version); 209 printf("compilerVersion: %u\n", bcWrapper.getCompilerVersion()); 210 printf("optimizationLevel: %u\n\n", bcWrapper.getOptimizationLevel()); 211 212 bcinfo::BitcodeTranslator *BT = 213 new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version); 214 if (!BT->translate()) { 215 fprintf(stderr, "failed to translate bitcode\n"); 216 return 3; 217 } 218 219 bcinfo::MetadataExtractor *ME = 220 new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(), 221 BT->getTranslatedBitcodeSize()); 222 if (!ME->extract()) { 223 fprintf(stderr, "failed to get metadata\n"); 224 return 4; 225 } 226 227 dumpMetadata(ME); 228 229 delete ME; 230 delete BT; 231 232 releaseBitcode(&bitcode); 233 234 return 0; 235} 236