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