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 #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_ | 5 #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_ |
6 #define COURGETTE_PATCH_GENERATOR_X86_32_H_ | 6 #define COURGETTE_PATCH_GENERATOR_X86_32_H_ |
7 | 7 |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "courgette/assembly_program.h" | |
13 #include "courgette/courgette_flow.h" | 12 #include "courgette/courgette_flow.h" |
14 #include "courgette/ensemble.h" | 13 #include "courgette/ensemble.h" |
15 #include "courgette/patcher_x86_32.h" | 14 #include "courgette/patcher_x86_32.h" |
16 #include "courgette/program_detector.h" | |
17 | 15 |
18 namespace courgette { | 16 namespace courgette { |
19 | 17 |
20 // PatchGeneratorX86_32 is the universal patch generator for all executables, | 18 // PatchGeneratorX86_32 is the universal patch generator for all executables, |
21 // performing transformation and adjustment. The executable type is determined | 19 // performing transformation and adjustment. The executable type is determined |
22 // by the program detector. | 20 // by the program detector. |
23 class PatchGeneratorX86_32 : public TransformationPatchGenerator { | 21 class PatchGeneratorX86_32 : public TransformationPatchGenerator { |
24 public: | 22 public: |
25 PatchGeneratorX86_32(Element* old_element, | 23 PatchGeneratorX86_32(Element* old_element, |
26 Element* new_element, | 24 Element* new_element, |
(...skipping 17 matching lines...) Expand all Loading... |
44 | 42 |
45 Status PredictTransformParameters(SinkStreamSet* prediction) { | 43 Status PredictTransformParameters(SinkStreamSet* prediction) { |
46 return TransformationPatchGenerator::PredictTransformParameters(prediction); | 44 return TransformationPatchGenerator::PredictTransformParameters(prediction); |
47 } | 45 } |
48 | 46 |
49 Status CorrectedTransformParameters(SinkStreamSet* parameters) { | 47 Status CorrectedTransformParameters(SinkStreamSet* parameters) { |
50 // No code needed to write an 'empty' parameter set. | 48 // No code needed to write an 'empty' parameter set. |
51 return C_OK; | 49 return C_OK; |
52 } | 50 } |
53 | 51 |
54 // The format of a transformed_element is a serialized EncodedProgram. We | 52 // The format of a transformed_element is a serialized EncodedProgram. Steps: |
55 // first disassemble the original old and new Elements into AssemblyPrograms. | 53 // - Form Disassembler for the old and new Elements. |
56 // Then we adjust the new AssemblyProgram to make it as much like the old one | 54 // - Extract AssemblyPrograms from old and new Disassemblers. |
57 // as possible, before converting the AssemblyPrograms to EncodedPrograms and | 55 // - Adjust the new AssemblyProgram to make it as much like the old one as |
58 // serializing them. | 56 // possible. |
| 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. |
59 Status Transform(SourceStreamSet* corrected_parameters, | 60 Status Transform(SourceStreamSet* corrected_parameters, |
60 SinkStreamSet* old_transformed_element, | 61 SinkStreamSet* old_transformed_element, |
61 SinkStreamSet* new_transformed_element) { | 62 SinkStreamSet* new_transformed_element) { |
62 // Don't expect any corrected parameters. | 63 // Don't expect any corrected parameters. |
63 if (!corrected_parameters->Empty()) | 64 if (!corrected_parameters->Empty()) |
64 return C_GENERAL_ERROR; | 65 return C_GENERAL_ERROR; |
65 | 66 |
| 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] |
| 70 // | | | | | |
| 71 // v | | v (move) v |
| 72 // [3 Old EP] <-----+ +->[7 Adj New AP] --> [8 New EP] |
| 73 // (4 Write) (9 Write) |
66 CourgetteFlow flow; | 74 CourgetteFlow flow; |
67 RegionBuffer old_buffer(old_element_->region()); | 75 RegionBuffer old_buffer(old_element_->region()); |
68 RegionBuffer new_buffer(new_element_->region()); | 76 RegionBuffer new_buffer(new_element_->region()); |
69 flow.ReadAssemblyProgramFromBuffer(flow.OLD, old_buffer, true); | 77 flow.ReadDisassemblerFromBuffer(flow.OLD, old_buffer); // 1 |
70 flow.CreateEncodedProgramFromAssemblyProgram(flow.OLD); | 78 flow.CreateAssemblyProgramFromDisassembler(flow.OLD, true); // 2 |
| 79 flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.OLD); // 3 |
| 80 flow.DestroyDisassembler(flow.OLD); |
71 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD, | 81 flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD, |
72 old_transformed_element); | 82 old_transformed_element); // 4 |
73 flow.DestroyEncodedProgram(flow.OLD); | 83 flow.DestroyEncodedProgram(flow.OLD); |
74 flow.ReadAssemblyProgramFromBuffer(flow.NEW, new_buffer, true); | 84 flow.ReadDisassemblerFromBuffer(flow.NEW, new_buffer); // 5 |
75 flow.AdjustNewAssemblyProgramToMatchOld(); | 85 flow.CreateAssemblyProgramFromDisassembler(flow.NEW, true); // 6 |
| 86 flow.AdjustNewAssemblyProgramToMatchOld(); // 7 |
76 flow.DestroyAssemblyProgram(flow.OLD); | 87 flow.DestroyAssemblyProgram(flow.OLD); |
77 flow.CreateEncodedProgramFromAssemblyProgram(flow.NEW); | 88 flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.NEW); // 8 |
78 flow.DestroyAssemblyProgram(flow.NEW); | 89 flow.DestroyAssemblyProgram(flow.NEW); |
| 90 flow.DestroyDisassembler(flow.NEW); |
79 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW, | 91 flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW, |
80 new_transformed_element); | 92 new_transformed_element); // 9 |
81 if (flow.failed()) { | 93 if (flow.failed()) { |
82 LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => " | 94 LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => " |
83 << new_element_->Name() << ")"; | 95 << new_element_->Name() << ")"; |
84 } | 96 } |
85 return flow.status(); | 97 return flow.status(); |
86 } | 98 } |
87 | 99 |
88 Status Reform(SourceStreamSet* transformed_element, | 100 Status Reform(SourceStreamSet* transformed_element, |
89 SinkStream* reformed_element) { | 101 SinkStream* reformed_element) { |
90 return TransformationPatchGenerator::Reform(transformed_element, | 102 return TransformationPatchGenerator::Reform(transformed_element, |
91 reformed_element); | 103 reformed_element); |
92 } | 104 } |
93 | 105 |
94 private: | 106 private: |
95 virtual ~PatchGeneratorX86_32() { } | 107 virtual ~PatchGeneratorX86_32() { } |
96 | 108 |
97 ExecutableType kind_; | 109 ExecutableType kind_; |
98 | 110 |
99 DISALLOW_COPY_AND_ASSIGN(PatchGeneratorX86_32); | 111 DISALLOW_COPY_AND_ASSIGN(PatchGeneratorX86_32); |
100 }; | 112 }; |
101 | 113 |
102 } // namespace courgette | 114 } // namespace courgette |
103 | 115 |
104 #endif // COURGETTE_PATCH_GENERATOR_X86_32_H_ | 116 #endif // COURGETTE_PATCH_GENERATOR_X86_32_H_ |
OLD | NEW |