1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/poirot/poirot_app.h"
16 :
17 : #include "base/at_exit.h"
18 : #include "base/command_line.h"
19 : #include "base/files/file_util.h"
20 :
21 : namespace poirot {
22 :
23 : namespace {
24 :
25 : const char kUsageFormatStr[] =
26 : "Usage: %ls [options]\n"
27 : "\n"
28 : " Read a minidump and extract the Kasko protobuf that is in it.\n"
29 : "\n"
30 : "Required parameters\n"
31 : " --input-minidump=<image file>\n"
32 : " The minidump to process.\n"
33 : "Optional parameters\n"
34 : " --output-file=<output file>\n"
35 : " Optionally provide the name or path to the output file. If not\n"
36 : " provided, output will be to standard out.\n";
37 :
38 : } // namespace
39 :
40 : void PoirotApp::PrintUsage(const base::FilePath& program,
41 E : const base::StringPiece& message) {
42 E : if (!message.empty()) {
43 E : ::fwrite(message.data(), 1, message.length(), out());
44 E : ::fprintf(out(), "\n\n");
45 : }
46 :
47 E : ::fprintf(out(), kUsageFormatStr, program.BaseName().value().c_str());
48 E : }
49 :
50 E : bool PoirotApp::ParseCommandLine(const base::CommandLine* cmd_line) {
51 E : DCHECK_NE(static_cast<const base::CommandLine*>(nullptr), cmd_line);
52 :
53 E : if (cmd_line->HasSwitch("help")) {
54 E : PrintUsage(cmd_line->GetProgram(), "");
55 E : return false;
56 : }
57 :
58 E : input_minidump_ = cmd_line->GetSwitchValuePath("input-minidump");
59 E : if (input_minidump_.empty()) {
60 E : PrintUsage(cmd_line->GetProgram(),
61 : "Must specify '--input-minidump' parameter!");
62 E : return false;
63 : }
64 :
65 : // If no output file is specified stdout will be used.
66 E : output_file_ = cmd_line->GetSwitchValuePath("output-file");
67 :
68 E : return true;
69 E : }
70 :
71 E : int PoirotApp::Run() {
72 : // Output defaults to STDOUT.
73 E : FILE* output_file = stdout;
74 :
75 : // If an output file is specified, make sure we close it on exit.
76 E : base::ScopedFILE scoped_file;
77 :
78 : // Open the output file, if one is provided. This is done early so as to fail
79 : // fast on problems with the output file or path.
80 E : if (!output_file_.empty()) {
81 E : scoped_file.reset(base::OpenFile(output_file_, "w"));
82 :
83 E : if (!scoped_file.get()) {
84 i : LOG(ERROR) << "Unable to open output file '" << output_file_.value()
85 : << "'.";
86 i : return 1;
87 : }
88 :
89 E : output_file = scoped_file.get();
90 : }
91 :
92 : // Do the processing.
93 E : MinidumpProcessor processor(input_minidump_);
94 E : if (!processor.ProcessDump())
95 E : return 1;
96 :
97 : // And write the output file.
98 E : if (!processor.GenerateJsonOutput(output_file))
99 i : return 1;
100 :
101 E : return 0;
102 E : }
103 :
104 : } // namespace poirot
|