123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- // Copyright (c) 2011 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_
- #define COURGETTE_PATCH_GENERATOR_X86_32_H_
- #include "base/logging.h"
- #include "courgette/courgette_flow.h"
- #include "courgette/ensemble.h"
- #include "courgette/patcher_x86_32.h"
- namespace courgette {
- // PatchGeneratorX86_32 is the universal patch generator for all executables,
- // performing transformation and adjustment. The executable type is determined
- // by the program detector.
- class PatchGeneratorX86_32 : public TransformationPatchGenerator {
- public:
- PatchGeneratorX86_32(Element* old_element,
- Element* new_element,
- PatcherX86_32* patcher,
- ExecutableType kind)
- : TransformationPatchGenerator(old_element, new_element, patcher),
- kind_(kind) {
- }
- PatchGeneratorX86_32(const PatchGeneratorX86_32&) = delete;
- PatchGeneratorX86_32& operator=(const PatchGeneratorX86_32&) = delete;
- virtual ExecutableType Kind() { return kind_; }
- Status WriteInitialParameters(SinkStream* parameter_stream) {
- if (!parameter_stream->WriteSizeVarint32(
- old_element_->offset_in_ensemble()) ||
- !parameter_stream->WriteSizeVarint32(old_element_->region().length())) {
- return C_STREAM_ERROR;
- }
- return C_OK;
- // TODO(sra): Initialize |patcher_| with these parameters.
- }
- Status PredictTransformParameters(SinkStreamSet* prediction) {
- return TransformationPatchGenerator::PredictTransformParameters(prediction);
- }
- Status CorrectedTransformParameters(SinkStreamSet* parameters) {
- // No code needed to write an 'empty' parameter set.
- return C_OK;
- }
- // The format of a transformed_element is a serialized EncodedProgram. Steps:
- // - Form Disassembler for the old and new Elements.
- // - Extract AssemblyPrograms from old and new Disassemblers.
- // - Adjust the new AssemblyProgram to make it as much like the old one as
- // possible.
- // - Serialize old and new Disassembler to EncodedProgram, using the old
- // AssemblyProgram and the adjusted new AssemblyProgram.
- // The steps are performed in an order to reduce peak memory.
- Status Transform(SourceStreamSet* corrected_parameters,
- SinkStreamSet* old_transformed_element,
- SinkStreamSet* new_transformed_element) {
- // Don't expect any corrected parameters.
- if (!corrected_parameters->Empty())
- return C_GENERAL_ERROR;
- // Flow graph and process sequence (DA = Disassembler, AP = AssemblyProgram,
- // EP = EncodedProgram, Adj = Adjusted):
- // [1 Old DA] --> [2 Old AP] [6 New AP] <-- [5 New DA]
- // | | | | |
- // v | | v (move) v
- // [3 Old EP] <-----+ +->[7 Adj New AP] --> [8 New EP]
- // (4 Write) (9 Write)
- CourgetteFlow flow;
- RegionBuffer old_buffer(old_element_->region());
- RegionBuffer new_buffer(new_element_->region());
- flow.ReadDisassemblerFromBuffer(flow.OLD, old_buffer); // 1
- flow.CreateAssemblyProgramFromDisassembler(flow.OLD, true); // 2
- flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.OLD); // 3
- flow.DestroyDisassembler(flow.OLD);
- flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD,
- old_transformed_element); // 4
- flow.DestroyEncodedProgram(flow.OLD);
- flow.ReadDisassemblerFromBuffer(flow.NEW, new_buffer); // 5
- flow.CreateAssemblyProgramFromDisassembler(flow.NEW, true); // 6
- flow.AdjustNewAssemblyProgramToMatchOld(); // 7
- flow.DestroyAssemblyProgram(flow.OLD);
- flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.NEW); // 8
- flow.DestroyAssemblyProgram(flow.NEW);
- flow.DestroyDisassembler(flow.NEW);
- flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW,
- new_transformed_element); // 9
- if (flow.failed()) {
- LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => "
- << new_element_->Name() << ")";
- }
- return flow.status();
- }
- Status Reform(SourceStreamSet* transformed_element,
- SinkStream* reformed_element) {
- return TransformationPatchGenerator::Reform(transformed_element,
- reformed_element);
- }
- private:
- virtual ~PatchGeneratorX86_32() { }
- ExecutableType kind_;
- };
- } // namespace courgette
- #endif // COURGETTE_PATCH_GENERATOR_X86_32_H_
|