1 //===-- llvm-tapi-diff.cpp - tbd comparator command-line driver ---*-
2 // C++
3 //-*-===//
4 //
5 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
6 // See https://llvm.org/LICENSE.txt for license information.
7 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 //
9 //===----------------------------------------------------------------------===//
10 //
11 // This file defines the command-line driver for the llvm-tapi difference
12 // engine.
13 //
14 //===----------------------------------------------------------------------===//
15 #include "DiffEngine.h"
16 #include "llvm/Object/TapiUniversal.h"
17 #include "llvm/Support/CommandLine.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/InitLLVM.h"
20 #include "llvm/Support/WithColor.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include <cstdlib>
23 
24 using namespace llvm;
25 using namespace MachO;
26 using namespace object;
27 
28 namespace {
29 cl::OptionCategory NMCat("llvm-tapi-diff Options");
30 cl::opt<std::string> InputFileNameLHS(cl::Positional, cl::desc("<first file>"),
31                                       cl::cat(NMCat));
32 cl::opt<std::string> InputFileNameRHS(cl::Positional, cl::desc("<second file>"),
33                                       cl::cat(NMCat));
34 
35 std::string ToolName;
36 } // anonymous namespace
37 
38 ExitOnError ExitOnErr;
39 
setErrorBanner(ExitOnError & ExitOnErr,std::string InputFile)40 void setErrorBanner(ExitOnError &ExitOnErr, std::string InputFile) {
41   ExitOnErr.setBanner(ToolName + ": error: " + InputFile + ": ");
42 }
43 
convertFileToBinary(std::string & Filename)44 Expected<std::unique_ptr<Binary>> convertFileToBinary(std::string &Filename) {
45   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
46       MemoryBuffer::getFileOrSTDIN(Filename);
47   if (BufferOrErr.getError())
48     return errorCodeToError(BufferOrErr.getError());
49   return createBinary(BufferOrErr.get()->getMemBufferRef());
50 }
51 
main(int Argc,char ** Argv)52 int main(int Argc, char **Argv) {
53   InitLLVM X(Argc, Argv);
54   cl::HideUnrelatedOptions(NMCat);
55   cl::ParseCommandLineOptions(
56       Argc, Argv,
57       "This tool will compare two tbd files and return the "
58       "differences in those files.");
59   if (InputFileNameLHS.empty() || InputFileNameRHS.empty()) {
60     cl::PrintHelpMessage();
61     return EXIT_FAILURE;
62   }
63 
64   ToolName = Argv[0];
65 
66   setErrorBanner(ExitOnErr, InputFileNameLHS);
67   auto BinLHS = ExitOnErr(convertFileToBinary(InputFileNameLHS));
68 
69   TapiUniversal *FileLHS = dyn_cast<TapiUniversal>(BinLHS.get());
70   if (!FileLHS) {
71     ExitOnErr(
72         createStringError(std::errc::executable_format_error,
73                           "Error when parsing file, unsupported file format"));
74   }
75 
76   setErrorBanner(ExitOnErr, InputFileNameRHS);
77   auto BinRHS = ExitOnErr(convertFileToBinary(InputFileNameRHS));
78 
79   TapiUniversal *FileRHS = dyn_cast<TapiUniversal>(BinRHS.get());
80   if (!FileRHS) {
81     ExitOnErr(
82         createStringError(std::errc::executable_format_error,
83                           "Error when parsing file, unsupported file format"));
84   }
85 
86   raw_ostream &OS = outs();
87 
88   return DiffEngine(FileLHS, FileRHS).compareFiles(OS);
89 }
90