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