1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
11 #include "base/command_line.h"
12 #include "base/strings/string_split.h"
13 #include "third_party/re2/re2/re2.h"
14 #include "tools/ipc_fuzzer/message_lib/message_file.h"
15 #include "tools/ipc_fuzzer/message_lib/message_names.h"
19 const char kDumpSwitch
[] = "dump";
20 const char kDumpSwitchHelp
[] =
21 "dump human-readable form to stdout instead of copying.";
23 const char kEndSwitch
[] = "end";
24 const char kEndSwitchHelp
[] =
25 "output messages before |m|th message in file (exclusive).";
27 const char kHelpSwitch
[] = "help";
28 const char kHelpSwitchHelp
[] =
29 "display this message.";
31 const char kInvertSwitch
[] = "invert";
32 const char kInvertSwitchHelp
[] =
33 "output messages NOT meeting above criteria.";
35 const char kRegexpSwitch
[] = "regexp";
36 const char kRegexpSwitchHelp
[] =
37 "output messages matching regular expression |x|.";
39 const char kStartSwitch
[] = "start";
40 const char kStartSwitchHelp
[] =
41 "output messages after |n|th message in file (inclusive).";
44 std::cerr
<< "ipc_message_util: Concatenate all |infile| message files and "
45 << "copy a subset of the result to |outfile|.\n";
47 std::cerr
<< "Usage:\n"
48 << " ipc_message_util"
49 << " [--" << kStartSwitch
<< "=n]"
50 << " [--" << kEndSwitch
<< "=m]"
51 << " [--" << kRegexpSwitch
<< "=x]"
52 << " [--" << kInvertSwitch
<< "]"
53 << " [--" << kDumpSwitch
<< "]"
54 << " [--" << kHelpSwitch
<< "]"
55 << " infile,infile,... [outfile]\n";
57 std::cerr
<< " --" << kStartSwitch
<< " - " << kStartSwitchHelp
<< "\n"
58 << " --" << kEndSwitch
<< " - " << kEndSwitchHelp
<< "\n"
59 << " --" << kRegexpSwitch
<< " - " << kRegexpSwitchHelp
<< "\n"
60 << " --" << kInvertSwitch
<< " - " << kInvertSwitchHelp
<< "\n"
61 << " --" << kDumpSwitch
<< " - " << kDumpSwitchHelp
<< "\n"
62 << " --" << kHelpSwitch
<< " - " << kHelpSwitchHelp
<< "\n";
65 std::string
MessageName(const IPC::Message
* msg
) {
66 return ipc_fuzzer::MessageNames::GetInstance()->TypeToName(msg
->type());
69 bool MessageMatches(const IPC::Message
* msg
, const RE2
& pattern
) {
70 return RE2::FullMatch(MessageName(msg
), pattern
);
75 int main(int argc
, char** argv
) {
76 CommandLine::Init(argc
, argv
);
77 CommandLine
* cmd
= CommandLine::ForCurrentProcess();
78 CommandLine::StringVector args
= cmd
->GetArgs();
80 if (args
.size() < 1 || args
.size() > 2 || cmd
->HasSwitch(kHelpSwitch
)) {
85 size_t start_index
= 0;
86 if (cmd
->HasSwitch(kStartSwitch
)) {
87 int temp
= atoi(cmd
->GetSwitchValueASCII(kStartSwitch
).c_str());
89 start_index
= static_cast<size_t>(temp
);
92 size_t end_index
= INT_MAX
;
93 if (cmd
->HasSwitch(kEndSwitch
)) {
94 int temp
= atoi(cmd
->GetSwitchValueASCII(kEndSwitch
).c_str());
96 end_index
= static_cast<size_t>(temp
);
99 bool has_regexp
= cmd
->HasSwitch(kRegexpSwitch
);
100 RE2
filter_pattern(cmd
->GetSwitchValueASCII(kRegexpSwitch
));
102 bool invert
= cmd
->HasSwitch(kInvertSwitch
);
103 bool perform_dump
= cmd
->HasSwitch(kDumpSwitch
);
105 std::vector
<std::string
> input_file_names
;
106 std::string output_file_name
;
107 base::SplitString(args
[0], ',', &input_file_names
);
110 if (args
.size() < 2) {
114 output_file_name
= args
[1];
117 ipc_fuzzer::MessageVector input_message_vector
;
118 for (std::vector
<std::string
>::iterator it
= input_file_names
.begin();
119 it
!= input_file_names
.end(); ++it
) {
120 ipc_fuzzer::MessageVector message_vector
;
121 if (!ipc_fuzzer::MessageFile::Read(base::FilePath(*it
), &message_vector
))
123 input_message_vector
.insert(input_message_vector
.end(),
124 message_vector
.begin(), message_vector
.end());
125 message_vector
.weak_clear();
128 ipc_fuzzer::MessageVector output_message_vector
;
129 std::vector
<size_t> remap_vector
;
131 for (size_t i
= 0; i
< input_message_vector
.size(); ++i
) {
132 bool valid
= (i
>= start_index
&& i
< end_index
);
133 if (valid
&& has_regexp
) {
134 valid
= MessageMatches(input_message_vector
[i
], filter_pattern
);
136 if (valid
!= invert
) {
137 output_message_vector
.push_back(input_message_vector
[i
]);
138 remap_vector
.push_back(i
);
139 input_message_vector
[i
] = NULL
;
144 for (size_t i
= 0; i
< output_message_vector
.size(); ++i
) {
145 std::cout
<< remap_vector
[i
] << ". "
146 << MessageName(output_message_vector
[i
]) << "\n";
149 if (!ipc_fuzzer::MessageFile::Write(
150 base::FilePath(output_file_name
), output_message_vector
)) {