1 : // Copyright 2011 Google Inc. All Rights Reserved.
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 avoid confusion when handling different
47 : // types of addresses in implementation.
48 : template <AddressType type> class AddressImpl {
49 : public:
50 : static const AddressImpl kInvalidAddress;
51 :
52 E : AddressImpl() : value_(0) {
53 E : }
54 E : explicit AddressImpl(uint32 value) : value_(value) {
55 E : }
56 E : AddressImpl(const AddressImpl<type>& other) // NOLINT
57 : : value_(other.value_) {
58 E : }
59 :
60 E : bool operator<(const AddressImpl<type>& other) const {
61 E : return value_ < other.value_;
62 E : }
63 E : bool operator<=(const AddressImpl<type>& other) const {
64 E : return value_ <= other.value_;
65 E : }
66 E : bool operator>(const AddressImpl<type>& other) const {
67 E : return value_ > other.value_;
68 E : }
69 E : bool operator>=(const AddressImpl<type>& other) const {
70 E : return value_ >= other.value_;
71 E : }
72 :
73 E : bool operator==(const AddressImpl<type>& other) const {
74 E : return value_ == other.value_;
75 E : }
76 E : bool operator!=(const AddressImpl<type>& other) const {
77 E : return value_ != other.value_;
78 E : }
79 :
80 E : void operator=(const AddressImpl<type>& other) {
81 E : value_ = other.value_;
82 E : }
83 E : void operator+=(int32 offset) {
84 E : value_ += offset;
85 E : }
86 E : void operator-=(int32 offset) {
87 E : value_ -= offset;
88 E : }
89 :
90 E : AddressImpl<type> operator+(size_t offset) const {
91 E : return AddressImpl<type>(value() + offset);
92 E : }
93 :
94 E : AddressImpl<type> operator-(size_t offset) const {
95 E : return AddressImpl<type>(value() - offset);
96 E : }
97 :
98 E : int32 operator-(const AddressImpl<type>& other) const {
99 E : return value_ - other.value_;
100 E : }
101 :
102 E : uint32 value() const { return value_; }
103 E : void set_value(uint32 value) {
104 E : value_ = value;
105 E : }
106 :
107 E : AddressImpl<type> AlignUp(size_t alignment) const {
108 E : DCHECK_NE(0U, alignment);
109 : // Round up to nearest multiple of alignment.
110 E : uint32 value = ((value_ + alignment - 1) / alignment) * alignment;
111 E : return AddressImpl<type>(value);
112 E : }
113 :
114 E : bool IsAligned(size_t alignment) const {
115 E : DCHECK_NE(0U, alignment);
116 E : return (value_ % alignment) == 0;
117 E : }
118 :
119 : // Determines the address alignment by counting the trailing zeros. If the
120 : // value of the address is 0 then we return the maximum alignment for a 32-bit
121 : // address (0x80000000).
122 E : uint32 GetAlignment() const {
123 E : uint32 value_copy = value_;
124 E : uint8 trailing_zeros = 0;
125 :
126 : // Sets the trailing zeros to one and set the other bits to zero.
127 : // This is inspired from the code on this page:
128 : // http://graphics.stanford.edu/~seander/bithacks.html#ZerosOnRightLinear
129 E : value_copy = (value_copy ^ (value_copy - 1)) >> 1;
130 :
131 E : for (; value_copy > 0; trailing_zeros++)
132 E : value_copy >>= 1;
133 :
134 E : return (1 << trailing_zeros);
135 E : }
136 :
137 : // For serialization.
138 E : bool Save(OutArchive *out_archive) const {
139 E : return out_archive->Save(value_);
140 E : }
141 E : bool Load(InArchive *in_archive) {
142 E : return in_archive->Load(&value_);
143 E : }
144 :
145 : private:
146 : uint32 value_;
147 : };
148 :
149 : // These types represent the different addressing formats used in PE images.
150 :
151 : // A virtual address relative to the image base, often termed
152 : // RVA in documentation and in data structure comments.
153 : typedef AddressImpl<kRelativeAddressType> RelativeAddress;
154 : // An absolute address.
155 : typedef AddressImpl<kAbsoluteAddressType> AbsoluteAddress;
156 : // A file offset within an image file.
157 : typedef AddressImpl<kFileOffsetAddressType> FileOffsetAddress;
158 :
159 : std::ostream& operator<<(std::ostream& str, RelativeAddress addr);
160 : std::ostream& operator<<(std::ostream& str, AbsoluteAddress addr);
161 : std::ostream& operator<<(std::ostream& str, FileOffsetAddress addr);
162 :
163 : } // namespace core
164 :
165 : #endif // SYZYGY_CORE_ADDRESS_H_
|