Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(974)

Side by Side Diff: third_party/courgette/courgette_tool.cc

Issue 115062: Move Courgette... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/courgette/courgette_minimal_tool.cc ('k') | third_party/courgette/crc.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2009 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.
4
5 #include <vector>
6 #include <string>
7
8 #include "base/at_exit.h"
9 #include "base/basictypes.h"
10 #include "base/command_line.h"
11 #include "base/file_util.h"
12 #include "base/logging.h"
13 #include "base/string_util.h"
14
15 #include "third_party/courgette/bsdiff.h"
16 #include "third_party/courgette/courgette.h"
17 #include "third_party/courgette/streams.h"
18
19
20 void PrintHelp() {
21 fprintf(stderr,
22 "Usage:\n"
23 " courgette_tool -dis <executable_file> <binary_assembly_file>\n"
24 " courgette_tool -asm <binary_assembly_file> <executable_file>\n"
25 " courgette_tool -disadj "
26 "<executable_file> <reference> <binary_assembly_file>\n"
27 " courgette_tool -gen <v1> <v2> <patch>\n"
28 " courgette_tool -apply <v1> <patch> <v2>\n"
29 "\n");
30 }
31
32 void UsageProblem(const char* message) {
33 fprintf(stderr, "%s", message);
34 fprintf(stderr, "\n");
35 PrintHelp();
36 exit(1);
37 }
38
39 void Problem(const char* format, ...) {
40 va_list args;
41 va_start(args, format);
42 vfprintf(stderr, format, args);
43 fprintf(stderr, "\n");
44 va_end(args);
45 exit(1);
46 }
47
48 std::string ReadOrFail(const std::wstring& file_name, const char* kind) {
49 FilePath file_path(file_name);
50 std::string buffer;
51 if (!file_util::ReadFileToString(file_path, &buffer))
52 Problem("Can't read %s file.", kind);
53 return buffer;
54 }
55
56 void WriteSinkToFile(const courgette::SinkStream *sink,
57 const std::wstring& output_file) {
58 FilePath output_path(output_file);
59 int count =
60 file_util::WriteFile(output_path,
61 reinterpret_cast<const char*>(sink->Buffer()),
62 sink->Length());
63 if (count == -1)
64 Problem("Cant write output.");
65 if (count != sink->Length())
66 Problem("Incomplete write.");
67 }
68
69 void Disassemble(const std::wstring& input_file,
70 const std::wstring& output_file) {
71 std::string buffer = ReadOrFail(input_file, "input");
72
73 courgette::AssemblyProgram* program = NULL;
74 const courgette::Status parse_status =
75 courgette::ParseWin32X86PE(buffer.c_str(), buffer.length(), &program);
76
77 if (parse_status != courgette::C_OK)
78 Problem("Can't parse input.");
79
80 courgette::EncodedProgram* encoded = NULL;
81 const courgette::Status encode_status = Encode(program, &encoded);
82
83 courgette::DeleteAssemblyProgram(program);
84
85 if (encode_status != courgette::C_OK)
86 Problem("Can't encode program.");
87
88 courgette::SinkStreamSet sinks;
89
90 const courgette::Status write_status =
91 courgette::WriteEncodedProgram(encoded, &sinks);
92 if (write_status != courgette::C_OK)
93 Problem("Can't serialize encoded program.");
94
95 courgette::DeleteEncodedProgram(encoded);
96
97 courgette::SinkStream sink;
98 sinks.CopyTo(&sink);
99
100 WriteSinkToFile(&sink, output_file);
101 }
102
103 void DisassembleAndAdjust(const std::wstring& program_file,
104 const std::wstring& model_file,
105 const std::wstring& output_file) {
106 std::string program_buffer = ReadOrFail(program_file, "program");
107 std::string model_buffer = ReadOrFail(model_file, "reference");
108
109 courgette::AssemblyProgram* program = NULL;
110 const courgette::Status parse_program_status =
111 courgette::ParseWin32X86PE(program_buffer.c_str(),
112 program_buffer.length(),
113 &program);
114 if (parse_program_status != courgette::C_OK)
115 Problem("Can't parse program input.");
116
117 courgette::AssemblyProgram* model = NULL;
118 const courgette::Status parse_model_status =
119 courgette::ParseWin32X86PE(model_buffer.c_str(),
120 model_buffer.length(),
121 &model);
122 if (parse_model_status != courgette::C_OK)
123 Problem("Can't parse model input.");
124
125 const courgette::Status adjust_status = Adjust(*model, program);
126 if (adjust_status != courgette::C_OK)
127 Problem("Can't adjust program.");
128
129 courgette::EncodedProgram* encoded = NULL;
130 const courgette::Status encode_status = Encode(program, &encoded);
131
132 courgette::DeleteAssemblyProgram(program);
133
134 if (encode_status != courgette::C_OK)
135 Problem("Can't encode program.");
136
137 courgette::SinkStreamSet sinks;
138
139 const courgette::Status write_status =
140 courgette::WriteEncodedProgram(encoded, &sinks);
141 if (write_status != courgette::C_OK)
142 Problem("Can't serialize encoded program.");
143
144 courgette::DeleteEncodedProgram(encoded);
145
146 courgette::SinkStream sink;
147 sinks.CopyTo(&sink);
148
149 WriteSinkToFile(&sink, output_file);
150 }
151
152 // Diffs two executable files, write a set of files for the diff, one file per
153 // stream of the EncodedProgram format. Each file is the bsdiff between the
154 // original file's stream and the new file's stream. This is completely
155 // uninteresting to users, but it is handy for seeing how much each which
156 // streams are contributing to the final file size. Adjustment is optional.
157 void DisassembleAdjustDiff(const std::wstring& model_file,
158 const std::wstring& program_file,
159 const std::wstring& output_file_root,
160 bool adjust) {
161 std::string model_buffer = ReadOrFail(model_file, "'old'");
162 std::string program_buffer = ReadOrFail(program_file, "'new'");
163
164 courgette::AssemblyProgram* model = NULL;
165 const courgette::Status parse_model_status =
166 courgette::ParseWin32X86PE(model_buffer.c_str(),
167 model_buffer.length(),
168 &model);
169 if (parse_model_status != courgette::C_OK)
170 Problem("Can't parse model input.");
171
172 courgette::AssemblyProgram* program = NULL;
173 const courgette::Status parse_program_status =
174 courgette::ParseWin32X86PE(program_buffer.c_str(),
175 program_buffer.length(),
176 &program);
177 if (parse_program_status != courgette::C_OK)
178 Problem("Can't parse program input.");
179
180 if (adjust) {
181 const courgette::Status adjust_status = Adjust(*model, program);
182 if (adjust_status != courgette::C_OK)
183 Problem("Can't adjust program.");
184 }
185
186 courgette::EncodedProgram* encoded_program = NULL;
187 const courgette::Status encode_program_status =
188 Encode(program, &encoded_program);
189 courgette::DeleteAssemblyProgram(program);
190 if (encode_program_status != courgette::C_OK)
191 Problem("Can't encode program.");
192
193 courgette::EncodedProgram* encoded_model = NULL;
194 const courgette::Status encode_model_status = Encode(model, &encoded_model);
195 courgette::DeleteAssemblyProgram(model);
196 if (encode_model_status != courgette::C_OK)
197 Problem("Can't encode model.");
198
199 courgette::SinkStreamSet program_sinks;
200 const courgette::Status write_program_status =
201 courgette::WriteEncodedProgram(encoded_program, &program_sinks);
202 if (write_program_status != courgette::C_OK)
203 Problem("Can't serialize encoded program.");
204 courgette::DeleteEncodedProgram(encoded_program);
205
206 courgette::SinkStreamSet model_sinks;
207 const courgette::Status write_model_status =
208 courgette::WriteEncodedProgram(encoded_model, &model_sinks);
209 if (write_model_status != courgette::C_OK)
210 Problem("Can't serialize encoded model.");
211 courgette::DeleteEncodedProgram(encoded_program);
212
213 for (int i = 0; ; ++i) {
214 courgette::SinkStream* old_stream = model_sinks.stream(i);
215 courgette::SinkStream* new_stream = program_sinks.stream(i);
216 if (old_stream == NULL && new_stream == NULL)
217 break;
218
219 courgette::SourceStream old_source;
220 courgette::SourceStream new_source;
221 old_source.Init(*old_stream);
222 new_source.Init(*new_stream);
223 courgette::SinkStream patch_stream;
224 courgette::BSDiffStatus status =
225 courgette::CreateBinaryPatch(&old_source, &new_source, &patch_stream);
226 if (status != courgette::OK) Problem("-xxx failed.");
227
228 WriteSinkToFile(&patch_stream,
229 output_file_root + L"-" + IntToWString(i));
230 }
231 }
232
233 void Assemble(const std::wstring& input_file,
234 const std::wstring& output_file) {
235 std::string buffer = ReadOrFail(input_file, "input");
236
237 courgette::SourceStreamSet sources;
238 if (!sources.Init(buffer.c_str(), buffer.length()))
239 Problem("Bad input file.");
240
241 courgette::EncodedProgram* encoded = NULL;
242 const courgette::Status read_status = ReadEncodedProgram(&sources, &encoded);
243 if (read_status != courgette::C_OK)
244 Problem("Bad encoded program.");
245
246 courgette::SinkStream sink;
247
248 const courgette::Status assemble_status = courgette::Assemble(encoded, &sink);
249 if (assemble_status != courgette::C_OK)
250 Problem("Can't assemble.");
251
252 WriteSinkToFile(&sink, output_file);
253 }
254
255 void GenerateEnsemblePatch(const std::wstring& old_file,
256 const std::wstring& new_file,
257 const std::wstring& patch_file) {
258 std::string old_buffer = ReadOrFail(old_file, "'old' input");
259 std::string new_buffer = ReadOrFail(new_file, "'new' input");
260
261 courgette::SourceStream old_stream;
262 courgette::SourceStream new_stream;
263 old_stream.Init(old_buffer);
264 new_stream.Init(new_buffer);
265
266 courgette::SinkStream patch_stream;
267 courgette::Status status =
268 courgette::GenerateEnsemblePatch(&old_stream, &new_stream, &patch_stream);
269
270 if (status != courgette::C_OK) Problem("-gen failed.");
271
272 WriteSinkToFile(&patch_stream, patch_file);
273 }
274
275 void ApplyEnsemblePatch(const std::wstring& old_file,
276 const std::wstring& patch_file,
277 const std::wstring& new_file) {
278 std::string old_buffer = ReadOrFail(old_file, "'old' input");
279 std::string patch_buffer = ReadOrFail(patch_file, "'patch' input");
280
281 courgette::SourceStream old_stream;
282 courgette::SourceStream patch_stream;
283 old_stream.Init(old_buffer);
284 patch_stream.Init(patch_buffer);
285 courgette::SinkStream new_stream;
286 courgette::Status status =
287 courgette::ApplyEnsemblePatch(&old_stream, &patch_stream, &new_stream);
288
289 if (status != courgette::C_OK) Problem("-apply failed.");
290
291 WriteSinkToFile(&new_stream, new_file);
292 }
293
294 void GenerateBSDiffPatch(const std::wstring& old_file,
295 const std::wstring& new_file,
296 const std::wstring& patch_file) {
297 std::string old_buffer = ReadOrFail(old_file, "'old' input");
298 std::string new_buffer = ReadOrFail(new_file, "'new' input");
299
300 courgette::SourceStream old_stream;
301 courgette::SourceStream new_stream;
302 old_stream.Init(old_buffer);
303 new_stream.Init(new_buffer);
304
305 courgette::SinkStream patch_stream;
306 courgette::BSDiffStatus status =
307 courgette::CreateBinaryPatch(&old_stream, &new_stream, &patch_stream);
308
309 if (status != courgette::OK) Problem("-genbsdiff failed.");
310
311 WriteSinkToFile(&patch_stream, patch_file);
312 }
313
314 void ApplyBSDiffPatch(const std::wstring& old_file,
315 const std::wstring& patch_file,
316 const std::wstring& new_file) {
317 std::string old_buffer = ReadOrFail(old_file, "'old' input");
318 std::string patch_buffer = ReadOrFail(patch_file, "'patch' input");
319
320 courgette::SourceStream old_stream;
321 courgette::SourceStream patch_stream;
322 old_stream.Init(old_buffer);
323 patch_stream.Init(patch_buffer);
324
325 courgette::SinkStream new_stream;
326 courgette::BSDiffStatus status =
327 courgette::ApplyBinaryPatch(&old_stream, &patch_stream, &new_stream);
328
329 if (status != courgette::OK) Problem("-applybsdiff failed.");
330
331 WriteSinkToFile(&new_stream, new_file);
332 }
333
334 int main(int argc, const char* argv[]) {
335 base::AtExitManager at_exit_manager;
336 CommandLine::Init(argc, argv);
337 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
338
339 bool cmd_dis = command_line.HasSwitch(L"dis");
340 bool cmd_asm = command_line.HasSwitch(L"asm");
341 bool cmd_disadj = command_line.HasSwitch(L"disadj");
342 bool cmd_make_patch = command_line.HasSwitch(L"gen");
343 bool cmd_apply_patch = command_line.HasSwitch(L"apply");
344 bool cmd_make_bsdiff_patch = command_line.HasSwitch(L"genbsdiff");
345 bool cmd_apply_bsdiff_patch = command_line.HasSwitch(L"applybsdiff");
346 bool cmd_spread_1_adjusted = command_line.HasSwitch(L"gen1a");
347 bool cmd_spread_1_unadjusted = command_line.HasSwitch(L"gen1u");
348
349 std::vector<std::wstring> values = command_line.GetLooseValues();
350
351 // '-repeat=N' is for debugging. Running many iterations can reveal leaks and
352 // bugs in cleanup.
353 int repeat_count = 1;
354 std::wstring repeat_switch = command_line.GetSwitchValue(L"repeat");
355 if (!repeat_switch.empty())
356 if (!StringToInt(repeat_switch, &repeat_count))
357 repeat_count = 1;
358
359 if (cmd_dis + cmd_asm + cmd_disadj + cmd_make_patch + cmd_apply_patch +
360 cmd_make_bsdiff_patch + cmd_apply_bsdiff_patch +
361 cmd_spread_1_adjusted + cmd_spread_1_unadjusted
362 != 1)
363 UsageProblem(
364 "Must have exactly one of:\n"
365 " -asm, -dis, -disadj, -gen or -apply, -genbsdiff or -applybsdiff.");
366
367 while (repeat_count-- > 0) {
368 if (cmd_dis) {
369 if (values.size() != 2)
370 UsageProblem("-dis <executable_file> <courgette_file>");
371 Disassemble(values[0], values[1]);
372 } else if (cmd_asm) {
373 if (values.size() != 2)
374 UsageProblem("-asm <courgette_file_input> <executable_file_output>");
375 Assemble(values[0], values[1]);
376 } else if (cmd_disadj) {
377 if (values.size() != 3)
378 UsageProblem("-disadj <executable_file> <model> <courgette_file>");
379 DisassembleAndAdjust(values[0], values[1], values[2]);
380 } else if (cmd_make_patch) {
381 if (values.size() != 3)
382 UsageProblem("-gen <old_file> <new_file> <patch_file>");
383 GenerateEnsemblePatch(values[0], values[1], values[2]);
384 } else if (cmd_apply_patch) {
385 if (values.size() != 3)
386 UsageProblem("-apply <old_file> <patch_file> <new_file>");
387 ApplyEnsemblePatch(values[0], values[1], values[2]);
388 } else if (cmd_make_bsdiff_patch) {
389 if (values.size() != 3)
390 UsageProblem("-genbsdiff <old_file> <new_file> <patch_file>");
391 GenerateBSDiffPatch(values[0], values[1], values[2]);
392 } else if (cmd_apply_bsdiff_patch) {
393 if (values.size() != 3)
394 UsageProblem("-applybsdiff <old_file> <patch_file> <new_file>");
395 ApplyBSDiffPatch(values[0], values[1], values[2]);
396 } else if (cmd_spread_1_adjusted || cmd_spread_1_unadjusted) {
397 if (values.size() != 3)
398 UsageProblem("-gen1[au] <old_file> <new_file> <patch_files_root>");
399 DisassembleAdjustDiff(values[0], values[1], values[2],
400 cmd_spread_1_adjusted);
401 } else {
402 UsageProblem("No operation specified");
403 }
404 }
405 }
OLDNEW
« no previous file with comments | « third_party/courgette/courgette_minimal_tool.cc ('k') | third_party/courgette/crc.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698