aboutsummaryrefslogtreecommitdiff
path: root/abs32_utils.h
blob: 07503b573919b4a40e5e18ac2231fdb509ab04e7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef COMPONENTS_ZUCCHINI_ABS32_UTILS_H_
#define COMPONENTS_ZUCCHINI_ABS32_UTILS_H_

#include <stddef.h>
#include <stdint.h>

#include <vector>

#include "components/zucchini/address_translator.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace zucchini {

// A class to represent an abs32 address (32-bit or 64-bit). Accessors are
// provided to translate from / to RVA, and to read / write the represented
// abs32 address from / to an image.
class AbsoluteAddress {
 public:
  AbsoluteAddress(Bitness bitness, uint64_t image_base);
  AbsoluteAddress(AbsoluteAddress&&);
  ~AbsoluteAddress();

  // Attempts to translate |rva| to an abs32 address. On success, assigns
  // |value_| to the result and returns true. On failure (invalid |rva| or
  // overflow), returns false.
  bool FromRva(rva_t rva);

  // Returns the RVA for |value_|, or |kInvalidRva| if the represented value
  // address does not correspond to a valid RVA.
  rva_t ToRva() const;

  // Attempts to read the abs32 address at |image[offset]| into |value_|. On
  // success, updates |value_| and returns true. On failure (invalid |offset|),
  // returns false.
  bool Read(offset_t offset, const ConstBufferView& image);

  // Attempts to write |value_| to to |(*image)[offset]|. On success, performs
  // the write and returns true. On failure (invalid |offset|), returns false.
  bool Write(offset_t offset, MutableBufferView* image);

  uint32_t width() const { return WidthOf(bitness_); }

  // Exposing |value_| for testing.
  uint64_t* mutable_value() { return &value_; }

 private:
  const Bitness bitness_;
  const uint64_t image_base_;  // Accommodates 32-bit and 64-bit.
  uint64_t value_;             // Accommodates 32-bit and 64-bit.
};

// A class to extract Win32 abs32 references from |abs32_locations| within
// |image_| bounded by |[lo, hi)|. GetNext() is used to successively return
// data as Units, which are locations and (potentially out-of-bound) RVAs.
// |addr| determines the bitness of abs32 values stored, and mediates all reads.
class Abs32RvaExtractorWin32 {
 public:
  struct Unit {
    offset_t location;
    rva_t target_rva;
  };

  // Requires |lo| <= |hi|, and they must not straddle a reference body (with
  // length |addr.width()|) in |abs32_locations|.
  Abs32RvaExtractorWin32(ConstBufferView image,
                         AbsoluteAddress&& addr,
                         const std::vector<offset_t>& abs32_locations,
                         offset_t lo,
                         offset_t hi);
  Abs32RvaExtractorWin32(Abs32RvaExtractorWin32&&);
  ~Abs32RvaExtractorWin32();

  // Visits given abs32 locations, rejects invalid locations and non-existent
  // RVAs, and returns reference as Unit, or absl::nullopt on completion.
  absl::optional<Unit> GetNext();

 private:
  ConstBufferView image_;
  AbsoluteAddress addr_;
  std::vector<offset_t>::const_iterator cur_abs32_;
  std::vector<offset_t>::const_iterator end_abs32_;
};

// A reader for Win32 abs32 references that filters and translates results from
// |abs32_rva_extractor_|.
class Abs32ReaderWin32 : public ReferenceReader {
 public:
  Abs32ReaderWin32(Abs32RvaExtractorWin32&& abs32_rva_extractor,
                   const AddressTranslator& translator);
  Abs32ReaderWin32(const Abs32ReaderWin32&) = delete;
  const Abs32ReaderWin32& operator=(const Abs32ReaderWin32&) = delete;
  ~Abs32ReaderWin32() override;

  // ReferenceReader:
  absl::optional<Reference> GetNext() override;

 private:
  Abs32RvaExtractorWin32 abs32_rva_extractor_;
  AddressTranslator::RvaToOffsetCache target_rva_to_offset_;
};

// A writer for Win32 abs32 references. |addr| determines the bitness of the
// abs32 values stored, and mediates all writes.
class Abs32WriterWin32 : public ReferenceWriter {
 public:
  Abs32WriterWin32(MutableBufferView image,
                   AbsoluteAddress&& addr,
                   const AddressTranslator& translator);
  Abs32WriterWin32(const Abs32WriterWin32&) = delete;
  const Abs32WriterWin32& operator=(const Abs32WriterWin32&) = delete;
  ~Abs32WriterWin32() override;

  // ReferenceWriter:
  void PutNext(Reference ref) override;

 private:
  MutableBufferView image_;
  AbsoluteAddress addr_;
  AddressTranslator::OffsetToRvaCache target_offset_to_rva_;
};

// Given a list of abs32 |locations|, removes all elements whose targets cannot
// be translated. Returns the number of elements removed.
size_t RemoveUntranslatableAbs32(ConstBufferView image,
                                 AbsoluteAddress&& addr,
                                 const AddressTranslator& translator,
                                 std::vector<offset_t>* locations);

// Given a sorted list of abs32 |locations|, removes all elements whose body
// (with |width| given) overlaps with the body of a previous element.
size_t RemoveOverlappingAbs32Locations(uint32_t width,
                                       std::vector<offset_t>* locations);

}  // namespace zucchini

#endif  // COMPONENTS_ZUCCHINI_ABS32_UTILS_H_