patch_generator_x86_32.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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. #ifndef COURGETTE_PATCH_GENERATOR_X86_32_H_
  5. #define COURGETTE_PATCH_GENERATOR_X86_32_H_
  6. #include "base/logging.h"
  7. #include "courgette/courgette_flow.h"
  8. #include "courgette/ensemble.h"
  9. #include "courgette/patcher_x86_32.h"
  10. namespace courgette {
  11. // PatchGeneratorX86_32 is the universal patch generator for all executables,
  12. // performing transformation and adjustment. The executable type is determined
  13. // by the program detector.
  14. class PatchGeneratorX86_32 : public TransformationPatchGenerator {
  15. public:
  16. PatchGeneratorX86_32(Element* old_element,
  17. Element* new_element,
  18. PatcherX86_32* patcher,
  19. ExecutableType kind)
  20. : TransformationPatchGenerator(old_element, new_element, patcher),
  21. kind_(kind) {
  22. }
  23. PatchGeneratorX86_32(const PatchGeneratorX86_32&) = delete;
  24. PatchGeneratorX86_32& operator=(const PatchGeneratorX86_32&) = delete;
  25. virtual ExecutableType Kind() { return kind_; }
  26. Status WriteInitialParameters(SinkStream* parameter_stream) {
  27. if (!parameter_stream->WriteSizeVarint32(
  28. old_element_->offset_in_ensemble()) ||
  29. !parameter_stream->WriteSizeVarint32(old_element_->region().length())) {
  30. return C_STREAM_ERROR;
  31. }
  32. return C_OK;
  33. // TODO(sra): Initialize |patcher_| with these parameters.
  34. }
  35. Status PredictTransformParameters(SinkStreamSet* prediction) {
  36. return TransformationPatchGenerator::PredictTransformParameters(prediction);
  37. }
  38. Status CorrectedTransformParameters(SinkStreamSet* parameters) {
  39. // No code needed to write an 'empty' parameter set.
  40. return C_OK;
  41. }
  42. // The format of a transformed_element is a serialized EncodedProgram. Steps:
  43. // - Form Disassembler for the old and new Elements.
  44. // - Extract AssemblyPrograms from old and new Disassemblers.
  45. // - Adjust the new AssemblyProgram to make it as much like the old one as
  46. // possible.
  47. // - Serialize old and new Disassembler to EncodedProgram, using the old
  48. // AssemblyProgram and the adjusted new AssemblyProgram.
  49. // The steps are performed in an order to reduce peak memory.
  50. Status Transform(SourceStreamSet* corrected_parameters,
  51. SinkStreamSet* old_transformed_element,
  52. SinkStreamSet* new_transformed_element) {
  53. // Don't expect any corrected parameters.
  54. if (!corrected_parameters->Empty())
  55. return C_GENERAL_ERROR;
  56. // Flow graph and process sequence (DA = Disassembler, AP = AssemblyProgram,
  57. // EP = EncodedProgram, Adj = Adjusted):
  58. // [1 Old DA] --> [2 Old AP] [6 New AP] <-- [5 New DA]
  59. // | | | | |
  60. // v | | v (move) v
  61. // [3 Old EP] <-----+ +->[7 Adj New AP] --> [8 New EP]
  62. // (4 Write) (9 Write)
  63. CourgetteFlow flow;
  64. RegionBuffer old_buffer(old_element_->region());
  65. RegionBuffer new_buffer(new_element_->region());
  66. flow.ReadDisassemblerFromBuffer(flow.OLD, old_buffer); // 1
  67. flow.CreateAssemblyProgramFromDisassembler(flow.OLD, true); // 2
  68. flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.OLD); // 3
  69. flow.DestroyDisassembler(flow.OLD);
  70. flow.WriteSinkStreamSetFromEncodedProgram(flow.OLD,
  71. old_transformed_element); // 4
  72. flow.DestroyEncodedProgram(flow.OLD);
  73. flow.ReadDisassemblerFromBuffer(flow.NEW, new_buffer); // 5
  74. flow.CreateAssemblyProgramFromDisassembler(flow.NEW, true); // 6
  75. flow.AdjustNewAssemblyProgramToMatchOld(); // 7
  76. flow.DestroyAssemblyProgram(flow.OLD);
  77. flow.CreateEncodedProgramFromDisassemblerAndAssemblyProgram(flow.NEW); // 8
  78. flow.DestroyAssemblyProgram(flow.NEW);
  79. flow.DestroyDisassembler(flow.NEW);
  80. flow.WriteSinkStreamSetFromEncodedProgram(flow.NEW,
  81. new_transformed_element); // 9
  82. if (flow.failed()) {
  83. LOG(ERROR) << flow.message() << " (" << old_element_->Name() << " => "
  84. << new_element_->Name() << ")";
  85. }
  86. return flow.status();
  87. }
  88. Status Reform(SourceStreamSet* transformed_element,
  89. SinkStream* reformed_element) {
  90. return TransformationPatchGenerator::Reform(transformed_element,
  91. reformed_element);
  92. }
  93. private:
  94. virtual ~PatchGeneratorX86_32() { }
  95. ExecutableType kind_;
  96. };
  97. } // namespace courgette
  98. #endif // COURGETTE_PATCH_GENERATOR_X86_32_H_