summaryrefslogtreecommitdiff
path: root/chromium/components/zucchini/reference_bytes_mixer.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/zucchini/reference_bytes_mixer.h')
-rw-r--r--chromium/components/zucchini/reference_bytes_mixer.h91
1 files changed, 91 insertions, 0 deletions
diff --git a/chromium/components/zucchini/reference_bytes_mixer.h b/chromium/components/zucchini/reference_bytes_mixer.h
new file mode 100644
index 00000000000..9bc8f2dbcb3
--- /dev/null
+++ b/chromium/components/zucchini/reference_bytes_mixer.h
@@ -0,0 +1,91 @@
+// Copyright 2018 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 COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_
+#define COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "components/zucchini/buffer_view.h"
+#include "components/zucchini/image_utils.h"
+
+namespace zucchini {
+
+class Disassembler;
+
+// References encoding may be quite complex in some architectures (e.g., ARM),
+// requiring bit-level manipulation. In general, bits in a reference body fall
+// under 2 categories:
+// - Operation bits: Instruction op code, conditionals, or structural data.
+// - Payload bits: Actual target data of the reference. These may be absolute,
+// or be displacements relative to instruction pointer / program counter.
+// During patch application,
+// Old reference bytes = {old operation, old payload},
+// is transformed to
+// New reference bytes = {new operation, new payload}.
+// New image bytes are written by three sources:
+// (1) Direct copy from old image to new image for matched blocks.
+// (2) Bytewise diff correction.
+// (3) Dedicated reference target correction.
+//
+// For references whose operation and payload bits are stored in easily
+// separable bytes (e.g., rel32 reference in X86), (2) can exclude payload bits.
+// So during patch application, (1) naively copies everything, (2) fixes
+// operation bytes only, and (3) fixes payload bytes only.
+//
+// For architectures with references whose operation and payload bits may mix
+// within shared bytes (e.g., ARM rel32), a dilemma arises:
+// - (2) cannot ignores shared bytes, since otherwise new operation bits not
+// properly transfer.
+// - Having (2) always overwrite these bytes would reduce the benefits of
+// reference correction, since references are likely to change.
+//
+// Our solution applies a hybrid approach: For each matching old / new reference
+// pair, define:
+// Mixed reference bytes = {new operation, old payload},
+//
+// During patch generation, we compute bytewise correction from old reference
+// bytes to the mixed reference bytes. So during patch application, (2) only
+// corrects operation bit changes (and skips if they don't change), and (3)
+// overwrites old payload bits to new payload bits.
+
+// A base class for (stateful) mixed reference byte generation. This base class
+// serves as a stub. Architectures whose references store operation bits and
+// payload bits can share common bytes (e.g., ARM rel32) should override this.
+class ReferenceBytesMixer {
+ public:
+ ReferenceBytesMixer();
+ virtual ~ReferenceBytesMixer();
+
+ // Returns a new ReferenceBytesMixer instance that's owned by the caller.
+ static std::unique_ptr<ReferenceBytesMixer> Create(
+ const Disassembler& src_dis,
+ const Disassembler& dst_dis);
+
+ // Returns the number of bytes that need to be mixed for references with given
+ // |type|. Returns 0 if no mixing is required.
+ virtual int NumBytes(uint8_t type) const;
+
+ // Computes mixed reference bytes by combining (a) "payload bits" from an
+ // "old" reference of |type| at |old_base[old_offset]| with (b) "operation
+ // bits" from a "new" reference of |type| at |new_base[new_offset]|. Returns
+ // the result as ConstBufferView, which is valid only until the next call to
+ // Mix().
+ virtual ConstBufferView Mix(uint8_t type,
+ ConstBufferView::const_iterator old_base,
+ offset_t old_offset,
+ ConstBufferView::const_iterator new_base,
+ offset_t new_offset);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ReferenceBytesMixer);
+};
+
+} // namespace zucchini
+
+#endif // COMPONENTS_ZUCCHINI_REFERENCE_BYTES_MIXER_H_