xref: /aosp_15_r20/external/zucchini/abs32_utils.h (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
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