C++程序  |  195行  |  4.45 KB

/*
 * Copyright 2011, The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <bcinfo/BitcodeTranslator.h>
#include <bcinfo/MetadataExtractor.h>

#include <ctype.h>
#include <dlfcn.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>

#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <unistd.h>

#include <vector>

// This file corresponds to the standalone bcinfo tool. It prints a variety of
// information about a supplied bitcode input file.

const char* inFile = NULL;

extern int opterr;
extern int optind;

bool translate = false;

static int parseOption(int argc, char** argv) {
  int c;
  while ((c = getopt(argc, argv, "t")) != -1) {
    opterr = 0;

    switch(c) {
      case '?':
        // ignore any error
        break;

      case 't':
        translate = true;
        break;

      default:
        // Critical error occurs
        return 0;
        break;
    }
  }

  if(optind >= argc) {
    fprintf(stderr, "input file required\n");
    return 0;
  }

  inFile = argv[optind];
  return 1;
}


static void dumpMetadata(bcinfo::MetadataExtractor *ME) {
  if (!ME) {
    return;
  }

  printf("exportVarCount: %u\n", ME->getExportVarCount());
  printf("exportFuncCount: %u\n", ME->getExportFuncCount());

  printf("exportForEachSignatureCount: %u\n",
         ME->getExportForEachSignatureCount());
  const uint32_t *sigList = ME->getExportForEachSignatureList();
  for (size_t i = 0; i < ME->getExportForEachSignatureCount(); i++) {
    printf("exportForEachSignatureList[%u]: %u\n", i, sigList[i]);
  }

  printf("pragmaCount: %u\n", ME->getPragmaCount());
  const char **keyList = ME->getPragmaKeyList();
  const char **valueList = ME->getPragmaValueList();
  for (size_t i = 0; i < ME->getPragmaCount(); i++) {
    printf("pragma[%u]: %s - %s\n", i, keyList[i], valueList[i]);
  }

  printf("objectSlotCount: %u\n", ME->getObjectSlotCount());
  const uint32_t *slotList = ME->getObjectSlotList();
  for (size_t i = 0; i < ME->getObjectSlotCount(); i++) {
    printf("objectSlotList[%u]: %u\n", i, slotList[i]);
  }

  return;
}


static size_t readBitcode(const char **bitcode) {
  if (!inFile) {
    fprintf(stderr, "input file required\n");
    return NULL;
  }

  struct stat statInFile;
  if (stat(inFile, &statInFile) < 0) {
    fprintf(stderr, "Unable to stat input file: %s\n", strerror(errno));
    return NULL;
  }

  if (!S_ISREG(statInFile.st_mode)) {
    fprintf(stderr, "Input file should be a regular file.\n");
    return NULL;
  }

  FILE *in = fopen(inFile, "r");
  if (!in) {
    fprintf(stderr, "Could not open input file %s\n", inFile);
    return NULL;
  }

  size_t bitcodeSize = statInFile.st_size;

  *bitcode = (const char*) calloc(1, bitcodeSize + 1);
  size_t nread = fread((void*) *bitcode, 1, bitcodeSize, in);

  if (nread != bitcodeSize)
      fprintf(stderr, "Could not read all of file %s\n", inFile);

  fclose(in);
  return nread;
}


static void releaseBitcode(const char **bitcode) {
  if (bitcode && *bitcode) {
    free((void*) *bitcode);
    *bitcode = NULL;
  }
  return;
}


int main(int argc, char** argv) {
  if(!parseOption(argc, argv)) {
    fprintf(stderr, "failed to parse option\n");
    return 1;
  }

  const char *bitcode = NULL;
  const char *translatedBitcode = NULL;
  size_t bitcodeSize = readBitcode(&bitcode);

  unsigned int version = 14;

  if (translate) {
    version = 12;
  }

  bcinfo::BitcodeTranslator *BT =
      new bcinfo::BitcodeTranslator(bitcode, bitcodeSize, version);
  if (!BT->translate()) {
    fprintf(stderr, "failed to translate bitcode\n");
    return 2;
  }

  bcinfo::MetadataExtractor *ME =
      new bcinfo::MetadataExtractor(BT->getTranslatedBitcode(),
                                    BT->getTranslatedBitcodeSize());
  if (!ME->extract()) {
    fprintf(stderr, "failed to get metadata\n");
    return 3;
  }

  dumpMetadata(ME);

  delete ME;
  delete BT;

  releaseBitcode(&bitcode);

  return 0;
}