Exemple #1
0
static void dumpSymbolNamesFromFile(std::string &Filename) {
  ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
      MemoryBuffer::getFileOrSTDIN(Filename);
  if (error(BufferOrErr.getError(), Filename))
    return;

  LLVMContext &Context = getGlobalContext();
  ErrorOr<std::unique_ptr<Binary>> BinaryOrErr = createBinary(
      BufferOrErr.get()->getMemBufferRef(), NoLLVMBitcode ? nullptr : &Context);
  if (error(BinaryOrErr.getError(), Filename))
    return;
  Binary &Bin = *BinaryOrErr.get();

  if (Archive *A = dyn_cast<Archive>(&Bin)) {
    if (ArchiveMap) {
      Archive::symbol_iterator I = A->symbol_begin();
      Archive::symbol_iterator E = A->symbol_end();
      if (I != E) {
        outs() << "Archive map\n";
        for (; I != E; ++I) {
          ErrorOr<Archive::Child> C = I->getMember();
          if (error(C.getError()))
            return;
          ErrorOr<StringRef> FileNameOrErr = C->getName();
          if (error(FileNameOrErr.getError()))
            return;
          StringRef SymName = I->getName();
          outs() << SymName << " in " << FileNameOrErr.get() << "\n";
        }
        outs() << "\n";
      }
    }

    for (Archive::child_iterator I = A->child_begin(), E = A->child_end();
         I != E; ++I) {
      if (error(I->getError()))
        return;
      auto &C = I->get();
      ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(&Context);
      if (ChildOrErr.getError())
        continue;
      if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
        if (!checkMachOAndArchFlags(O, Filename))
          return;
        if (!PrintFileName) {
          outs() << "\n";
          if (isa<MachOObjectFile>(O)) {
            outs() << Filename << "(" << O->getFileName() << ")";
          } else
            outs() << O->getFileName();
          outs() << ":\n";
        }
        dumpSymbolNamesFromObject(*O, false, 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->getArchTypeName()) {
            ArchFound = true;
            ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
                I->getAsObjectFile();
            std::string ArchiveName;
            std::string ArchitectureName;
            ArchiveName.clear();
            ArchitectureName.clear();
            if (ObjOrErr) {
              ObjectFile &Obj = *ObjOrErr.get();
              if (ArchFlags.size() > 1) {
                if (PrintFileName)
                  ArchitectureName = I->getArchTypeName();
                else
                  outs() << "\n" << Obj.getFileName() << " (for architecture "
                         << I->getArchTypeName() << ")"
                         << ":\n";
              }
              dumpSymbolNamesFromObject(Obj, false, ArchiveName,
                                        ArchitectureName);
            } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
                           I->getAsArchive()) {
              std::unique_ptr<Archive> &A = *AOrErr;
              for (Archive::child_iterator AI = A->child_begin(),
                                           AE = A->child_end();
                   AI != AE; ++AI) {
                if (error(AI->getError()))
                  return;
                auto &C = AI->get();
                ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
                    C.getAsBinary(&Context);
                if (ChildOrErr.getError())
                  continue;
                if (SymbolicFile *O =
                        dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
                  if (PrintFileName) {
                    ArchiveName = A->getFileName();
                    if (ArchFlags.size() > 1)
                      ArchitectureName = I->getArchTypeName();
                  } else {
                    outs() << "\n" << A->getFileName();
                    outs() << "(" << O->getFileName() << ")";
                    if (ArchFlags.size() > 1) {
                      outs() << " (for architecture " << I->getArchTypeName()
                             << ")";
                    }
                    outs() << ":\n";
                  }
                  dumpSymbolNamesFromObject(*O, false, ArchiveName,
                                            ArchitectureName);
                }
              }
            }
          }
        }
        if (!ArchFound) {
          error(ArchFlags[i],
                "file: " + Filename + " does not contain architecture");
          return;
        }
      }
      return;
    }
    // No architecture flags were specified so if this contains a slice that
    // matches the host architecture dump only that.
    if (!ArchAll) {
      StringRef HostArchName = MachOObjectFile::getHostArch().getArchName();
      for (MachOUniversalBinary::object_iterator I = UB->begin_objects(),
                                                 E = UB->end_objects();
           I != E; ++I) {
        if (HostArchName == I->getArchTypeName()) {
          ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
          std::string ArchiveName;
          ArchiveName.clear();
          if (ObjOrErr) {
            ObjectFile &Obj = *ObjOrErr.get();
            dumpSymbolNamesFromObject(Obj, false);
          } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr =
                         I->getAsArchive()) {
            std::unique_ptr<Archive> &A = *AOrErr;
            for (Archive::child_iterator AI = A->child_begin(),
                                         AE = A->child_end();
                 AI != AE; ++AI) {
              if (error(AI->getError()))
                return;
              auto &C = AI->get();
              ErrorOr<std::unique_ptr<Binary>> ChildOrErr =
                  C.getAsBinary(&Context);
              if (ChildOrErr.getError())
                continue;
              if (SymbolicFile *O =
                      dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
                if (PrintFileName)
                  ArchiveName = A->getFileName();
                else
                  outs() << "\n" << A->getFileName() << "(" << O->getFileName()
                         << ")"
                         << ":\n";
                dumpSymbolNamesFromObject(*O, false, ArchiveName);
              }
            }
          }
          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) {
      ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr = I->getAsObjectFile();
      std::string ArchiveName;
      std::string ArchitectureName;
      ArchiveName.clear();
      ArchitectureName.clear();
      if (ObjOrErr) {
        ObjectFile &Obj = *ObjOrErr.get();
        if (PrintFileName) {
          if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
            ArchitectureName = I->getArchTypeName();
        } else {
          if (moreThanOneArch)
            outs() << "\n";
          outs() << Obj.getFileName();
          if (isa<MachOObjectFile>(Obj) && moreThanOneArch)
            outs() << " (for architecture " << I->getArchTypeName() << ")";
          outs() << ":\n";
        }
        dumpSymbolNamesFromObject(Obj, false, ArchiveName, ArchitectureName);
      } else if (ErrorOr<std::unique_ptr<Archive>> AOrErr = I->getAsArchive()) {
        std::unique_ptr<Archive> &A = *AOrErr;
        for (Archive::child_iterator AI = A->child_begin(), AE = A->child_end();
             AI != AE; ++AI) {
          if (error(AI->getError()))
            return;
          auto &C = AI->get();
          ErrorOr<std::unique_ptr<Binary>> ChildOrErr = C.getAsBinary(&Context);
          if (ChildOrErr.getError())
            continue;
          if (SymbolicFile *O = dyn_cast<SymbolicFile>(&*ChildOrErr.get())) {
            if (PrintFileName) {
              ArchiveName = A->getFileName();
              if (isa<MachOObjectFile>(O) && moreThanOneArch)
                ArchitectureName = I->getArchTypeName();
            } else {
              outs() << "\n" << A->getFileName();
              if (isa<MachOObjectFile>(O)) {
                outs() << "(" << O->getFileName() << ")";
                if (moreThanOneArch)
                  outs() << " (for architecture " << I->getArchTypeName()
                         << ")";
              } else
                outs() << ":" << O->getFileName();
              outs() << ":\n";
            }
            dumpSymbolNamesFromObject(*O, false, ArchiveName, ArchitectureName);
          }
        }
      }
    }
    return;
  }
  if (SymbolicFile *O = dyn_cast<SymbolicFile>(&Bin)) {
    if (!checkMachOAndArchFlags(O, Filename))
      return;
    dumpSymbolNamesFromObject(*O, true);
  }
}