void llvm::parseInputMachO()

in MachODump.cpp [911:1133]


void llvm::parseInputMachO(StringRef Filename) {
  // Check for -arch all and verifiy the -arch flags are valid.
  for (unsigned i = 0; i < ArchFlags.size(); ++i) {
    if (ArchFlags[i] == "all") {
      ArchAll = true;
    } else {
      if (!MachOObjectFile::isValidArch(ArchFlags[i])) {
        errs() << "llvm-mctoll: Unknown architecture named '" + ArchFlags[i] +
                      "'for the -arch option\n";
        return;
      }
    }
  }

  // Attempt to open the binary.
  Expected<OwningBinary<Binary>> BinaryOrErr = createBinary(Filename);
  if (!BinaryOrErr) {
    if (auto E = isNotObjectErrorInvalidFileType(BinaryOrErr.takeError()))
      report_error(std::move(E), Filename);
    else
      outs() << Filename << ": is not an object file\n";
    return;
  }
  Binary &Bin = *BinaryOrErr.get().getBinary();

  if (Archive *A = dyn_cast<Archive>(&Bin)) {
    outs() << "Archive : " << Filename << "\n";

    Error Err = Error::success();
    for (auto &C : A->children(Err)) {
      Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
      if (!ChildOrErr) {
        if (auto E = isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
          report_error(std::move(E), Filename, C);
        continue;
      }
      if (MachOObjectFile *O = dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
        if (!checkMachOAndArchFlags(O, Filename))
          return;
        ProcessMachO(Filename, O, O->getFileName());
      }
    }
    if (Err)
      report_error(std::move(Err), Filename);
    return;
  }

  if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(&Bin)) {
    // If we have a list of architecture flags specified dump only those.
    if (!ArchAll && ArchFlags.size() != 0) {
      // Look for a slice in the universal binary that matches each ArchFlag.
      bool ArchFound;
      for (unsigned i = 0; i < ArchFlags.size(); ++i) {
        ArchFound = false;
        for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
                                                   E = UB->end_objects();
             I != E; ++I) {
          if (ArchFlags[i] == I->getArchFlagName()) {
            ArchFound = true;
            Expected<std::unique_ptr<ObjectFile>> ObjOrErr =
                I->getAsObjectFile();
            std::string ArchitectureName = "";
            if (ArchFlags.size() > 1)
              ArchitectureName = I->getArchFlagName();
            if (ObjOrErr) {
              ObjectFile &O = *ObjOrErr.get();
              if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
                ProcessMachO(Filename, MachOOF, "", ArchitectureName);
            } else if (auto E = isNotObjectErrorInvalidFileType(
                           ObjOrErr.takeError())) {
              report_error(std::move(E), Filename, StringRef(),
                           ArchitectureName);
              continue;
            } else if (Expected<std::unique_ptr<Archive>> AOrErr =
                           I->getAsArchive()) {
              std::unique_ptr<Archive> &A = *AOrErr;
              outs() << "Archive : " << Filename;
              if (!ArchitectureName.empty())
                outs() << " (architecture " << ArchitectureName << ")";
              outs() << "\n";
              Error Err = Error::success();
              for (auto &C : A->children(Err)) {
                Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
                if (!ChildOrErr) {
                  if (auto E = isNotObjectErrorInvalidFileType(
                          ChildOrErr.takeError()))
                    report_error(std::move(E), Filename, C, ArchitectureName);
                  continue;
                }
                if (MachOObjectFile *O =
                        dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
                  ProcessMachO(Filename, O, O->getFileName(), ArchitectureName);
              }
              if (Err)
                report_error(std::move(Err), Filename);
            } else {
              consumeError(AOrErr.takeError());
              error("Mach-O universal file: " + Filename + " for " +
                    "architecture " + StringRef(I->getArchFlagName()) +
                    " is not a Mach-O file or an archive file");
            }
          }
        }
        if (!ArchFound) {
          errs() << "llvm-mctoll: file: " + Filename + " does not contain "
                 << "architecture: " + ArchFlags[i] + "\n";
          return;
        }
      }
      return;
    }
    // No architecture flags were specified so if this contains a slice that
    // matches the host architecture dump only that.
    if (!ArchAll) {
      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
                                                 E = UB->end_objects();
           I != E; ++I) {
        if (MachOObjectFile::getHostArch().getArchName() ==
            I->getArchFlagName()) {
          Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
          std::string ArchiveName;
          ArchiveName.clear();
          if (ObjOrErr) {
            ObjectFile &O = *ObjOrErr.get();
            if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&O))
              ProcessMachO(Filename, MachOOF);
          } else if (auto E = isNotObjectErrorInvalidFileType(
                         ObjOrErr.takeError())) {
            report_error(std::move(E), Filename);
            continue;
          } else if (Expected<std::unique_ptr<Archive>> AOrErr =
                         I->getAsArchive()) {
            std::unique_ptr<Archive> &A = *AOrErr;
            Error Err = Error::success();
            for (auto &C : A->children(Err)) {
              Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
              if (!ChildOrErr) {
                if (auto E =
                        isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
                  report_error(std::move(E), Filename, C);
                continue;
              }
              if (MachOObjectFile *O =
                      dyn_cast<MachOObjectFile>(&*ChildOrErr.get()))
                ProcessMachO(Filename, O, O->getFileName());
            }
            if (Err)
              report_error(std::move(Err), Filename);
          } else {
            consumeError(AOrErr.takeError());
            error("Mach-O universal file: " + Filename + " for architecture " +
                  StringRef(I->getArchFlagName()) +
                  " is not a Mach-O file or an archive file");
          }
          return;
        }
      }
    }
    // Either all architectures have been specified or none have been specified
    // and this does not contain the host architecture so dump all the slices.
    bool moreThanOneArch = UB->getNumberOfObjects() > 1;
    for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
                                               E = UB->end_objects();
         I != E; ++I) {
      Expected<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
      std::string ArchitectureName = "";
      if (moreThanOneArch)
        ArchitectureName = I->getArchFlagName();
      if (ObjOrErr) {
        ObjectFile &Obj = *ObjOrErr.get();
        if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&Obj))
          ProcessMachO(Filename, MachOOF, "", ArchitectureName);
      } else if (auto E =
                     isNotObjectErrorInvalidFileType(ObjOrErr.takeError())) {
        report_error(std::move(E), Filename, StringRef(), ArchitectureName);

        continue;
      } else if (Expected<std::unique_ptr<Archive>> AOrErr =
                     I->getAsArchive()) {
        std::unique_ptr<Archive> &A = *AOrErr;
        outs() << "Archive : " << Filename;
        if (!ArchitectureName.empty())
          outs() << " (architecture " << ArchitectureName << ")";
        outs() << "\n";
        Error Err = Error::success();
        for (auto &C : A->children(Err)) {
          Expected<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary();
          if (!ChildOrErr) {
            if (auto E =
                    isNotObjectErrorInvalidFileType(ChildOrErr.takeError()))
              report_error(std::move(E), Filename, C, ArchitectureName);
            continue;
          }
          if (MachOObjectFile *O =
                  dyn_cast<MachOObjectFile>(&*ChildOrErr.get())) {
            if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(O))
              ProcessMachO(Filename, MachOOF, MachOOF->getFileName(),
                           ArchitectureName);
          }
        }
        if (Err)
          report_error(std::move(Err), Filename);
      } else {
        consumeError(AOrErr.takeError());
        error("Mach-O universal file: " + Filename + " for architecture " +
              StringRef(I->getArchFlagName()) +
              " is not a Mach-O file or an archive file");
      }
    }
    return;
  }
  if (ObjectFile *O = dyn_cast<ObjectFile>(&Bin)) {
    if (!checkMachOAndArchFlags(O, Filename))
      return;
    if (MachOObjectFile *MachOOF = dyn_cast<MachOObjectFile>(&*O)) {
      ProcessMachO(Filename, MachOOF);
    } else
      errs() << "llvm-mctoll: '" << Filename << "': "
             << "Object is not a Mach-O file type.\n";
    return;
  }
  llvm_unreachable("Input object can't be invalid at this point");
}