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_ABS32_UTILS_H_ 6*a03ca8b9SKrzysztof Kosiński #define COMPONENTS_ZUCCHINI_ABS32_UTILS_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 <optional> 12*a03ca8b9SKrzysztof Kosiński #include <vector> 13*a03ca8b9SKrzysztof Kosiński 14*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/address_translator.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 18*a03ca8b9SKrzysztof Kosiński namespace zucchini { 19*a03ca8b9SKrzysztof Kosiński 20*a03ca8b9SKrzysztof Kosiński // A class to represent an abs32 address (32-bit or 64-bit). Accessors are 21*a03ca8b9SKrzysztof Kosiński // provided to translate from / to RVA, and to read / write the represented 22*a03ca8b9SKrzysztof Kosiński // abs32 address from / to an image. 23*a03ca8b9SKrzysztof Kosiński class AbsoluteAddress { 24*a03ca8b9SKrzysztof Kosiński public: 25*a03ca8b9SKrzysztof Kosiński AbsoluteAddress(Bitness bitness, uint64_t image_base); 26*a03ca8b9SKrzysztof Kosiński AbsoluteAddress(AbsoluteAddress&&); 27*a03ca8b9SKrzysztof Kosiński ~AbsoluteAddress(); 28*a03ca8b9SKrzysztof Kosiński 29*a03ca8b9SKrzysztof Kosiński // Attempts to translate |rva| to an abs32 address. On success, assigns 30*a03ca8b9SKrzysztof Kosiński // |value_| to the result and returns true. On failure (invalid |rva| or 31*a03ca8b9SKrzysztof Kosiński // overflow), returns false. 32*a03ca8b9SKrzysztof Kosiński bool FromRva(rva_t rva); 33*a03ca8b9SKrzysztof Kosiński 34*a03ca8b9SKrzysztof Kosiński // Returns the RVA for |value_|, or |kInvalidRva| if the represented value 35*a03ca8b9SKrzysztof Kosiński // address does not correspond to a valid RVA. 36*a03ca8b9SKrzysztof Kosiński rva_t ToRva() const; 37*a03ca8b9SKrzysztof Kosiński 38*a03ca8b9SKrzysztof Kosiński // Attempts to read the abs32 address at |image[offset]| into |value_|. On 39*a03ca8b9SKrzysztof Kosiński // success, updates |value_| and returns true. On failure (invalid |offset|), 40*a03ca8b9SKrzysztof Kosiński // returns false. 41*a03ca8b9SKrzysztof Kosiński bool Read(offset_t offset, const ConstBufferView& image); 42*a03ca8b9SKrzysztof Kosiński 43*a03ca8b9SKrzysztof Kosiński // Attempts to write |value_| to to |(*image)[offset]|. On success, performs 44*a03ca8b9SKrzysztof Kosiński // the write and returns true. On failure (invalid |offset|), returns false. 45*a03ca8b9SKrzysztof Kosiński bool Write(offset_t offset, MutableBufferView* image); 46*a03ca8b9SKrzysztof Kosiński width()47*a03ca8b9SKrzysztof Kosiński uint32_t width() const { return WidthOf(bitness_); } 48*a03ca8b9SKrzysztof Kosiński 49*a03ca8b9SKrzysztof Kosiński // Exposing |value_| for testing. mutable_value()50*a03ca8b9SKrzysztof Kosiński uint64_t* mutable_value() { return &value_; } 51*a03ca8b9SKrzysztof Kosiński 52*a03ca8b9SKrzysztof Kosiński private: 53*a03ca8b9SKrzysztof Kosiński const Bitness bitness_; 54*a03ca8b9SKrzysztof Kosiński const uint64_t image_base_; // Accommodates 32-bit and 64-bit. 55*a03ca8b9SKrzysztof Kosiński uint64_t value_; // Accommodates 32-bit and 64-bit. 56*a03ca8b9SKrzysztof Kosiński }; 57*a03ca8b9SKrzysztof Kosiński 58*a03ca8b9SKrzysztof Kosiński // A class to extract Win32 abs32 references from |abs32_locations| within 59*a03ca8b9SKrzysztof Kosiński // |image_| bounded by |[lo, hi)|. GetNext() is used to successively return 60*a03ca8b9SKrzysztof Kosiński // data as Units, which are locations and (potentially out-of-bound) RVAs. 61*a03ca8b9SKrzysztof Kosiński // |addr| determines the bitness of abs32 values stored, and mediates all reads. 62*a03ca8b9SKrzysztof Kosiński class Abs32RvaExtractorWin32 { 63*a03ca8b9SKrzysztof Kosiński public: 64*a03ca8b9SKrzysztof Kosiński struct Unit { 65*a03ca8b9SKrzysztof Kosiński offset_t location; 66*a03ca8b9SKrzysztof Kosiński rva_t target_rva; 67*a03ca8b9SKrzysztof Kosiński }; 68*a03ca8b9SKrzysztof Kosiński 69*a03ca8b9SKrzysztof Kosiński // Requires |lo| <= |hi|, and they must not straddle a reference body (with 70*a03ca8b9SKrzysztof Kosiński // length |addr.width()|) in |abs32_locations|. 71*a03ca8b9SKrzysztof Kosiński Abs32RvaExtractorWin32(ConstBufferView image, 72*a03ca8b9SKrzysztof Kosiński AbsoluteAddress&& addr, 73*a03ca8b9SKrzysztof Kosiński const std::vector<offset_t>& abs32_locations, 74*a03ca8b9SKrzysztof Kosiński offset_t lo, 75*a03ca8b9SKrzysztof Kosiński offset_t hi); 76*a03ca8b9SKrzysztof Kosiński Abs32RvaExtractorWin32(Abs32RvaExtractorWin32&&); 77*a03ca8b9SKrzysztof Kosiński ~Abs32RvaExtractorWin32(); 78*a03ca8b9SKrzysztof Kosiński 79*a03ca8b9SKrzysztof Kosiński // Visits given abs32 locations, rejects invalid locations and non-existent 80*a03ca8b9SKrzysztof Kosiński // RVAs, and returns reference as Unit, or std::nullopt on completion. 81*a03ca8b9SKrzysztof Kosiński std::optional<Unit> GetNext(); 82*a03ca8b9SKrzysztof Kosiński 83*a03ca8b9SKrzysztof Kosiński private: 84*a03ca8b9SKrzysztof Kosiński ConstBufferView image_; 85*a03ca8b9SKrzysztof Kosiński AbsoluteAddress addr_; 86*a03ca8b9SKrzysztof Kosiński std::vector<offset_t>::const_iterator cur_abs32_; 87*a03ca8b9SKrzysztof Kosiński std::vector<offset_t>::const_iterator end_abs32_; 88*a03ca8b9SKrzysztof Kosiński }; 89*a03ca8b9SKrzysztof Kosiński 90*a03ca8b9SKrzysztof Kosiński // A reader for Win32 abs32 references that filters and translates results from 91*a03ca8b9SKrzysztof Kosiński // |abs32_rva_extractor_|. 92*a03ca8b9SKrzysztof Kosiński class Abs32ReaderWin32 : public ReferenceReader { 93*a03ca8b9SKrzysztof Kosiński public: 94*a03ca8b9SKrzysztof Kosiński Abs32ReaderWin32(Abs32RvaExtractorWin32&& abs32_rva_extractor, 95*a03ca8b9SKrzysztof Kosiński const AddressTranslator& translator); 96*a03ca8b9SKrzysztof Kosiński Abs32ReaderWin32(const Abs32ReaderWin32&) = delete; 97*a03ca8b9SKrzysztof Kosiński const Abs32ReaderWin32& operator=(const Abs32ReaderWin32&) = delete; 98*a03ca8b9SKrzysztof Kosiński ~Abs32ReaderWin32() override; 99*a03ca8b9SKrzysztof Kosiński 100*a03ca8b9SKrzysztof Kosiński // ReferenceReader: 101*a03ca8b9SKrzysztof Kosiński std::optional<Reference> GetNext() override; 102*a03ca8b9SKrzysztof Kosiński 103*a03ca8b9SKrzysztof Kosiński private: 104*a03ca8b9SKrzysztof Kosiński Abs32RvaExtractorWin32 abs32_rva_extractor_; 105*a03ca8b9SKrzysztof Kosiński AddressTranslator::RvaToOffsetCache target_rva_to_offset_; 106*a03ca8b9SKrzysztof Kosiński }; 107*a03ca8b9SKrzysztof Kosiński 108*a03ca8b9SKrzysztof Kosiński // A writer for Win32 abs32 references. |addr| determines the bitness of the 109*a03ca8b9SKrzysztof Kosiński // abs32 values stored, and mediates all writes. 110*a03ca8b9SKrzysztof Kosiński class Abs32WriterWin32 : public ReferenceWriter { 111*a03ca8b9SKrzysztof Kosiński public: 112*a03ca8b9SKrzysztof Kosiński Abs32WriterWin32(MutableBufferView image, 113*a03ca8b9SKrzysztof Kosiński AbsoluteAddress&& addr, 114*a03ca8b9SKrzysztof Kosiński const AddressTranslator& translator); 115*a03ca8b9SKrzysztof Kosiński Abs32WriterWin32(const Abs32WriterWin32&) = delete; 116*a03ca8b9SKrzysztof Kosiński const Abs32WriterWin32& operator=(const Abs32WriterWin32&) = delete; 117*a03ca8b9SKrzysztof Kosiński ~Abs32WriterWin32() override; 118*a03ca8b9SKrzysztof Kosiński 119*a03ca8b9SKrzysztof Kosiński // ReferenceWriter: 120*a03ca8b9SKrzysztof Kosiński void PutNext(Reference ref) override; 121*a03ca8b9SKrzysztof Kosiński 122*a03ca8b9SKrzysztof Kosiński private: 123*a03ca8b9SKrzysztof Kosiński MutableBufferView image_; 124*a03ca8b9SKrzysztof Kosiński AbsoluteAddress addr_; 125*a03ca8b9SKrzysztof Kosiński AddressTranslator::OffsetToRvaCache target_offset_to_rva_; 126*a03ca8b9SKrzysztof Kosiński }; 127*a03ca8b9SKrzysztof Kosiński 128*a03ca8b9SKrzysztof Kosiński // Given a list of abs32 |locations|, removes all elements whose targets cannot 129*a03ca8b9SKrzysztof Kosiński // be translated. Returns the number of elements removed. 130*a03ca8b9SKrzysztof Kosiński size_t RemoveUntranslatableAbs32(ConstBufferView image, 131*a03ca8b9SKrzysztof Kosiński AbsoluteAddress&& addr, 132*a03ca8b9SKrzysztof Kosiński const AddressTranslator& translator, 133*a03ca8b9SKrzysztof Kosiński std::vector<offset_t>* locations); 134*a03ca8b9SKrzysztof Kosiński 135*a03ca8b9SKrzysztof Kosiński // Given a sorted list of abs32 |locations|, removes all elements whose body 136*a03ca8b9SKrzysztof Kosiński // (with |width| given) overlaps with the body of a previous element. 137*a03ca8b9SKrzysztof Kosiński size_t RemoveOverlappingAbs32Locations(uint32_t width, 138*a03ca8b9SKrzysztof Kosiński std::vector<offset_t>* locations); 139*a03ca8b9SKrzysztof Kosiński 140*a03ca8b9SKrzysztof Kosiński } // namespace zucchini 141*a03ca8b9SKrzysztof Kosiński 142*a03ca8b9SKrzysztof Kosiński #endif // COMPONENTS_ZUCCHINI_ABS32_UTILS_H_ 143