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