OLD | NEW |
| (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 // The main idea in Courgette is to do patching *under a tranformation*. The | |
6 // input is transformed into a new representation, patching occurs in the new | |
7 // repesentation, and then the tranform is reversed to get the patched data. | |
8 // | |
9 // The idea is applied to pieces (or 'Elements') of the whole (or 'Ensemble'). | |
10 // Each of the elements has to go through the same set of steps in lock-step, | |
11 // but there may be many different kinds of elements, which have different | |
12 // transformation. | |
13 // | |
14 // This file declares all the main types involved in creating and applying a | |
15 // patch with this structure. | |
16 | |
17 #ifndef COURGETTE_ENSEMBLE_H_ | |
18 #define COURGETTE_ENSEMBLE_H_ | |
19 | |
20 #include <vector> | |
21 #include <string> | |
22 | |
23 #include "base/basictypes.h" | |
24 | |
25 #include "third_party/courgette/courgette.h" | |
26 #include "third_party/courgette/region.h" | |
27 #include "third_party/courgette/streams.h" | |
28 | |
29 namespace courgette { | |
30 | |
31 // Forward declarations: | |
32 class Ensemble; | |
33 class PEInfo; | |
34 | |
35 // An Element is a region of an Ensemble with an identifyable kind. | |
36 // | |
37 class Element { | |
38 public: | |
39 enum Kind { WIN32_X86_WITH_CODE, WIN32_NOCODE }; | |
40 | |
41 virtual ~Element() {} | |
42 | |
43 Kind kind() const { return kind_; } | |
44 const Region& region() const { return region_; } | |
45 | |
46 // The name is used only for debugging and logging. | |
47 virtual std::string Name() const; | |
48 | |
49 // Returns the byte position of this Element relative to the start of | |
50 // containing Ensemble. | |
51 size_t offset_in_ensemble() const; | |
52 | |
53 // Some subclasses of Element might have a PEInfo. | |
54 virtual PEInfo* GetPEInfo() const { return NULL; } | |
55 | |
56 protected: | |
57 Element(Kind kind, Ensemble* ensemble, const Region& region); | |
58 | |
59 private: | |
60 Kind kind_; | |
61 Ensemble* ensemble_; | |
62 Region region_; | |
63 | |
64 DISALLOW_COPY_AND_ASSIGN(Element); | |
65 }; | |
66 | |
67 | |
68 class Ensemble { | |
69 public: | |
70 Ensemble(const Region& region, const char* name) | |
71 : region_(region), name_(name) {} | |
72 ~Ensemble(); | |
73 | |
74 const Region& region() const { return region_; } | |
75 const std::string& name() const { return name_; } | |
76 | |
77 // Scans the region to find Elements within the region(). | |
78 Status FindEmbeddedElements(); | |
79 | |
80 // Returns the elements found by 'FindEmbeddedElements'. | |
81 const std::vector<Element*>& elements() const { return elements_; } | |
82 | |
83 | |
84 private: | |
85 Region region_; // The memory, owned by caller, containing the | |
86 // Ensemble's data. | |
87 std::string name_; // A debugging/logging name for the Ensemble. | |
88 | |
89 std::vector<Element*> elements_; // Embedded elements discovered. | |
90 std::vector<Element*> owned_elements_; // For deallocation. | |
91 | |
92 DISALLOW_COPY_AND_ASSIGN(Ensemble); | |
93 }; | |
94 | |
95 inline size_t Element::offset_in_ensemble() const { | |
96 return region().start() - ensemble_->region().start(); | |
97 } | |
98 | |
99 // The 'CourgettePatchFile' is class is a 'namespace' for the constants that | |
100 // appear in a Courgette patch file. | |
101 struct CourgettePatchFile { | |
102 // | |
103 // The Courgette patch format interleaves the data for N embedded Elements. | |
104 // | |
105 // Format of a patch file: | |
106 // header: | |
107 // magic | |
108 // version | |
109 // source-checksum | |
110 // target-checksum | |
111 // multiple-streams: | |
112 // stream 0: | |
113 // number-of-transformed-elements (N) - varint32 | |
114 // transformation-1-method-id | |
115 // transformation-2-method-id | |
116 // ... | |
117 // transformation-1-initial-parameters | |
118 // transformation-2-initial-parameters | |
119 // ... | |
120 // stream 1: | |
121 // correction: | |
122 // transformation-1-parameters | |
123 // transformation-2-parameters | |
124 // ... | |
125 // stream 2: | |
126 // correction: | |
127 // transformed-element-1 | |
128 // transformed-element-2 | |
129 // ... | |
130 // stream 3: | |
131 // correction: | |
132 // base-file | |
133 // element-1 | |
134 // element-2 | |
135 // ... | |
136 | |
137 static const uint32 kMagic = 'C' | ('o' << 8) | ('u' << 16); | |
138 | |
139 static const uint32 kVersion = 20090320; | |
140 | |
141 // Transformation method IDs. | |
142 enum TransformationMethodId { | |
143 T_COURGETTE_WIN32_X86 = 1, // Windows 32 bit 'Portable Executable' x86. | |
144 }; | |
145 }; | |
146 | |
147 // For any transform you would implement both a TransformationPatcher and a | |
148 // TransformationPatchGenerator. | |
149 // | |
150 // TransformationPatcher is the interface which abstracts out the actual | |
151 // transformation used on an Element. The patching itself happens outside the | |
152 // actions of a TransformationPatcher. There are four steps. | |
153 // | |
154 // The first step is an Init step. The parameters to the Init step identify the | |
155 // element, for example, range of locations within the original ensemble that | |
156 // correspond to the element. | |
157 // | |
158 // PredictTransformParameters, explained below. | |
159 // | |
160 // The two final steps are 'Transform' - to transform the element into a new | |
161 // representation, and to 'Reform' - to transform from the new representation | |
162 // back to the original form. | |
163 // | |
164 // The Transform step takes some parameters. This allows the transform to be | |
165 // customized to the particular element, or to receive some assistance in the | |
166 // analysis required to perform the transform. The transform parameters might | |
167 // be extensive but mostly predicable, so preceeding Transform is a | |
168 // PredictTransformParameters step. | |
169 // | |
170 class TransformationPatcher { | |
171 public: | |
172 virtual ~TransformationPatcher() {} | |
173 | |
174 // First step: provides parameters for the patching. This would at a minimum | |
175 // identify the element within the ensemble being patched. | |
176 virtual Status Init(SourceStream* parameter_stream) = 0; | |
177 | |
178 // Second step: predicts transform parameters. | |
179 virtual Status PredictTransformParameters( | |
180 SinkStreamSet* predicted_parameters) = 0; | |
181 | |
182 // Third step: transforms element from original representation into alternate | |
183 // representation. | |
184 virtual Status Transform(SourceStreamSet* corrected_parameters, | |
185 SinkStreamSet* transformed_element) = 0; | |
186 | |
187 // Final step: transforms element back from alternate representation into | |
188 // original representation. | |
189 virtual Status Reform(SourceStreamSet* transformed_element, | |
190 SinkStream* reformed_element) = 0; | |
191 }; | |
192 | |
193 // TransformationPatchGenerator is the interface which abstracts out the actual | |
194 // transformation used (and adjustment used) when differentially compressing one | |
195 // Element from the |new_ensemble| against a corresponding element in the | |
196 // |old_ensemble|. | |
197 // | |
198 // This is not a pure interface. There is a small amount of inheritance | |
199 // implementation for the fields and actions common to all | |
200 // TransformationPatchGenerators. | |
201 // | |
202 // When TransformationPatchGenerator is subclassed, there will be a | |
203 // corresponding subclass of TransformationPatcher. | |
204 // | |
205 class TransformationPatchGenerator { | |
206 public: | |
207 TransformationPatchGenerator(Element* old_element, | |
208 Element* new_element, | |
209 TransformationPatcher* patcher); | |
210 | |
211 virtual ~TransformationPatchGenerator(); | |
212 | |
213 // Returns the TransformationMethodId that identies this transformation. | |
214 virtual CourgettePatchFile::TransformationMethodId Kind() = 0; | |
215 | |
216 // Writes the parameters that will be passed to TransformationPatcher::Init. | |
217 virtual Status WriteInitialParameters(SinkStream* parameter_stream) = 0; | |
218 | |
219 // Predicts the transform parameters for the |old_element|. This must match | |
220 // exactly the output that will be produced by the PredictTransformParameters | |
221 // method of the corresponding subclass of TransformationPatcher. This method | |
222 // is not pure. The default implementation delegates to the patcher to | |
223 // guarantee matching output. | |
224 virtual Status PredictTransformParameters(SinkStreamSet* prediction); | |
225 | |
226 // Writes the desired parameters for the transform of the old element from the | |
227 // file representation to the alternate representation. | |
228 virtual Status CorrectedTransformParameters(SinkStreamSet* parameters) = 0; | |
229 | |
230 // Writes both |old_element| and |new_element| in the new representation. | |
231 // |old_corrected_parameters| will match the |corrected_parameters| passed to | |
232 // the Transform method of the corresponding sublcass of | |
233 // TransformationPatcher. | |
234 // | |
235 // The output written to |old_transformed_element| must match exactly the | |
236 // output written by the Transform method of the corresponding subclass of | |
237 // TransformationPatcher. | |
238 virtual Status Transform(SourceStreamSet* old_corrected_parameters, | |
239 SinkStreamSet* old_transformed_element, | |
240 SinkStreamSet* new_transformed_element) = 0; | |
241 | |
242 // Transforms the new transformed_element back from the alternate | |
243 // representation into the original file format. This must match exactly the | |
244 // output that will be produced by the corresponding subclass of | |
245 // TransformationPatcher::Reform. This method is not pure. The default | |
246 // implementation delegates to the patcher. | |
247 virtual Status Reform(SourceStreamSet* transformed_element, | |
248 SinkStream* reformed_element); | |
249 | |
250 protected: | |
251 Element* old_element_; | |
252 Element* new_element_; | |
253 TransformationPatcher* patcher_; | |
254 }; | |
255 | |
256 } // namespace | |
257 #endif // COURGETTE_ENSEMBLE_H_ | |
OLD | NEW |