1*a03ca8b9SKrzysztof Kosiński // Copyright 2018 The Chromium Authors. All rights reserved. 2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be 3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file. 4*a03ca8b9SKrzysztof Kosiński 5*a03ca8b9SKrzysztof Kosiński #ifndef COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_ 6*a03ca8b9SKrzysztof Kosiński #define COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_ 7*a03ca8b9SKrzysztof Kosiński 8*a03ca8b9SKrzysztof Kosiński #include <stdint.h> 9*a03ca8b9SKrzysztof Kosiński 10*a03ca8b9SKrzysztof Kosiński #include <memory> 11*a03ca8b9SKrzysztof Kosiński 12*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/buffer_view.h" 13*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/image_utils.h" 14*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/rel32_utils.h" 15*a03ca8b9SKrzysztof Kosiński 16*a03ca8b9SKrzysztof Kosiński namespace zucchini { 17*a03ca8b9SKrzysztof Kosiński 18*a03ca8b9SKrzysztof Kosiński class Disassembler; 19*a03ca8b9SKrzysztof Kosiński 20*a03ca8b9SKrzysztof Kosiński // References encoding may be quite complex in some architectures (e.g., ARM), 21*a03ca8b9SKrzysztof Kosiński // requiring bit-level manipulation. In general, bits in a reference body fall 22*a03ca8b9SKrzysztof Kosiński // under 2 categories: 23*a03ca8b9SKrzysztof Kosiński // - Operation bits: Instruction op code, conditionals, or structural data. 24*a03ca8b9SKrzysztof Kosiński // - Payload bits: Actual target data of the reference. These may be absolute, 25*a03ca8b9SKrzysztof Kosiński // or be displacements relative to instruction pointer / program counter. 26*a03ca8b9SKrzysztof Kosiński // During patch application, 27*a03ca8b9SKrzysztof Kosiński // Old reference bytes = {old operation, old payload}, 28*a03ca8b9SKrzysztof Kosiński // is transformed to 29*a03ca8b9SKrzysztof Kosiński // New reference bytes = {new operation, new payload}. 30*a03ca8b9SKrzysztof Kosiński // New image bytes are written by three sources: 31*a03ca8b9SKrzysztof Kosiński // (1) Direct copy from old image to new image for matched blocks. 32*a03ca8b9SKrzysztof Kosiński // (2) Bytewise diff correction. 33*a03ca8b9SKrzysztof Kosiński // (3) Dedicated reference target correction. 34*a03ca8b9SKrzysztof Kosiński // 35*a03ca8b9SKrzysztof Kosiński // For references whose operation and payload bits are stored in easily 36*a03ca8b9SKrzysztof Kosiński // separable bytes (e.g., rel32 reference in X86), (2) can exclude payload bits. 37*a03ca8b9SKrzysztof Kosiński // So during patch application, (1) naively copies everything, (2) fixes 38*a03ca8b9SKrzysztof Kosiński // operation bytes only, and (3) fixes payload bytes only. 39*a03ca8b9SKrzysztof Kosiński // 40*a03ca8b9SKrzysztof Kosiński // For architectures with references whose operation and payload bits may mix 41*a03ca8b9SKrzysztof Kosiński // within shared bytes (e.g., ARM rel32), a dilemma arises: 42*a03ca8b9SKrzysztof Kosiński // - (2) cannot ignores shared bytes, since otherwise new operation bits not 43*a03ca8b9SKrzysztof Kosiński // properly transfer. 44*a03ca8b9SKrzysztof Kosiński // - Having (2) always overwrite these bytes would reduce the benefits of 45*a03ca8b9SKrzysztof Kosiński // reference correction, since references are likely to change. 46*a03ca8b9SKrzysztof Kosiński // 47*a03ca8b9SKrzysztof Kosiński // Our solution applies a hybrid approach: For each matching old / new reference 48*a03ca8b9SKrzysztof Kosiński // pair, define: 49*a03ca8b9SKrzysztof Kosiński // Mixed reference bytes = {new operation, old payload}, 50*a03ca8b9SKrzysztof Kosiński // 51*a03ca8b9SKrzysztof Kosiński // During patch generation, we compute bytewise correction from old reference 52*a03ca8b9SKrzysztof Kosiński // bytes to the mixed reference bytes. So during patch application, (2) only 53*a03ca8b9SKrzysztof Kosiński // corrects operation bit changes (and skips if they don't change), and (3) 54*a03ca8b9SKrzysztof Kosiński // overwrites old payload bits to new payload bits. 55*a03ca8b9SKrzysztof Kosiński 56*a03ca8b9SKrzysztof Kosiński // A base class for (stateful) mixed reference byte generation. This base class 57*a03ca8b9SKrzysztof Kosiński // serves as a stub. Architectures whose references store operation bits and 58*a03ca8b9SKrzysztof Kosiński // payload bits can share common bytes (e.g., ARM rel32) should override this. 59*a03ca8b9SKrzysztof Kosiński class ReferenceBytesMixer { 60*a03ca8b9SKrzysztof Kosiński public: 61*a03ca8b9SKrzysztof Kosiński ReferenceBytesMixer(); 62*a03ca8b9SKrzysztof Kosiński ReferenceBytesMixer(const ReferenceBytesMixer&) = delete; 63*a03ca8b9SKrzysztof Kosiński const ReferenceBytesMixer& operator=(const ReferenceBytesMixer&) = delete; 64*a03ca8b9SKrzysztof Kosiński virtual ~ReferenceBytesMixer(); 65*a03ca8b9SKrzysztof Kosiński 66*a03ca8b9SKrzysztof Kosiński // Returns a new ReferenceBytesMixer instance that's owned by the caller. 67*a03ca8b9SKrzysztof Kosiński static std::unique_ptr<ReferenceBytesMixer> Create( 68*a03ca8b9SKrzysztof Kosiński const Disassembler& src_dis, 69*a03ca8b9SKrzysztof Kosiński const Disassembler& dst_dis); 70*a03ca8b9SKrzysztof Kosiński 71*a03ca8b9SKrzysztof Kosiński // Returns the number of bytes that need to be mixed for references with given 72*a03ca8b9SKrzysztof Kosiński // |type|. Returns 0 if no mixing is required. 73*a03ca8b9SKrzysztof Kosiński virtual int NumBytes(uint8_t type) const; 74*a03ca8b9SKrzysztof Kosiński 75*a03ca8b9SKrzysztof Kosiński // Computes mixed reference bytes by combining (a) "payload bits" from an 76*a03ca8b9SKrzysztof Kosiński // "old" reference of |type| at |old_view[old_offset]| with (b) "operation 77*a03ca8b9SKrzysztof Kosiński // bits" from a "new" reference of |type| at |new_view[new_offset]|. Returns 78*a03ca8b9SKrzysztof Kosiński // the result as ConstBufferView, which is valid only until the next call to 79*a03ca8b9SKrzysztof Kosiński // Mix(). 80*a03ca8b9SKrzysztof Kosiński virtual ConstBufferView Mix(uint8_t type, 81*a03ca8b9SKrzysztof Kosiński ConstBufferView old_view, 82*a03ca8b9SKrzysztof Kosiński offset_t old_offset, 83*a03ca8b9SKrzysztof Kosiński ConstBufferView new_view, 84*a03ca8b9SKrzysztof Kosiński offset_t new_offset); 85*a03ca8b9SKrzysztof Kosiński }; 86*a03ca8b9SKrzysztof Kosiński 87*a03ca8b9SKrzysztof Kosiński // In AArch32 and AArch64, instructions mix operation bits and payload bits in 88*a03ca8b9SKrzysztof Kosiński // complex ways. This is the main use case of ReferenceBytesMixer. 89*a03ca8b9SKrzysztof Kosiński class ReferenceBytesMixerElfArm : public ReferenceBytesMixer { 90*a03ca8b9SKrzysztof Kosiński public: 91*a03ca8b9SKrzysztof Kosiński // |exe_type| must be EXE_TYPE_ELF_ARM or EXE_TYPE_ELF_AARCH64. 92*a03ca8b9SKrzysztof Kosiński explicit ReferenceBytesMixerElfArm(ExecutableType exe_type); 93*a03ca8b9SKrzysztof Kosiński ReferenceBytesMixerElfArm(const ReferenceBytesMixerElfArm&) = delete; 94*a03ca8b9SKrzysztof Kosiński const ReferenceBytesMixerElfArm& operator=(const ReferenceBytesMixerElfArm&) = 95*a03ca8b9SKrzysztof Kosiński delete; 96*a03ca8b9SKrzysztof Kosiński ~ReferenceBytesMixerElfArm() override; 97*a03ca8b9SKrzysztof Kosiński 98*a03ca8b9SKrzysztof Kosiński // ReferenceBytesMixer: 99*a03ca8b9SKrzysztof Kosiński int NumBytes(uint8_t type) const override; 100*a03ca8b9SKrzysztof Kosiński ConstBufferView Mix(uint8_t type, 101*a03ca8b9SKrzysztof Kosiński ConstBufferView old_view, 102*a03ca8b9SKrzysztof Kosiński offset_t old_offset, 103*a03ca8b9SKrzysztof Kosiński ConstBufferView new_view, 104*a03ca8b9SKrzysztof Kosiński offset_t new_offset) override; 105*a03ca8b9SKrzysztof Kosiński 106*a03ca8b9SKrzysztof Kosiński private: 107*a03ca8b9SKrzysztof Kosiński ArmCopyDispFun GetCopier(uint8_t type) const; 108*a03ca8b9SKrzysztof Kosiński 109*a03ca8b9SKrzysztof Kosiński // For simplicity, 32-bit vs. 64-bit distinction is represented by state 110*a03ca8b9SKrzysztof Kosiński // |exe_type_|, instead of creating derived classes. 111*a03ca8b9SKrzysztof Kosiński const ExecutableType exe_type_; 112*a03ca8b9SKrzysztof Kosiński 113*a03ca8b9SKrzysztof Kosiński std::vector<uint8_t> out_buffer_; 114*a03ca8b9SKrzysztof Kosiński }; 115*a03ca8b9SKrzysztof Kosiński 116*a03ca8b9SKrzysztof Kosiński } // namespace zucchini 117*a03ca8b9SKrzysztof Kosiński 118*a03ca8b9SKrzysztof Kosiński #endif // COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_ 119