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 3 // found in the LICENSE file. 4 5 // This is the transformation and adjustment for Windows X86 executables. 6 7 #ifndef COURGETTE_WIN32_X86_GENERATOR_H_ 8 #define COURGETTE_WIN32_X86_GENERATOR_H_ 9 10 #include "base/logging.h" 11 #include "base/memory/scoped_ptr.h" 12 13 #include "courgette/assembly_program.h" 14 #include "courgette/ensemble.h" 15 16 namespace courgette { 17 18 class PatchGeneratorX86_32 : public TransformationPatchGenerator { 19 public: 20 PatchGeneratorX86_32(Element* old_element, 21 Element* new_element, 22 PatcherX86_32* patcher, 23 ExecutableType kind) 24 : TransformationPatchGenerator(old_element, new_element, patcher), 25 kind_(kind) { 26 } 27 28 virtual ExecutableType Kind() { return kind_; } 29 30 Status WriteInitialParameters(SinkStream* parameter_stream) { 31 if (!parameter_stream->WriteSizeVarint32( 32 old_element_->offset_in_ensemble()) || 33 !parameter_stream->WriteSizeVarint32(old_element_->region().length())) { 34 return C_STREAM_ERROR; 35 } 36 return C_OK; 37 // TODO(sra): Initialize |patcher_| with these parameters. 38 } 39 40 Status PredictTransformParameters(SinkStreamSet* prediction) { 41 return TransformationPatchGenerator::PredictTransformParameters(prediction); 42 } 43 44 Status CorrectedTransformParameters(SinkStreamSet* parameters) { 45 // No code needed to write an 'empty' parameter set. 46 return C_OK; 47 } 48 49 // The format of a transformed_element is a serialized EncodedProgram. We 50 // first disassemble the original old and new Elements into AssemblyPrograms. 51 // Then we adjust the new AssemblyProgram to make it as much like the old one 52 // as possible, before converting the AssemblyPrograms to EncodedPrograms and 53 // serializing them. 54 Status Transform(SourceStreamSet* corrected_parameters, 55 SinkStreamSet* old_transformed_element, 56 SinkStreamSet* new_transformed_element) { 57 // Don't expect any corrected parameters. 58 if (!corrected_parameters->Empty()) 59 return C_GENERAL_ERROR; 60 61 // Generate old version of program using |corrected_parameters|. 62 // TODO(sra): refactor to use same code from patcher_. 63 AssemblyProgram* old_program = NULL; 64 Status old_parse_status = 65 ParseDetectedExecutable(old_element_->region().start(), 66 old_element_->region().length(), 67 &old_program); 68 if (old_parse_status != C_OK) { 69 LOG(ERROR) << "Cannot parse as Win32X86PE " << old_element_->Name(); 70 return old_parse_status; 71 } 72 73 AssemblyProgram* new_program = NULL; 74 Status new_parse_status = 75 ParseDetectedExecutable(new_element_->region().start(), 76 new_element_->region().length(), 77 &new_program); 78 if (new_parse_status != C_OK) { 79 DeleteAssemblyProgram(old_program); 80 LOG(ERROR) << "Cannot parse as Win32X86PE " << new_element_->Name(); 81 return new_parse_status; 82 } 83 84 // Trim labels below a certain threshold 85 Status trim_old_status = TrimLabels(old_program); 86 if (trim_old_status != C_OK) { 87 DeleteAssemblyProgram(old_program); 88 return trim_old_status; 89 } 90 91 Status trim_new_status = TrimLabels(new_program); 92 if (trim_new_status != C_OK) { 93 DeleteAssemblyProgram(new_program); 94 return trim_new_status; 95 } 96 97 EncodedProgram* old_encoded = NULL; 98 Status old_encode_status = Encode(old_program, &old_encoded); 99 if (old_encode_status != C_OK) { 100 DeleteAssemblyProgram(old_program); 101 return old_encode_status; 102 } 103 104 Status old_write_status = 105 WriteEncodedProgram(old_encoded, old_transformed_element); 106 DeleteEncodedProgram(old_encoded); 107 if (old_write_status != C_OK) { 108 DeleteAssemblyProgram(old_program); 109 return old_write_status; 110 } 111 112 Status adjust_status = Adjust(*old_program, new_program); 113 DeleteAssemblyProgram(old_program); 114 if (adjust_status != C_OK) { 115 DeleteAssemblyProgram(new_program); 116 return adjust_status; 117 } 118 119 EncodedProgram* new_encoded = NULL; 120 Status new_encode_status = Encode(new_program, &new_encoded); 121 DeleteAssemblyProgram(new_program); 122 if (new_encode_status != C_OK) 123 return new_encode_status; 124 125 Status new_write_status = 126 WriteEncodedProgram(new_encoded, new_transformed_element); 127 DeleteEncodedProgram(new_encoded); 128 if (new_write_status != C_OK) 129 return new_write_status; 130 131 return C_OK; 132 } 133 134 Status Reform(SourceStreamSet* transformed_element, 135 SinkStream* reformed_element) { 136 return TransformationPatchGenerator::Reform(transformed_element, 137 reformed_element); 138 } 139 140 private: 141 virtual ~PatchGeneratorX86_32() { } 142 143 ExecutableType kind_; 144 145 DISALLOW_COPY_AND_ASSIGN(PatchGeneratorX86_32); 146 }; 147 148 } // namespace courgette 149 #endif // COURGETTE_WIN32_X86_GENERATOR_H_ 150