Chromium Code Reviews| 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 |