static void DumpBitcodeSection()

in MachODump.cpp [3064:3261]


static void DumpBitcodeSection(MachOObjectFile *O, const char *sect,
                               uint32_t size, bool verbose, bool PrintXarHeader,
                               bool PrintXarFileHeaders,
                               std::string XarMemberName) {
  if (size < sizeof(struct xar_header)) {
    outs() << "size of (__LLVM,__bundle) section too small (smaller than size "
              "of struct xar_header)\n";
    return;
  }
  struct xar_header XarHeader;
  memcpy(&XarHeader, sect, sizeof(struct xar_header));
  if (sys::IsLittleEndianHost)
    swapStruct(XarHeader);
  if (PrintXarHeader) {
    if (!XarMemberName.empty())
      outs() << "In xar member " << XarMemberName << ": ";
    else
      outs() << "For (__LLVM,__bundle) section: ";
    outs() << "xar header\n";
    if (XarHeader.magic == XAR_HEADER_MAGIC)
      outs() << "                  magic XAR_HEADER_MAGIC\n";
    else
      outs() << "                  magic "
             << format_hex(XarHeader.magic, 10, true)
             << " (not XAR_HEADER_MAGIC)\n";
    outs() << "                   size " << XarHeader.size << "\n";
    outs() << "                version " << XarHeader.version << "\n";
    outs() << "  toc_length_compressed " << XarHeader.toc_length_compressed
           << "\n";
    outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed
           << "\n";
    outs() << "              cksum_alg ";
    switch (XarHeader.cksum_alg) {
    case XAR_CKSUM_NONE:
      outs() << "XAR_CKSUM_NONE\n";
      break;
    case XAR_CKSUM_SHA1:
      outs() << "XAR_CKSUM_SHA1\n";
      break;
    case XAR_CKSUM_MD5:
      outs() << "XAR_CKSUM_MD5\n";
      break;
#ifdef XAR_CKSUM_SHA256
    case XAR_CKSUM_SHA256:
      outs() << "XAR_CKSUM_SHA256\n";
      break;
#endif
#ifdef XAR_CKSUM_SHA512
    case XAR_CKSUM_SHA512:
      outs() << "XAR_CKSUM_SHA512\n";
      break;
#endif
    default:
      outs() << XarHeader.cksum_alg << "\n";
    }
  }

  SmallString<128> XarFilename;
  int FD;
  std::error_code XarEC =
      sys::fs::createTemporaryFile("llvm-mctoll", "xar", FD, XarFilename);
  if (XarEC) {
    errs() << XarEC.message() << "\n";
    return;
  }
  ToolOutputFile XarFile(XarFilename, FD);
  raw_fd_ostream &XarOut = XarFile.os();
  StringRef XarContents(sect, size);
  XarOut << XarContents;
  XarOut.close();
  if (XarOut.has_error())
    return;

  xar_t xar = xar_open(XarFilename.c_str(), READ);
  if (!xar) {
    errs() << "Can't create temporary xar archive " << XarFilename << "\n";
    return;
  }

  SmallString<128> TocFilename;
  std::error_code TocEC =
      sys::fs::createTemporaryFile("llvm-mctoll", "toc", TocFilename);
  if (TocEC) {
    errs() << TocEC.message() << "\n";
    return;
  }
  xar_serialize(xar, TocFilename.c_str());

  if (PrintXarFileHeaders) {
    if (!XarMemberName.empty())
      outs() << "In xar member " << XarMemberName << ": ";
    else
      outs() << "For (__LLVM,__bundle) section: ";
    outs() << "xar archive files:\n";
    PrintXarFilesSummary(XarFilename.c_str(), xar);
  }

  ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
      MemoryBuffer::getFileOrSTDIN(TocFilename.c_str());
  if (std::error_code EC = FileOrErr.getError()) {
    errs() << EC.message() << "\n";
    return;
  }
  std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();

  if (!XarMemberName.empty())
    outs() << "In xar member " << XarMemberName << ": ";
  else
    outs() << "For (__LLVM,__bundle) section: ";
  outs() << "xar table of contents:\n";
  outs() << Buffer->getBuffer() << "\n";

  // TODO: Go through the xar's files.
  xar_iter_t xi = xar_iter_new();
  if (!xi) {
    errs() << "Can't obtain an xar iterator for xar archive "
           << XarFilename.c_str() << "\n";
    xar_close(xar);
    return;
  }
  for (xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) {
    const char *key;
    xar_iter_t xp;
    const char *member_name, *member_type, *member_size_string;
    size_t member_size;

    xp = xar_iter_new();
    if (!xp) {
      errs() << "Can't obtain an xar iterator for xar archive "
             << XarFilename.c_str() << "\n";
      xar_close(xar);
      return;
    }
    member_name = NULL;
    member_type = NULL;
    member_size_string = NULL;
    for (key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)) {
      const char *val = nullptr;
      xar_prop_get(xf, key, &val);
#if 0 // Useful for debugging.
      outs() << "key: " << key << " value: " << val << "\n";
#endif
      if (strcmp(key, "name") == 0)
        member_name = val;
      if (strcmp(key, "type") == 0)
        member_type = val;
      if (strcmp(key, "data/size") == 0)
        member_size_string = val;
    }
    /*
     * If we find a file with a name, date/size and type properties
     * and with the type being "file" see if that is a xar file.
     */
    if (member_name != NULL && member_type != NULL &&
        strcmp(member_type, "file") == 0 && member_size_string != NULL) {
      // Extract the file into a buffer.
      char *endptr;
      member_size = strtoul(member_size_string, &endptr, 10);
      if (*endptr == '\0' && member_size != 0) {
        char *buffer = (char *)::operator new(member_size);
        if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) {
#if 0 // Useful for debugging.
          outs() << "xar member: " << member_name << " extracted\n";
#endif
          // Set the XarMemberName we want to see printed in the header.
          std::string OldXarMemberName;
          // If XarMemberName is already set this is nested. So
          // save the old name and create the nested name.
          if (!XarMemberName.empty()) {
            OldXarMemberName = XarMemberName;
            XarMemberName =
                (Twine("[") + XarMemberName + "]" + member_name).str();
          } else {
            OldXarMemberName = "";
            XarMemberName = member_name;
          }
          // See if this is could be a xar file (nested).
          if (member_size >= sizeof(struct xar_header)) {
#if 0 // Useful for debugging.
            outs() << "could be a xar file: " << member_name << "\n";
#endif
            memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header));
            if (sys::IsLittleEndianHost)
              swapStruct(XarHeader);
            if (XarHeader.magic == XAR_HEADER_MAGIC)
              DumpBitcodeSection(O, buffer, member_size, verbose,
                                 PrintXarHeader, PrintXarFileHeaders,
                                 XarMemberName);
          }
          XarMemberName = OldXarMemberName;
        }
        delete buffer;
      }
    }
    xar_iter_free(xp);
  }
  xar_close(xar);
}