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 
14 #include "base/check_op.h"
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.
TypeCount()43   size_t TypeCount() const {
44     if (reference_sets_.empty())
45       return 0U;
46     return reference_sets_.rbegin()->first.value() + 1;  // Max key + 1.
47   }
48 
49   // Returns the array size needed to accommodate all pool values.
PoolCount()50   size_t PoolCount() const {
51     if (target_pools_.empty())
52       return 0U;
53     return target_pools_.rbegin()->first.value() + 1;  // Max key + 1.
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.
IsReference(offset_t location)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.
LookupType(offset_t location)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|.
GetRawValue(offset_t location)74   uint8_t GetRawValue(offset_t location) const {
75     DCHECK_LT(location, size());
76     return image_[location];
77   }
78 
target_pools()79   const std::map<PoolTag, TargetPool>& target_pools() const {
80     return target_pools_;
81   }
reference_sets()82   const std::map<TypeTag, ReferenceSet>& reference_sets() const {
83     return reference_sets_;
84   }
85 
pool(PoolTag pool_tag)86   const TargetPool& pool(PoolTag pool_tag) const {
87     return target_pools_.at(pool_tag);
88   }
refs(TypeTag type_tag)89   const ReferenceSet& refs(TypeTag type_tag) const {
90     return reference_sets_.at(type_tag);
91   }
92 
93   // Returns the size of the image.
size()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_
117