1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_
6 #define COURGETTE_PATCH_GENERATOR_X86_32_H_
8 #include "base/logging.h"
9 #include "courgette/courgette_flow.h"
10 #include "courgette/ensemble.h"
11 #include "courgette/patcher_x86_32.h"
15 // PatchGeneratorX86_32 is the universal patch generator for all executables,
16 // performing transformation and adjustment. The executable type is determined
17 // by the program detector.
18 class PatchGeneratorX86_32 : public TransformationPatchGenerator {
20 PatchGeneratorX86_32(Element* old_element,
22 PatcherX86_32* patcher,
24 : TransformationPatchGenerator(old_element, new_element, patcher),
28 PatchGeneratorX86_32(const PatchGeneratorX86_32&) = delete;
29 PatchGeneratorX86_32& operator=(const PatchGeneratorX86_32&) = delete;
31 virtual ExecutableType Kind() { return kind_; }
33 Status WriteInitialParameters(SinkStream* parameter_stream) {
34 if (!parameter_stream->WriteSizeVarint32(
35 old_element_->offset_in_ensemble()) ||
36 !parameter_stream->WriteSizeVarint32(old_element_->region().length())) {
37 return C_STREAM_ERROR;
40 // TODO(sra): Initialize |patcher_| with these parameters.
43 Status PredictTransformParameters(SinkStreamSet* prediction) {
44 return TransformationPatchGenerator::PredictTransformParameters(prediction);
47 Status CorrectedTransformParameters(SinkStreamSet* parameters) {
48 // No code needed to write an 'empty' parameter set.
52 // The format of a transformed_element is a serialized EncodedProgram. Steps:
53 // - Form Disassembler for the old and new Elements.
54 // - Extract AssemblyPrograms from old and new Disassemblers.
55 // - Adjust the new AssemblyProgram to make it as much like the old one as
57 // - Serialize old and new Disassembler to EncodedProgram, using the old
58 // AssemblyProgram and the adjusted new AssemblyProgram.
59 // The steps are performed in an order to reduce peak memory.
60 Status Transform(SourceStreamSet* corrected_parameters,
61 SinkStreamSet* old_transformed_element,
62 SinkStreamSet* new_transformed_element) {
63 // Don't expect any corrected parameters.
64 if (!corrected_parameters->Empty())
65 return C_GENERAL_ERROR;
67 // Flow graph and process sequence (DA = Disassembler, AP = AssemblyProgram,
68 // EP = EncodedProgram, Adj = Adjusted):
69 // [1 Old DA] --> [2 Old AP] [6 New AP] <-- [5 New DA]
72 // [3 Old EP] <-----+ +->[7 Adj New AP] --> [8 New EP]
73 // (4 Write) (9 Write)
75 RegionBuffer old_buffer(old_element_->region());
76 RegionBuffer new_buffer(new_element_->region());
77 flow.ReadDisassemblerFromBuffer(flow.OLD, old_buffer); // 1
78 flow.CreateAssemblyProgramFromDisassembler(flow.OLD, true); // 2
79 flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.OLD); // 3
80 flow.DestroyDisassembler(flow.OLD);
81 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD,
82 old_transformed_element); // 4
83 flow.DestroyEncodedProgram(flow.OLD);
84 flow.ReadDisassemblerFromBuffer(flow.NEW, new_buffer); // 5
85 flow.CreateAssemblyProgramFromDisassembler(flow.NEW, true); // 6
86 flow.AdjustNewAssemblyProgramToMatchOld(); // 7
87 flow.DestroyAssemblyProgram(flow.OLD);
88 flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.NEW); // 8
89 flow.DestroyAssemblyProgram(flow.NEW);
90 flow.DestroyDisassembler(flow.NEW);
91 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW,
92 new_transformed_element); // 9
94 LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => "
95 << new_element_->Name() << ")";
100 Status Reform(SourceStreamSet* transformed_element,
101 SinkStream* reformed_element) {
102 return TransformationPatchGenerator::Reform(transformed_element,
107 virtual ~PatchGeneratorX86_32() { }
109 ExecutableType kind_;
112 } // namespace courgette
114 #endif // COURGETTE_PATCH_GENERATOR_X86_32_H_