Home | History | Annotate | Download | only in tools
      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 
     41 const char* inFile = NULL;
     42 
     43 extern int opterr;
     44 extern int optind;
     45 
     46 bool translateFlag = false;
     47 
     48 static 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 
     79 static 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 
    143 static 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 
    179 static void releaseBitcode(const char **bitcode) {
    180   if (bitcode && *bitcode) {
    181     free((void*) *bitcode);
    182     *bitcode = NULL;
    183   }
    184   return;
    185 }
    186 
    187 
    188 int 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