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 ~BufferedFileReader() override {} |
64 size_t length() const { return buffer_.length(); } | 87 |
| 88 // courgette::BasicBuffer: |
| 89 const uint8_t* data() const override { return buffer_.data(); } |
| 90 size_t length() const override { return buffer_.length(); } |
65 | 91 |
66 private: | 92 private: |
67 base::MemoryMappedFile buffer_; | 93 base::MemoryMappedFile buffer_; |
| 94 |
| 95 DISALLOW_COPY_AND_ASSIGN(BufferedFileReader); |
68 }; | 96 }; |
69 | 97 |
| 98 /******** Various helpers ********/ |
| 99 |
70 void WriteSinkToFile(const courgette::SinkStream *sink, | 100 void WriteSinkToFile(const courgette::SinkStream *sink, |
71 const base::FilePath& output_file) { | 101 const base::FilePath& output_file) { |
72 int count = | 102 int count = |
73 base::WriteFile(output_file, | 103 base::WriteFile(output_file, |
74 reinterpret_cast<const char*>(sink->Buffer()), | 104 reinterpret_cast<const char*>(sink->Buffer()), |
75 static_cast<int>(sink->Length())); | 105 static_cast<int>(sink->Length())); |
76 if (count == -1) | 106 if (count == -1) |
77 Problem("Can't write output."); | 107 Problem("Can't write output."); |
78 if (static_cast<size_t>(count) != sink->Length()) | 108 if (static_cast<size_t>(count) != sink->Length()) |
79 Problem("Incomplete write."); | 109 Problem("Incomplete write."); |
80 } | 110 } |
81 | 111 |
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) { | 112 bool Supported(const base::FilePath& input_file) { |
115 bool result = false; | 113 bool result = false; |
116 | 114 |
117 BufferedFileReader buffer(input_file, "input"); | 115 BufferedFileReader buffer(input_file, "input"); |
118 | 116 |
119 courgette::ExecutableType type; | 117 courgette::ExecutableType type; |
120 size_t detected_length; | 118 size_t detected_length; |
121 | 119 |
122 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); | 120 DetectExecutableType(buffer.data(), buffer.length(), &type, &detected_length); |
123 | 121 |
(...skipping 22 matching lines...) Expand all Loading... |
146 case courgette::EXE_WIN_32_X64: | 144 case courgette::EXE_WIN_32_X64: |
147 format = "Windows 64 PE"; | 145 format = "Windows 64 PE"; |
148 result = true; | 146 result = true; |
149 break; | 147 break; |
150 } | 148 } |
151 | 149 |
152 printf("%s Executable\n", format.c_str()); | 150 printf("%s Executable\n", format.c_str()); |
153 return result; | 151 return result; |
154 } | 152 } |
155 | 153 |
156 void DisassembleAndAdjust(const base::FilePath& program_file, | 154 void Disassemble(const base::FilePath& input_file, |
157 const base::FilePath& model_file, | 155 const base::FilePath& output_file) { |
158 const base::FilePath& output_file) { | 156 CourgetteFlow flow; |
159 BufferedFileReader program_buffer(program_file, "program"); | 157 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
160 BufferedFileReader model_buffer(model_file, "model"); | 158 flow.ReadAssemblyProgramFromBuffer(flow.ONLY, input_buffer, false); |
161 | 159 flow.CreateEncodedProgramFromAssemblyProgram(flow.ONLY); |
162 std::unique_ptr<courgette::AssemblyProgram> program; | 160 flow.DestroyAssemblyProgram(flow.ONLY); |
163 const courgette::Status parse_program_status = | 161 flow.WriteSinkStreamSetFromEncodedProgram(flow.ONLY); |
164 courgette::ParseDetectedExecutable(program_buffer.data(), | 162 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; | 163 courgette::SinkStream sink; |
198 if (!sinks.CopyTo(&sink)) | 164 flow.WriteSinkStreamFromSinkStreamSet(flow.ONLY, &sink); |
199 Problem("Can't combine serialized encoded program streams."); | 165 if (flow.failed()) |
| 166 Problem(flow.message().c_str()); |
200 | 167 |
201 WriteSinkToFile(&sink, output_file); | 168 WriteSinkToFile(&sink, output_file); |
202 } | 169 } |
| 170 |
| 171 void DisassembleAndAdjust(const base::FilePath& old_file, |
| 172 const base::FilePath& new_file, |
| 173 const base::FilePath& output_file) { |
| 174 CourgetteFlow flow; |
| 175 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); |
| 176 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); |
| 177 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); |
| 178 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); |
| 179 flow.AdjustNewAssemblyProgramToMatchOld(); |
| 180 flow.DestroyAssemblyProgram(flow.OLD); |
| 181 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); |
| 182 flow.DestroyAssemblyProgram(flow.NEW); |
| 183 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); |
| 184 flow.DestroyEncodedProgram(flow.NEW); |
| 185 courgette::SinkStream sink; |
| 186 flow.WriteSinkStreamFromSinkStreamSet(flow.NEW, &sink); |
| 187 if (flow.failed()) |
| 188 Problem(flow.message().c_str()); |
| 189 |
| 190 WriteSinkToFile(&sink, output_file); |
| 191 } |
203 | 192 |
204 // Diffs two executable files, write a set of files for the diff, one file per | 193 // 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 | 194 // 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 | 195 // 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 | 196 // 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. | 197 // streams are contributing to the final file size. Adjustment is optional. |
209 void DisassembleAdjustDiff(const base::FilePath& model_file, | 198 void DisassembleAdjustDiff(const base::FilePath& old_file, |
210 const base::FilePath& program_file, | 199 const base::FilePath& new_file, |
211 const base::FilePath& output_file_root, | 200 const base::FilePath& output_file_root, |
212 bool adjust) { | 201 bool adjust) { |
213 BufferedFileReader model_buffer(model_file, "old"); | 202 CourgetteFlow flow; |
214 BufferedFileReader program_buffer(program_file, "new"); | 203 BufferedFileReader old_buffer(old_file, flow.name(flow.OLD)); |
215 | 204 BufferedFileReader new_buffer(new_file, flow.name(flow.NEW)); |
216 auto parser = adjust ? courgette::ParseDetectedExecutableWithAnnotation | 205 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, adjust); |
217 : courgette::ParseDetectedExecutable; | 206 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, adjust); |
218 | 207 if (adjust) |
219 std::unique_ptr<courgette::AssemblyProgram> model; | 208 flow.AdjustNewAssemblyProgramToMatchOld(); |
220 const courgette::Status parse_model_status = | 209 flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); |
221 parser(model_buffer.data(), model_buffer.length(), &model); | 210 flow.DestroyAssemblyProgram(flow.OLD); |
222 if (parse_model_status != courgette::C_OK) | 211 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); |
223 Problem("Can't parse model input (code = %d).", parse_model_status); | 212 flow.DestroyAssemblyProgram(flow.NEW); |
224 | 213 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD); |
225 std::unique_ptr<courgette::AssemblyProgram> program; | 214 flow.DestroyEncodedProgram(flow.OLD); |
226 const courgette::Status parse_program_status = | 215 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW); |
227 parser(program_buffer.data(), program_buffer.length(), &program); | 216 flow.DestroyEncodedProgram(flow.NEW); |
228 if (parse_program_status != courgette::C_OK) | 217 if (flow.failed()) |
229 Problem("Can't parse program input (code = %d).", parse_program_status); | 218 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 | 219 |
268 courgette::SinkStream empty_sink; | 220 courgette::SinkStream empty_sink; |
269 for (int i = 0; ; ++i) { | 221 for (int i = 0; ; ++i) { |
270 courgette::SinkStream* old_stream = model_sinks.stream(i); | 222 courgette::SinkStream* old_stream = flow.data(flow.OLD)->sinks.stream(i); |
271 courgette::SinkStream* new_stream = program_sinks.stream(i); | 223 courgette::SinkStream* new_stream = flow.data(flow.NEW)->sinks.stream(i); |
272 if (old_stream == NULL && new_stream == NULL) | 224 if (old_stream == NULL && new_stream == NULL) |
273 break; | 225 break; |
274 | 226 |
275 courgette::SourceStream old_source; | 227 courgette::SourceStream old_source; |
276 courgette::SourceStream new_source; | 228 courgette::SourceStream new_source; |
277 old_source.Init(old_stream ? *old_stream : empty_sink); | 229 old_source.Init(old_stream ? *old_stream : empty_sink); |
278 new_source.Init(new_stream ? *new_stream : empty_sink); | 230 new_source.Init(new_stream ? *new_stream : empty_sink); |
279 courgette::SinkStream patch_stream; | 231 courgette::SinkStream patch_stream; |
280 bsdiff::BSDiffStatus status = | 232 bsdiff::BSDiffStatus status = |
281 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); | 233 bsdiff::CreateBinaryPatch(&old_source, &new_source, &patch_stream); |
282 if (status != bsdiff::OK) | 234 if (status != bsdiff::OK) |
283 Problem("-xxx failed."); | 235 Problem("-xxx failed."); |
284 | 236 |
285 std::string append = std::string("-") + base::IntToString(i); | 237 std::string append = std::string("-") + base::IntToString(i); |
286 | 238 |
287 WriteSinkToFile(&patch_stream, | 239 WriteSinkToFile(&patch_stream, |
288 output_file_root.InsertBeforeExtensionASCII(append)); | 240 output_file_root.InsertBeforeExtensionASCII(append)); |
289 } | 241 } |
290 } | 242 } |
291 | 243 |
292 void Assemble(const base::FilePath& input_file, | 244 void Assemble(const base::FilePath& input_file, |
293 const base::FilePath& output_file) { | 245 const base::FilePath& output_file) { |
294 BufferedFileReader buffer(input_file, "input"); | 246 CourgetteFlow flow; |
295 | 247 BufferedFileReader input_buffer(input_file, flow.name(flow.ONLY)); |
296 courgette::SourceStreamSet sources; | 248 flow.ReadSourceStreamSetFromBuffer(flow.ONLY, input_buffer); |
297 if (!sources.Init(buffer.data(), buffer.length())) | 249 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; | 250 courgette::SinkStream sink; |
307 | 251 flow.WriteExecutableFromEncodedProgram(flow.ONLY, &sink); |
308 const courgette::Status assemble_status = | 252 if (flow.failed()) |
309 courgette::Assemble(encoded.get(), &sink); | 253 Problem(flow.message().c_str()); |
310 if (assemble_status != courgette::C_OK) | |
311 Problem("Can't assemble."); | |
312 | 254 |
313 WriteSinkToFile(&sink, output_file); | 255 WriteSinkToFile(&sink, output_file); |
314 } | 256 } |
315 | 257 |
316 void GenerateEnsemblePatch(const base::FilePath& old_file, | 258 void GenerateEnsemblePatch(const base::FilePath& old_file, |
317 const base::FilePath& new_file, | 259 const base::FilePath& new_file, |
318 const base::FilePath& patch_file) { | 260 const base::FilePath& patch_file) { |
319 BufferedFileReader old_buffer(old_file, "'old' input"); | 261 BufferedFileReader old_buffer(old_file, "'old' input"); |
320 BufferedFileReader new_buffer(new_file, "'new' input"); | 262 BufferedFileReader new_buffer(new_file, "'new' input"); |
321 | 263 |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
423 courgette::SinkStream new_stream; | 365 courgette::SinkStream new_stream; |
424 bsdiff::BSDiffStatus status = | 366 bsdiff::BSDiffStatus status = |
425 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); | 367 bsdiff::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream); |
426 | 368 |
427 if (status != bsdiff::OK) | 369 if (status != bsdiff::OK) |
428 Problem("-applybsdiff failed."); | 370 Problem("-applybsdiff failed."); |
429 | 371 |
430 WriteSinkToFile(&new_stream, new_file); | 372 WriteSinkToFile(&new_stream, new_file); |
431 } | 373 } |
432 | 374 |
| 375 } // namespace |
| 376 |
433 int main(int argc, const char* argv[]) { | 377 int main(int argc, const char* argv[]) { |
434 base::AtExitManager at_exit_manager; | 378 base::AtExitManager at_exit_manager; |
435 base::CommandLine::Init(argc, argv); | 379 base::CommandLine::Init(argc, argv); |
436 const base::CommandLine& command_line = | 380 const base::CommandLine& command_line = |
437 *base::CommandLine::ForCurrentProcess(); | 381 *base::CommandLine::ForCurrentProcess(); |
438 | 382 |
439 logging::LoggingSettings settings; | 383 logging::LoggingSettings settings; |
440 settings.logging_dest = logging::LOG_TO_ALL; | 384 settings.logging_dest = logging::LOG_TO_ALL; |
441 settings.log_file = FILE_PATH_LITERAL("courgette.log"); | 385 settings.log_file = FILE_PATH_LITERAL("courgette.log"); |
442 (void)logging::InitLogging(settings); | 386 (void)logging::InitLogging(settings); |
(...skipping 18 matching lines...) Expand all Loading... |
461 | 405 |
462 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and | 406 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and |
463 // bugs in cleanup. | 407 // bugs in cleanup. |
464 int repeat_count = 1; | 408 int repeat_count = 1; |
465 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); | 409 std::string repeat_switch = command_line.GetSwitchValueASCII("repeat"); |
466 if (!repeat_switch.empty()) | 410 if (!repeat_switch.empty()) |
467 if (!base::StringToInt(repeat_switch, &repeat_count)) | 411 if (!base::StringToInt(repeat_switch, &repeat_count)) |
468 repeat_count = 1; | 412 repeat_count = 1; |
469 | 413 |
470 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + | 414 if (cmd_sup + cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + |
471 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + | 415 cmd_apply_patch + cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch + |
472 cmd_spread_1_adjusted + cmd_spread_1_unadjusted | 416 cmd_spread_1_adjusted + cmd_spread_1_unadjusted != |
473 != 1) | 417 1) { |
474 UsageProblem( | 418 UsageProblem( |
475 "Must have exactly one of:\n" | 419 "First argument must be one of:\n" |
476 " -supported -asm, -dis, -disadj, -gen or -apply, -genbsdiff" | 420 " -supported, -asm, -dis, -disadj, -gen, -apply, -genbsdiff," |
477 " or -applybsdiff."); | 421 " -applybsdiff, or -gen1[au]."); |
| 422 } |
478 | 423 |
479 while (repeat_count-- > 0) { | 424 while (repeat_count-- > 0) { |
480 if (cmd_sup) { | 425 if (cmd_sup) { |
481 if (values.size() != 1) | 426 if (values.size() != 1) |
482 UsageProblem("-supported <executable_file>"); | 427 UsageProblem(kUsageSupported); |
483 return !Supported(values[0]); | 428 return !Supported(values[0]); |
484 } else if (cmd_dis) { | 429 } else if (cmd_dis) { |
485 if (values.size() != 2) | 430 if (values.size() != 2) |
486 UsageProblem("-dis <executable_file> <courgette_file>"); | 431 UsageProblem(kUsageDis); |
487 Disassemble(values[0], values[1]); | 432 Disassemble(values[0], values[1]); |
488 } else if (cmd_asm) { | 433 } else if (cmd_asm) { |
489 if (values.size() != 2) | 434 if (values.size() != 2) |
490 UsageProblem("-asm <courgette_file_input> <executable_file_output>"); | 435 UsageProblem(kUsageAsm); |
491 Assemble(values[0], values[1]); | 436 Assemble(values[0], values[1]); |
492 } else if (cmd_disadj) { | 437 } else if (cmd_disadj) { |
493 if (values.size() != 3) | 438 if (values.size() != 3) |
494 UsageProblem("-disadj <executable_file> <model> <courgette_file>"); | 439 UsageProblem(kUsageDisadj); |
495 DisassembleAndAdjust(values[0], values[1], values[2]); | 440 DisassembleAndAdjust(values[0], values[1], values[2]); |
496 } else if (cmd_make_patch) { | 441 } else if (cmd_make_patch) { |
497 if (values.size() != 3) | 442 if (values.size() != 3) |
498 UsageProblem("-gen <old_file> <new_file> <patch_file>"); | 443 UsageProblem(kUsageGen); |
499 GenerateEnsemblePatch(values[0], values[1], values[2]); | 444 GenerateEnsemblePatch(values[0], values[1], values[2]); |
500 } else if (cmd_apply_patch) { | 445 } else if (cmd_apply_patch) { |
501 if (values.size() != 3) | 446 if (values.size() != 3) |
502 UsageProblem("-apply <old_file> <patch_file> <new_file>"); | 447 UsageProblem(kUsageApply); |
503 ApplyEnsemblePatch(values[0], values[1], values[2]); | 448 ApplyEnsemblePatch(values[0], values[1], values[2]); |
504 } else if (cmd_make_bsdiff_patch) { | 449 } else if (cmd_make_bsdiff_patch) { |
505 if (values.size() != 3) | 450 if (values.size() != 3) |
506 UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>"); | 451 UsageProblem(kUsageGenbsdiff); |
507 GenerateBSDiffPatch(values[0], values[1], values[2]); | 452 GenerateBSDiffPatch(values[0], values[1], values[2]); |
508 } else if (cmd_apply_bsdiff_patch) { | 453 } else if (cmd_apply_bsdiff_patch) { |
509 if (values.size() != 3) | 454 if (values.size() != 3) |
510 UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>"); | 455 UsageProblem(kUsageApplybsdiff); |
511 ApplyBSDiffPatch(values[0], values[1], values[2]); | 456 ApplyBSDiffPatch(values[0], values[1], values[2]); |
512 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { | 457 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) { |
513 if (values.size() != 3) | 458 if (values.size() != 3) |
514 UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>"); | 459 UsageProblem(kUsageGen1); |
515 DisassembleAdjustDiff(values[0], values[1], values[2], | 460 DisassembleAdjustDiff(values[0], values[1], values[2], |
516 cmd_spread_1_adjusted); | 461 cmd_spread_1_adjusted); |
517 } else { | 462 } else { |
518 UsageProblem("No operation specified"); | 463 UsageProblem("No operation specified"); |
519 } | 464 } |
520 } | 465 } |
521 | 466 |
522 return 0; | 467 return 0; |
523 } | 468 } |
OLD | NEW |