aboutsummaryrefslogtreecommitdiff
path: root/abs32_utils.h
blob: b1d3ae00c78a8eaa25eab52d2a0c784e5baf8d8e (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
// 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 "base/macros.h"
#include "base/optional.h"
#include "components/zucchini/address_translator.h"
#include "components/zucchini/buffer_view.h"
#include "components/zucchini/image_utils.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);

  size_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 base::nullopt on completion.
  base::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() override;

  // ReferenceReader:
  base::Optional<Reference> GetNext() override;

 private:
  Abs32RvaExtractorWin32 abs32_rva_extractor_;
  AddressTranslator::RvaToOffsetCache target_rva_to_offset_;

  DISALLOW_COPY_AND_ASSIGN(Abs32ReaderWin32);
};

// 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() override;

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

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

  DISALLOW_COPY_AND_ASSIGN(Abs32WriterWin32);
};

// Given a sorted list of abs32 |locations|, removes all elements whose body
// overlaps with the body of a previous element (|bitness| determines length).
// Returns the number of elements removed.
size_t RemoveOverlappingAbs32Locations(Bitness bitness,
                                       std::vector<offset_t>* locations);

}  // namespace zucchini

#endif  // COMPONENTS_ZUCCHINI_ABS32_UTILS_H_