Samuel Huang | 06f1ae9 | 2018-03-13 18:19:34 +0000 | [diff] [blame] | 1 | // Copyright 2017 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 | #ifndef COMPONENTS_ZUCCHINI_IMAGE_INDEX_H_ |
| 6 | #define COMPONENTS_ZUCCHINI_IMAGE_INDEX_H_ |
| 7 | |
| 8 | #include <stddef.h> |
| 9 | #include <stdint.h> |
| 10 | |
| 11 | #include <map> |
| 12 | #include <vector> |
| 13 | |
Hans Wennborg | d5ccca8 | 2020-06-24 13:46:35 +0000 | [diff] [blame] | 14 | #include "base/check_op.h" |
Samuel Huang | 06f1ae9 | 2018-03-13 18:19:34 +0000 | [diff] [blame] | 15 | #include "components/zucchini/buffer_view.h" |
| 16 | #include "components/zucchini/image_utils.h" |
| 17 | #include "components/zucchini/reference_set.h" |
| 18 | #include "components/zucchini/target_pool.h" |
| 19 | |
| 20 | namespace zucchini { |
| 21 | |
| 22 | class Disassembler; |
| 23 | |
| 24 | // A class that holds annotations of an image, allowing quick access to its raw |
| 25 | // and reference content. The memory overhead of storing all references is |
| 26 | // relatively high, so this is only used during patch generation. |
| 27 | class ImageIndex { |
| 28 | public: |
| 29 | explicit ImageIndex(ConstBufferView image); |
| 30 | ImageIndex(const ImageIndex&) = delete; |
| 31 | ImageIndex(ImageIndex&&); |
| 32 | ~ImageIndex(); |
| 33 | |
| 34 | // Inserts all references read from |disasm|. This should be called exactly |
| 35 | // once. If overlap between any two references of any type is encountered, |
| 36 | // returns false and leaves the object in an invalid state. Otherwise, |
| 37 | // returns true. |
| 38 | // TODO(huangs): Refactor ReaderFactory and WriterFactory so |
| 39 | // |const Disassembler&| can be used here. |
| 40 | bool Initialize(Disassembler* disasm); |
| 41 | |
| 42 | // Returns the array size needed to accommodate all reference type values. |
| 43 | size_t TypeCount() const { |
| 44 | if (reference_sets_.empty()) |
| 45 | return 0U; |
Samuel Huang | 56a6ff4 | 2018-03-13 21:35:53 +0000 | [diff] [blame] | 46 | return reference_sets_.rbegin()->first.value() + 1; // Max key + 1. |
Samuel Huang | 06f1ae9 | 2018-03-13 18:19:34 +0000 | [diff] [blame] | 47 | } |
| 48 | |
| 49 | // Returns the array size needed to accommodate all pool values. |
| 50 | size_t PoolCount() const { |
| 51 | if (target_pools_.empty()) |
| 52 | return 0U; |
Samuel Huang | 56a6ff4 | 2018-03-13 21:35:53 +0000 | [diff] [blame] | 53 | return target_pools_.rbegin()->first.value() + 1; // Max key + 1. |
Samuel Huang | 06f1ae9 | 2018-03-13 18:19:34 +0000 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | // Returns true if |image_[location]| is either: |
| 57 | // - A raw value. |
| 58 | // - The first byte of a reference. |
| 59 | bool IsToken(offset_t location) const; |
| 60 | |
| 61 | // Returns true if |image_[location]| is part of a reference. |
| 62 | bool IsReference(offset_t location) const { |
| 63 | return LookupType(location) != kNoTypeTag; |
| 64 | } |
| 65 | |
| 66 | // Returns the type tag of the reference covering |location|, or kNoTypeTag if |
| 67 | // |location| is not part of a reference. |
| 68 | TypeTag LookupType(offset_t location) const { |
| 69 | DCHECK_LT(location, size()); |
| 70 | return type_tags_[location]; |
| 71 | } |
| 72 | |
| 73 | // Returns the raw value at |location|. |
| 74 | uint8_t GetRawValue(offset_t location) const { |
| 75 | DCHECK_LT(location, size()); |
| 76 | return image_[location]; |
| 77 | } |
| 78 | |
| 79 | const std::map<PoolTag, TargetPool>& target_pools() const { |
| 80 | return target_pools_; |
| 81 | } |
| 82 | const std::map<TypeTag, ReferenceSet>& reference_sets() const { |
| 83 | return reference_sets_; |
| 84 | } |
| 85 | |
| 86 | const TargetPool& pool(PoolTag pool_tag) const { |
| 87 | return target_pools_.at(pool_tag); |
| 88 | } |
| 89 | const ReferenceSet& refs(TypeTag type_tag) const { |
| 90 | return reference_sets_.at(type_tag); |
| 91 | } |
| 92 | |
| 93 | // Returns the size of the image. |
| 94 | size_t size() const { return image_.size(); } |
| 95 | |
| 96 | private: |
| 97 | // Inserts to |*this| index, all references described by |traits| read from |
| 98 | // |ref_reader|, which gets consumed. This should be called exactly once for |
| 99 | // each reference type. If overlap between any two references of any type is |
| 100 | // encountered, returns false and leaves the object in an invalid state. |
| 101 | // Otherwise, returns true. |
| 102 | bool InsertReferences(const ReferenceTypeTraits& traits, |
| 103 | ReferenceReader&& ref_reader); |
| 104 | |
| 105 | const ConstBufferView image_; |
| 106 | |
| 107 | // Used for random access lookup of reference type, for each byte in |image_|. |
| 108 | std::vector<TypeTag> type_tags_; |
| 109 | |
| 110 | std::map<PoolTag, TargetPool> target_pools_; |
| 111 | std::map<TypeTag, ReferenceSet> reference_sets_; |
| 112 | }; |
| 113 | |
| 114 | } // namespace zucchini |
| 115 | |
| 116 | #endif // COMPONENTS_ZUCCHINI_IMAGE_INDEX_H_ |