1 : // Copyright 2011 Google Inc.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (the "License");
4 : // you may not use this file except in compliance with the License.
5 : // You may obtain a copy of the License at
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #ifndef SYZYGY_CORE_ADDRESS_H_
16 : #define SYZYGY_CORE_ADDRESS_H_
17 :
18 : #include <iosfwd>
19 : #include "base/basictypes.h"
20 : #include "base/logging.h"
21 : #include "syzygy/core/serialization.h"
22 :
23 : namespace core {
24 :
25 : enum AddressType {
26 : kRelativeAddressType,
27 : kAbsoluteAddressType,
28 : kFileOffsetAddressType,
29 : };
30 :
31 : // This class implements an address in a PE image file.
32 : // Addresses are of three varieties:
33 : // - Relative addresses are relative to the base of the image, and thus do not
34 : // change when the image is relocated. Bulk of the addresses in the PE image
35 : // format itself are of this variety, and that's where relative addresses
36 : // crop up most frequently.
37 : // - Absolute addresses are as the name indicates absolute, and those change
38 : // when an image is relocated. Absolute addresses mostly occur in initialized
39 : // data, and for each absolute datum in an image file, there will be a
40 : // relocation entry calling out its location in the image.
41 : // - File offset addresses occur only in the debug data directory that I'm
42 : // aware of, where the debug data is referred to both by a relative address
43 : // and (presumably for convenience) by a file offset address.
44 : // This class is a lightweight wrapper for an integer, which can be freely
45 : // copied. The different address types are deliberately assignment
46 : // incompatible, which helps to avod confusion when handling different
47 : // types of addresses in implementation.
48 : template <AddressType type> class AddressImpl {
49 : public:
50 E : AddressImpl() : value_(0) {
51 E : }
52 E : explicit AddressImpl(uint32 value) : value_(value) {
53 E : }
54 E : AddressImpl(const AddressImpl<type>& other) // NOLINT
55 : : value_(other.value_) {
56 E : }
57 :
58 E : bool operator<(const AddressImpl<type>& other) const {
59 E : return value_ < other.value_;
60 E : }
61 E : bool operator<=(const AddressImpl<type>& other) const {
62 E : return value_ <= other.value_;
63 E : }
64 E : bool operator>(const AddressImpl<type>& other) const {
65 E : return value_ > other.value_;
66 E : }
67 E : bool operator>=(const AddressImpl<type>& other) const {
68 E : return value_ >= other.value_;
69 E : }
70 :
71 E : bool operator==(const AddressImpl<type>& other) const {
72 E : return value_ == other.value_;
73 E : }
74 E : bool operator!=(const AddressImpl<type>& other) const {
75 E : return value_ != other.value_;
76 E : }
77 :
78 E : void operator=(const AddressImpl<type>& other) {
79 E : value_ = other.value_;
80 E : }
81 E : void operator+=(int32 offset) {
82 E : value_ += offset;
83 E : }
84 E : void operator-=(int32 offset) {
85 E : value_ -= offset;
86 E : }
87 :
88 E : AddressImpl<type> operator+(size_t offset) const {
89 E : return AddressImpl<type>(value() + offset);
90 E : }
91 :
92 E : AddressImpl<type> operator-(size_t offset) const {
93 E : return AddressImpl<type>(value() - offset);
94 E : }
95 :
96 E : int32 operator-(const AddressImpl<type>& other) const {
97 E : return value_ - other.value_;
98 E : }
99 :
100 E : uint32 value() const { return value_; }
101 E : void set_value(uint32 value) {
102 E : value_ = value;
103 E : }
104 :
105 E : AddressImpl<type> AlignUp(size_t alignment) const {
106 E : DCHECK(alignment > 0);
107 : // Round up to nearest multiple of alignment.
108 E : uint32 value = ((value_ + alignment - 1) / alignment) * alignment;
109 E : return AddressImpl<type>(value);
110 E : }
111 :
112 E : bool IsAligned(size_t alignment) const {
113 E : DCHECK(alignment > 0);
114 E : return (value_ % alignment) == 0;
115 E : }
116 :
117 : // For serialization.
118 E : bool Save(OutArchive *out_archive) const {
119 E : return out_archive->Save(value_);
120 E : }
121 E : bool Load(InArchive *in_archive) {
122 E : return in_archive->Load(&value_);
123 E : }
124 :
125 : private:
126 : uint32 value_;
127 : };
128 :
129 : // These types represent the different addressing formats used in PE images.
130 :
131 : // A virtual address relative to the image base, often termed
132 : // RVA in documentation and in data structure comments.
133 : typedef AddressImpl<kRelativeAddressType> RelativeAddress;
134 : // An absolute address.
135 : typedef AddressImpl<kAbsoluteAddressType> AbsoluteAddress;
136 : // A file offset within an image file.
137 : typedef AddressImpl<kFileOffsetAddressType> FileOffsetAddress;
138 :
139 : std::ostream& operator<<(std::ostream& str, RelativeAddress addr);
140 : std::ostream& operator<<(std::ostream& str, AbsoluteAddress addr);
141 : std::ostream& operator<<(std::ostream& str, FileOffsetAddress addr);
142 :
143 : } // namespace core
144 :
145 : #endif // SYZYGY_CORE_ADDRESS_H_
|