1// Copyright (c) 2012 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 for Windows X86 executables.
6// The same patcher can be used for Windows X64 executables.
7
8#ifndef COURGETTE_WIN32_X86_PATCHER_H_
9#define COURGETTE_WIN32_X86_PATCHER_H_
10
11#include "courgette/ensemble.h"
12
13namespace courgette {
14
15// Courgette32X86Patcher is a TransformationPatcher for Windows 32-bit
16// and 64-bit executables.  We can use the same patcher for both.
17//
18class PatcherX86_32 : public TransformationPatcher {
19 public:
20  explicit PatcherX86_32(const Region& region)
21      : ensemble_region_(region),
22        base_offset_(0),
23        base_length_(0) {
24  }
25
26  Status Init(SourceStream* parameter_stream) {
27    if (!parameter_stream->ReadVarint32(&base_offset_))
28      return C_BAD_TRANSFORM;
29    if (!parameter_stream->ReadVarint32(&base_length_))
30      return C_BAD_TRANSFORM;
31
32    if (base_offset_ > ensemble_region_.length())
33      return C_BAD_TRANSFORM;
34    if (base_length_ > ensemble_region_.length() - base_offset_)
35      return C_BAD_TRANSFORM;
36
37    return C_OK;
38  }
39
40  Status PredictTransformParameters(SinkStreamSet* predicted_parameters) {
41    // No code needed to write an 'empty' predicted parameter set.
42    return C_OK;
43  }
44
45  Status Transform(SourceStreamSet* corrected_parameters,
46                   SinkStreamSet* transformed_element) {
47    Status status;
48    if (!corrected_parameters->Empty())
49      return C_GENERAL_ERROR;   // Don't expect any corrected parameters.
50
51    AssemblyProgram* program = NULL;
52    status = ParseDetectedExecutable(ensemble_region_.start() + base_offset_,
53                                     base_length_,
54                                     &program);
55    if (status != C_OK)
56      return status;
57
58    // Trim labels below a certain threshold
59    Status trim_status = TrimLabels(program);
60    if (trim_status != C_OK) {
61      DeleteAssemblyProgram(program);
62      return trim_status;
63    }
64
65    EncodedProgram* encoded = NULL;
66    status = Encode(program, &encoded);
67    DeleteAssemblyProgram(program);
68    if (status != C_OK)
69      return status;
70
71    status = WriteEncodedProgram(encoded, transformed_element);
72    DeleteEncodedProgram(encoded);
73
74    return status;
75  }
76
77  Status Reform(SourceStreamSet* transformed_element,
78                SinkStream* reformed_element) {
79    Status status;
80    EncodedProgram* encoded_program = NULL;
81    status = ReadEncodedProgram(transformed_element, &encoded_program);
82    if (status != C_OK)
83      return status;
84
85    status = Assemble(encoded_program, reformed_element);
86    DeleteEncodedProgram(encoded_program);
87    if (status != C_OK)
88      return status;
89
90    return C_OK;
91  }
92
93 private:
94  Region ensemble_region_;
95
96  uint32 base_offset_;
97  uint32 base_length_;
98
99  DISALLOW_COPY_AND_ASSIGN(PatcherX86_32);
100};
101
102}  // namespace
103#endif  // COURGETTE_WIN32_X86_PATCHER_H_
104