OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdarg.h> | |
5 #include <stddef.h> | 6 #include <stddef.h> |
6 #include <stdint.h> | 7 #include <stdint.h> |
7 | 8 |
9 #include <initializer_list> | |
8 #include <memory> | 10 #include <memory> |
9 #include <string> | 11 #include <string> |
10 #include <vector> | 12 #include <vector> |
11 | 13 |
12 #include "base/at_exit.h" | 14 #include "base/at_exit.h" |
13 #include "base/command_line.h" | 15 #include "base/command_line.h" |
14 #include "base/files/file_path.h" | 16 #include "base/files/file_path.h" |
15 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
16 #include "base/files/memory_mapped_file.h" | 18 #include "base/files/memory_mapped_file.h" |
17 #include "base/logging.h" | 19 #include "base/logging.h" |
20 #include "base/macros.h" | |
18 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/string_util.h" | 22 #include "base/strings/string_util.h" |
20 #include "base/strings/utf_string_conversions.h" | 23 #include "base/strings/utf_string_conversions.h" |
21 #include "courgette/assembly_program.h" | 24 #include "courgette/assembly_program.h" |
22 #include "courgette/courgette.h" | 25 #include "courgette/courgette.h" |
26 #include "courgette/courgette_flow.h" | |
23 #include "courgette/encoded_program.h" | 27 #include "courgette/encoded_program.h" |
24 #include "courgette/program_detector.h" | 28 #include "courgette/program_detector.h" |
25 #include "courgette/streams.h" | 29 #include "courgette/streams.h" |
26 #include "courgette/third_party/bsdiff/bsdiff.h" | 30 #include "courgette/third_party/bsdiff/bsdiff.h" |
27 | 31 |
32 namespace { | |
33 | |
34 using courgette::CourgetteFlow; | |
35 | |
36 const char kUsageGen[] = "-gen <old_in> <new_in> <patch_out>"; | |
37 const char kUsageApply[] = "-apply <old_in> <patch_in> <new_out>"; | |
38 const char kUsageGenbsdiff[] = "-genbsdiff <old_in> <new_in> <patch_out>"; | |
39 const char kUsageApplybsdiff[] = "-applybsdiff <old_in> <patch_in> <new_out>"; | |
40 const char kUsageSupported[] = "-supported <exec_file_in>"; | |
41 const char kUsageDis[] = "-dis <exec_file_in> <assembly_file_out>"; | |
42 const char kUsageAsm[] = "-asm <assembly_file_in> <exec_file_out>"; | |
43 const char kUsageDisadj[] = "-disadj <old_in> <new_in> <new_assembly_file_out>"; | |
44 const char kUsageGen1[] = "-gen1[au] <old_in> <new_in> <patch_base_out>"; | |
45 | |
46 /******** Utilities to print help and exit ********/ | |
47 | |
28 void PrintHelp() { | 48 void PrintHelp() { |
29 fprintf(stderr, | 49 fprintf(stderr, "Main Usage:\n"); |
30 "Usage:\n" | 50 for (auto usage : |
31 " courgette -supported <executable_file>\n" | 51 {kUsageGen, kUsageApply, kUsageGenbsdiff, kUsageApplybsdiff}) { |
32 " courgette -dis <executable_file> <binary_assembly_file>\n" | 52 fprintf(stderr, " courgette %s\n", usage); |
33 " courgette -asm <binary_assembly_file> <executable_file>\n" | 53 } |
34 " courgette -disadj <executable_file> <reference> <binary_assembly_file>\n" | 54 fprintf(stderr, "Diagnosis Usage:\n"); |
35 " courgette -gen <v1> <v2> <patch>\n" | 55 for (auto usage : |
36 " courgette -apply <v1> <patch> <v2>\n" | 56 {kUsageSupported, kUsageDis, kUsageAsm, kUsageDisadj, kUsageGen1}) { |
37 "\n"); | 57 fprintf(stderr, " courgette %s\n", usage); |
58 } | |
38 } | 59 } |
39 | 60 |
40 void UsageProblem(const char* message) { | 61 void UsageProblem(const char* message) { |
41 fprintf(stderr, "%s", message); | 62 fprintf(stderr, "%s", message); |
42 fprintf(stderr, "\n"); | 63 fprintf(stderr, "\n"); |
43 PrintHelp(); | 64 PrintHelp(); |
44 exit(1); | 65 exit(1); |
45 } | 66 } |
46 | 67 |
47 void Problem(const char* format, ...) { | 68 void Problem(const char* format, ...) { |
48 va_list args; | 69 va_list args; |
49 va_start(args, format); | 70 va_start(args, format); |
50 vfprintf(stderr, format, args); | 71 vfprintf(stderr, format, args); |
51 fprintf(stderr, "\n"); | 72 fprintf(stderr, "\n"); |
52 va_end(args); | 73 va_end(args); |
53 exit(1); | 74 exit(1); |
54 } | 75 } |
55 | 76 |
77 /******** BufferedFileReader ********/ | |
78 | |
56 // A file reader that calls Problem() on failure. | 79 // A file reader that calls Problem() on failure. |
57 class BufferedFileReader { | 80 class BufferedFileReader : public courgette::BasicBuffer { |
58 public: | 81 public: |
59 BufferedFileReader(const base::FilePath& file_name, const char* kind) { | 82 BufferedFileReader(const base::FilePath& file_name, const char* kind) { |
60 if (!buffer_.Initialize(file_name)) | 83 if (!buffer_.Initialize(file_name)) |
61 Problem("Can't read %s file.", kind); | 84 Problem("Can't read %s file.", kind); |
62 } | 85 } |
63 const uint8_t* data() const { return buffer_.data(); } | 86 |
64 size_t length() const { return buffer_.length(); } | 87 // courgette::BasicBuffer: |
88 const uint8_t* data() const override { return buffer_.data(); } | |
89 size_t length() const override { return buffer_.length(); } | |
65 | 90 |
66 private: | 91 private: |
67 base::MemoryMappedFile buffer_; | 92 base::MemoryMappedFile buffer_; |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(BufferedFileReader); | |
68 }; | 95 }; |
69 | 96 |
97 /******** Various helpers ********/ | |
98 | |
70 void WriteSinkToFile(const courgette::SinkStream *sink, | 99 void WriteSinkToFile(const courgette::SinkStream *sink, |
71 const base::FilePath& output_file) { | 100 const base::FilePath& output_file) { |
72 int count = | 101 int count = |
73 base::WriteFile(output_file, | 102 base::WriteFile(output_file, |
74 reinterpret_cast<const char*>(sink->Buffer()), | 103 reinterpret_cast<const char*>(sink->Buffer()), |
75 static_cast<int>(sink->Length())); | 104 static_cast<int>(sink->Length())); |
76 if (count == -1) | 105 if (count == -1) |
77 Problem("Can't write output."); | 106 Problem("Can't write output."); |
78 if (static_cast<size_t>(count) != sink->Length()) | 107 if (static_cast<size_t>(count) != sink->Length()) |
79 Problem("Incomplete write."); | 108 Problem("Incomplete write."); |
80 } | 109 } |
81 | 110 |
82 void Disassemble(const base::FilePath& input_file, | |
83 const base::FilePath& output_file) { | |
84 BufferedFileReader buffer(input_file, "input"); | |
85 | |
86 std::unique_ptr<courgette::AssemblyProgram> program; | |
87 const courgette::Status parse_status = courgette::ParseDetectedExecutable( | |
88 buffer.data(), buffer.length(), &program); | |
89 if (parse_status != courgette::C_OK) | |
90 Problem("Can't parse input (code = %d).", parse_status); | |
91 | |
92 std::unique_ptr<courgette::EncodedProgram> encoded; | |
93 const courgette::Status encode_status = Encode(*program, &encoded); | |
94 if (encode_status != courgette::C_OK) | |
95 Problem("Can't encode program."); | |
96 | |
97 program.reset(); | |
98 | |
99 courgette::SinkStreamSet sinks; | |
100 const courgette::Status write_status = | |
101 courgette::WriteEncodedProgram(encoded.get(), &sinks); | |
102 if (write_status != courgette::C_OK) | |
103 Problem("Can't serialize encoded program."); | |
104 | |
105 encoded.reset(); | |
106 | |
107 courgette::SinkStream sink; | |
108 if (!sinks.CopyTo(&sink)) | |
109 Problem("Can't combine serialized encoded program streams."); | |
110 | |
111 WriteSinkToFile(&sink, output_file); | |
112 } | |
113 | |
114 bool Supported(const base::FilePath& input_file) { | 111 bool Supported(const base::FilePath& input_file) { |
115 bool result = false; | 112 bool result = false; |
116 | 113 |
117 BufferedFileReader buffer(input_file, "input"); | 114 BufferedFileReader buffer(input_file, "input"); |
118 | 115 |
119 courgette::ExecutableType type; | 116 courgette::ExecutableType type; |
120 size_t detected_length; | 117 size_t detected_length; |
121 | 118 |
122 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); | 119 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); |
123 | 120 |
(...skipping 22 matching lines...) Expand all Loading... | |
146 case courgette::EXE_WIN_32_X64: | 143 case courgette::EXE_WIN_32_X64: |
147 format = "Windows 64 PE"; | 144 format = "Windows 64 PE"; |
148 result = true; | 145 result = true; |
149 break; | 146 break; |
150 } | 147 } |
151 | 148 |
152 printf("%s Executable\n", format.c_str()); | 149 printf("%s Executable\n", format.c_str()); |
153 return result; | 150 return result; |
154 } | 151 } |
155 | 152 |
156 void DisassembleAndAdjust(const base::FilePath& program_file, | 153 void Disassemble(const base::FilePath& input_file, |
157 const base::FilePath& model_file, | 154 const base::FilePath& output_file) { |
158 const base::FilePath& output_file) { | 155 CourgetteFlow flow; |
159 BufferedFileReader program_buffer(program_file, "program"); | 156 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
160 BufferedFileReader model_buffer(model_file, "model"); | 157 flow.ReadAssemblyProgramFromBuffer(flow.ONLY, input_buffer, false); |
161 | 158 flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); |
162 std::unique_ptr<courgette::AssemblyProgram> program; | 159 flow.DestroyAssemblyProgram(flow.ONLY); |
163 const courgette::Status parse_program_status = | 160 flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); |
164 courgette::ParseDetectedExecutable(program_buffer.data(), | 161 flow.DestroyEncodedProgram(flow.ONLY); |
165 program_buffer.length(), &program); | |
166 if (parse_program_status != courgette::C_OK) | |
167 Problem("Can't parse program input (code = %d).", parse_program_status); | |
168 | |
169 std::unique_ptr<courgette::AssemblyProgram> model; | |
170 const courgette::Status parse_model_status = | |
171 courgette::ParseDetectedExecutable(model_buffer.data(), | |
172 model_buffer.length(), &model); | |
173 if (parse_model_status != courgette::C_OK) | |
174 Problem("Can't parse model input (code = %d).", parse_model_status); | |
175 | |
176 const courgette::Status adjust_status = Adjust(*model, program.get()); | |
177 if (adjust_status != courgette::C_OK) | |
178 Problem("Can't adjust program."); | |
179 | |
180 model.reset(); | |
181 | |
182 std::unique_ptr<courgette::EncodedProgram> encoded; | |
183 const courgette::Status encode_status = Encode(*program, &encoded); | |
184 if (encode_status != courgette::C_OK) | |
185 Problem("Can't encode program."); | |
186 | |
187 program.reset(); | |
188 | |
189 courgette::SinkStreamSet sinks; | |
190 const courgette::Status write_status = | |
191 courgette::WriteEncodedProgram(encoded.get(), &sinks); | |
192 if (write_status != courgette::C_OK) | |
193 Problem("Can't serialize encoded program."); | |
194 | |
195 encoded.reset(); | |
196 | |
197 courgette::SinkStream sink; | 162 courgette::SinkStream sink; |
198 if (!sinks.CopyTo(&sink)) | 163 flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); |
199 Problem("Can't combine serialized encoded program streams."); | 164 if (flow.failed()) |
165 Problem(flow.message().c_str()); | |
200 | 166 |
201 WriteSinkToFile(&sink, output_file); | 167 WriteSinkToFile(&sink, output_file); |
chrisha
2017/04/24 18:15:50
Does this still need to happen, even if failed() i
huangs
2017/04/24 20:08:14
Problem() calls exit(1), so on failure this will n
| |
202 } | 168 } |
169 | |
170 void DisassembleAndAdjust(const base::FilePath& old_file, | |
171 const base::FilePath& new_file, | |
172 const base::FilePath& output_file) { | |
173 CourgetteFlow flow; | |
174 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); | |
175 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); | |
176 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); | |
177 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); | |
178 flow.AdjustNewAssemblyProgramToMatchOld(); | |
179 flow.DestroyAssemblyProgram(flow.OLD); | |
180 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); | |
181 flow.DestroyAssemblyProgram(flow.NEW); | |
182 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); | |
183 flow.DestroyEncodedProgram(flow.NEW); | |
184 courgette::SinkStream sink; | |
185 flow.WriteSinkStreamFromSinkStreamSet(flow.NEW, &sink); | |
186 if (flow.failed()) | |
187 Problem(flow.message().c_str()); | |
188 | |
189 WriteSinkToFile(&sink, output_file); | |
190 } | |
203 | 191 |
204 // Diffs two executable files, write a set of files for the diff, one file per | 192 // Diffs two executable files, write a set of files for the diff, one file per |
205 // stream of the EncodedProgram format. Each file is the bsdiff between the | 193 // stream of the EncodedProgram format. Each file is the bsdiff between the |
206 // original file's stream and the new file's stream. This is completely | 194 // original file's stream and the new file's stream. This is completely |
207 // uninteresting to users, but it is handy for seeing how much each which | 195 // uninteresting to users, but it is handy for seeing how much each which |
208 // streams are contributing to the final file size. Adjustment is optional. | 196 // streams are contributing to the final file size. Adjustment is optional. |
209 void DisassembleAdjustDiff(const base::FilePath& model_file, | 197 void DisassembleAdjustDiff(const base::FilePath& old_file, |
210 const base::FilePath& program_file, | 198 const base::FilePath& new_file, |
211 const base::FilePath& output_file_root, | 199 const base::FilePath& output_file_root, |
212 bool adjust) { | 200 bool adjust) { |
213 BufferedFileReader model_buffer(model_file, "old"); | 201 CourgetteFlow flow; |
214 BufferedFileReader program_buffer(program_file, "new"); | 202 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); |
215 | 203 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); |
216 auto parser = adjust ? courgette::ParseDetectedExecutableWithAnnotation | 204 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, adjust); |
217 : courgette::ParseDetectedExecutable; | 205 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, adjust); |
218 | 206 if (adjust) |
219 std::unique_ptr<courgette::AssemblyProgram> model; | 207 flow.AdjustNewAssemblyProgramToMatchOld(); |
220 const courgette::Status parse_model_status = | 208 flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); |
221 parser(model_buffer.data(), model_buffer.length(), &model); | 209 flow.DestroyAssemblyProgram(flow.OLD); |
222 if (parse_model_status != courgette::C_OK) | 210 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); |
223 Problem("Can't parse model input (code = %d).", parse_model_status); | 211 flow.DestroyAssemblyProgram(flow.NEW); |
224 | 212 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD); |
225 std::unique_ptr<courgette::AssemblyProgram> program; | 213 flow.DestroyEncodedProgram(flow.OLD); |
226 const courgette::Status parse_program_status = | 214 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); |
227 parser(program_buffer.data(), program_buffer.length(), &program); | 215 flow.DestroyEncodedProgram(flow.NEW); |
228 if (parse_program_status != courgette::C_OK) | 216 if (flow.failed()) |
229 Problem("Can't parse program input (code = %d).", parse_program_status); | 217 Problem(flow.message().c_str()); |
230 | |
231 if (adjust) { | |
232 const courgette::Status adjust_status = Adjust(*model, program.get()); | |
233 if (adjust_status != courgette::C_OK) | |
234 Problem("Can't adjust program."); | |
235 } | |
236 | |
237 std::unique_ptr<courgette::EncodedProgram> encoded_program; | |
238 const courgette::Status encode_program_status = | |
239 Encode(*program, &encoded_program); | |
240 if (encode_program_status != courgette::C_OK) | |
241 Problem("Can't encode program."); | |
242 | |
243 program.reset(); | |
244 | |
245 std::unique_ptr<courgette::EncodedProgram> encoded_model; | |
246 const courgette::Status encode_model_status = Encode(*model, &encoded_model); | |
247 if (encode_model_status != courgette::C_OK) | |
248 Problem("Can't encode model."); | |
249 | |
250 model.reset(); | |
251 | |
252 courgette::SinkStreamSet program_sinks; | |
253 const courgette::Status write_program_status = | |
254 courgette::WriteEncodedProgram(encoded_program.get(), &program_sinks); | |
255 if (write_program_status != courgette::C_OK) | |
256 Problem("Can't serialize encoded program."); | |
257 | |
258 encoded_program.reset(); | |
259 | |
260 courgette::SinkStreamSet model_sinks; | |
261 const courgette::Status write_model_status = | |
262 courgette::WriteEncodedProgram(encoded_model.get(), &model_sinks); | |
263 if (write_model_status != courgette::C_OK) | |
264 Problem("Can't serialize encoded model."); | |
265 | |
266 encoded_model.reset(); | |
267 | 218 |
268 courgette::SinkStream empty_sink; | 219 courgette::SinkStream empty_sink; |
269 for (int i = 0; ; ++i) { | 220 for (int i = 0; ; ++i) { |
270 courgette::SinkStream* old_stream = model_sinks.stream(i); | 221 courgette::SinkStream* old_stream = flow.data(flow.OLD)->sinks.stream(i); |
271 courgette::SinkStream* new_stream = program_sinks.stream(i); | 222 courgette::SinkStream* new_stream = flow.data(flow.NEW)->sinks.stream(i); |
272 if (old_stream == NULL && new_stream == NULL) | 223 if (old_stream == NULL && new_stream == NULL) |
273 break; | 224 break; |
274 | 225 |
275 courgette::SourceStream old_source; | 226 courgette::SourceStream old_source; |
276 courgette::SourceStream new_source; | 227 courgette::SourceStream new_source; |
277 old_source.Init(old_stream ? *old_stream : empty_sink); | 228 old_source.Init(old_stream ? *old_stream : empty_sink); |
278 new_source.Init(new_stream ? *new_stream : empty_sink); | 229 new_source.Init(new_stream ? *new_stream : empty_sink); |
279 courgette::SinkStream patch_stream; | 230 courgette::SinkStream patch_stream; |
280 bsdiff::BSDiffStatus status = | 231 bsdiff::BSDiffStatus status = |
281 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); | 232 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); |
282 if (status != bsdiff::OK) | 233 if (status != bsdiff::OK) |
283 Problem("-xxx failed."); | 234 Problem("-xxx failed."); |
284 | 235 |
285 std::string append = std::string("-") + base::IntToString(i); | 236 std::string append = std::string("-") + base::IntToString(i); |
286 | 237 |
287 WriteSinkToFile(&patch_stream, | 238 WriteSinkToFile(&patch_stream, |
288 output_file_root.InsertBeforeExtensionASCII(append)); | 239 output_file_root.InsertBeforeExtensionASCII(append)); |
289 } | 240 } |
290 } | 241 } |
291 | 242 |
292 void Assemble(const base::FilePath& input_file, | 243 void Assemble(const base::FilePath& input_file, |
293 const base::FilePath& output_file) { | 244 const base::FilePath& output_file) { |
294 BufferedFileReader buffer(input_file, "input"); | 245 CourgetteFlow flow; |
295 | 246 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
296 courgette::SourceStreamSet sources; | 247 flow.ReadSourceStreamSetFromBuffer(flow.ONLY, input_buffer); |
297 if (!sources.Init(buffer.data(), buffer.length())) | 248 flow.ReadEncodedProgramFromSourceStreamSet(flow.ONLY); |
298 Problem("Bad input file."); | |
299 | |
300 std::unique_ptr<courgette::EncodedProgram> encoded; | |
301 const courgette::Status read_status = | |
302 courgette::ReadEncodedProgram(&sources, &encoded); | |
303 if (read_status != courgette::C_OK) | |
304 Problem("Bad encoded program."); | |
305 | |
306 courgette::SinkStream sink; | 249 courgette::SinkStream sink; |
307 | 250 flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink); |
308 const courgette::Status assemble_status = | 251 if (flow.failed()) |
309 courgette::Assemble(encoded.get(), &sink); | 252 Problem(flow.message().c_str()); |
310 if (assemble_status != courgette::C_OK) | |
311 Problem("Can't assemble."); | |
312 | 253 |
313 WriteSinkToFile(&sink, output_file); | 254 WriteSinkToFile(&sink, output_file); |
314 } | 255 } |
315 | 256 |
316 void GenerateEnsemblePatch(const base::FilePath& old_file, | 257 void GenerateEnsemblePatch(const base::FilePath& old_file, |
317 const base::FilePath& new_file, | 258 const base::FilePath& new_file, |
318 const base::FilePath& patch_file) { | 259 const base::FilePath& patch_file) { |
319 BufferedFileReader old_buffer(old_file, "'old' input"); | 260 BufferedFileReader old_buffer(old_file, "'old' input"); |
320 BufferedFileReader new_buffer(new_file, "'new' input"); | 261 BufferedFileReader new_buffer(new_file, "'new' input"); |
321 | 262 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
423 courgette::SinkStream new_stream; | 364 courgette::SinkStream new_stream; |
424 bsdiff::BSDiffStatus status = | 365 bsdiff::BSDiffStatus status = |
425 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); | 366 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); |
426 | 367 |
427 if (status != bsdiff::OK) | 368 if (status != bsdiff::OK) |
428 Problem("-applybsdiff failed."); | 369 Problem("-applybsdiff failed."); |
429 | 370 |
430 WriteSinkToFile(&new_stream, new_file); | 371 WriteSinkToFile(&new_stream, new_file); |
431 } | 372 } |
432 | 373 |
374 } // namespace | |
375 | |
433 int main(int argc, const char* argv[]) { | 376 int main(int argc, const char* argv[]) { |
434 base::AtExitManager at_exit_manager; | 377 base::AtExitManager at_exit_manager; |
435 base::CommandLine::Init(argc, argv); | 378 base::CommandLine::Init(argc, argv); |
436 const base::CommandLine& command_line = | 379 const base::CommandLine& command_line = |
437 *base::CommandLine::ForCurrentProcess(); | 380 *base::CommandLine::ForCurrentProcess(); |
438 | 381 |
439 logging::LoggingSettings settings; | 382 logging::LoggingSettings settings; |
440 settings.logging_dest = logging::LOG_TO_ALL; | 383 settings.logging_dest = logging::LOG_TO_ALL; |
441 settings.log_file = FILE_PATH_LITERAL("courgette.log"); | 384 settings.log_file = FILE_PATH_LITERAL("courgette.log"); |
442 (void)logging::InitLogging(settings); | 385 (void)logging::InitLogging(settings); |
(...skipping 18 matching lines...) Expand all Loading... | |
461 | 404 |
462 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and | 405 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and |
463 // bugs in cleanup. | 406 // bugs in cleanup. |
464 int repeat_count = 1; | 407 int repeat_count = 1; |
465 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); | 408 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); |
466 if (!repeat_switch.empty()) | 409 if (!repeat_switch.empty()) |
467 if (!base::StringToInt(repeat_switch, &repeat_count)) | 410 if (!base::StringToInt(repeat_switch, &repeat_count)) |
468 repeat_count = 1; | 411 repeat_count = 1; |
469 | 412 |
470 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + | 413 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + |
471 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + | 414 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + |
472 cmd_spread_1_adjusted + cmd_spread_1_unadjusted | 415 cmd_spread_1_adjusted + cmd_spread_1_unadjusted != |
473 != 1) | 416 1) { |
474 UsageProblem( | 417 UsageProblem( |
475 "Must have exactly one of:\n" | 418 "First argument must be one of:\n" |
476 " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" | 419 " -supported, -asm, -dis, -disadj, -gen, -apply, -genbsdiff," |
477 " or -applybsdiff."); | 420 " -applybsdiff, or -gen1[au]."); |
421 } | |
478 | 422 |
479 while (repeat_count-- > 0) { | 423 while (repeat_count-- > 0) { |
480 if (cmd_sup) { | 424 if (cmd_sup) { |
481 if (values.size() != 1) | 425 if (values.size() != 1) |
482 UsageProblem("-supported <executable_file>"); | 426 UsageProblem(kUsageSupported); |
483 return !Supported(values[0]); | 427 return !Supported(values[0]); |
484 } else if (cmd_dis) { | 428 } else if (cmd_dis) { |
485 if (values.size() != 2) | 429 if (values.size() != 2) |
486 UsageProblem("-dis <executable_file> <courgette_file>"); | 430 UsageProblem(kUsageDis); |
487 Disassemble(values[0], values[1]); | 431 Disassemble(values[0], values[1]); |
488 } else if (cmd_asm) { | 432 } else if (cmd_asm) { |
489 if (values.size() != 2) | 433 if (values.size() != 2) |
490 UsageProblem("-asm <courgette_file_input> <executable_file_output>"); | 434 UsageProblem(kUsageAsm); |
491 Assemble(values[0], values[1]); | 435 Assemble(values[0], values[1]); |
492 } else if (cmd_disadj) { | 436 } else if (cmd_disadj) { |
493 if (values.size() != 3) | 437 if (values.size() != 3) |
494 UsageProblem("-disadj <executable_file> <model> <courgette_file>"); | 438 UsageProblem(kUsageDisadj); |
495 DisassembleAndAdjust(values[0], values[1], values[2]); | 439 DisassembleAndAdjust(values[0], values[1], values[2]); |
496 } else if (cmd_make_patch) { | 440 } else if (cmd_make_patch) { |
497 if (values.size() != 3) | 441 if (values.size() != 3) |
498 UsageProblem("-gen <old_file> <new_file> <patch_file>"); | 442 UsageProblem(kUsageGen); |
499 GenerateEnsemblePatch(values[0], values[1], values[2]); | 443 GenerateEnsemblePatch(values[0], values[1], values[2]); |
500 } else if (cmd_apply_patch) { | 444 } else if (cmd_apply_patch) { |
501 if (values.size() != 3) | 445 if (values.size() != 3) |
502 UsageProblem("-apply <old_file> <patch_file> <new_file>"); | 446 UsageProblem(kUsageApply); |
503 ApplyEnsemblePatch(values[0], values[1], values[2]); | 447 ApplyEnsemblePatch(values[0], values[1], values[2]); |
504 } else if (cmd_make_bsdiff_patch) { | 448 } else if (cmd_make_bsdiff_patch) { |
505 if (values.size() != 3) | 449 if (values.size() != 3) |
506 UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); | 450 UsageProblem(kUsageGenbsdiff); |
507 GenerateBSDiffPatch(values[0], values[1], values[2]); | 451 GenerateBSDiffPatch(values[0], values[1], values[2]); |
508 } else if (cmd_apply_bsdiff_patch) { | 452 } else if (cmd_apply_bsdiff_patch) { |
509 if (values.size() != 3) | 453 if (values.size() != 3) |
510 UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); | 454 UsageProblem(kUsageApplybsdiff); |
511 ApplyBSDiffPatch(values[0], values[1], values[2]); | 455 ApplyBSDiffPatch(values[0], values[1], values[2]); |
512 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { | 456 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { |
513 if (values.size() != 3) | 457 if (values.size() != 3) |
514 UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); | 458 UsageProblem(kUsageGen1); |
515 DisassembleAdjustDiff(values[0], values[1], values[2], | 459 DisassembleAdjustDiff(values[0], values[1], values[2], |
516 cmd_spread_1_adjusted); | 460 cmd_spread_1_adjusted); |
517 } else { | 461 } else { |
518 UsageProblem("No operation specified"); | 462 UsageProblem("No operation specified"); |
519 } | 463 } |
520 } | 464 } |
521 | 465 |
522 return 0; | 466 return 0; |
523 } | 467 } |
OLD | NEW |