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