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/common/align.h"
22 : #include "syzygy/core/serialization.h"
23 :
24 : namespace core {
25 :
26 : enum AddressType {
27 : kRelativeAddressType,
28 : kAbsoluteAddressType,
29 : kFileOffsetAddressType,
30 : };
31 :
32 : // This class implements an address in a PE image file.
33 : // Addresses are of three varieties:
34 : // - Relative addresses are relative to the base of the image, and thus do not
35 : // change when the image is relocated. Bulk of the addresses in the PE image
36 : // format itself are of this variety, and that's where relative addresses
37 : // crop up most frequently.
38 : // - Absolute addresses are as the name indicates absolute, and those change
39 : // when an image is relocated. Absolute addresses mostly occur in initialized
40 : // data, and for each absolute datum in an image file, there will be a
41 : // relocation entry calling out its location in the image.
42 : // - File offset addresses occur only in the debug data directory that I'm
43 : // aware of, where the debug data is referred to both by a relative address
44 : // and (presumably for convenience) by a file offset address.
45 : // This class is a lightweight wrapper for an integer, which can be freely
46 : // copied. The different address types are deliberately assignment
47 : // incompatible, which helps to avoid confusion when handling different
48 : // types of addresses in implementation.
49 : template <AddressType type> class AddressImpl {
50 : public:
51 : static const AddressImpl kInvalidAddress;
52 :
53 E : AddressImpl() : value_(0) {
54 E : }
55 E : explicit AddressImpl(uint32 value) : value_(value) {
56 E : }
57 E : AddressImpl(const AddressImpl<type>& other) // NOLINT
58 : : value_(other.value_) {
59 E : }
60 :
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 E : bool operator>=(const AddressImpl<type>& other) const {
71 E : return value_ >= other.value_;
72 E : }
73 :
74 E : bool operator==(const AddressImpl<type>& other) const {
75 E : return value_ == other.value_;
76 E : }
77 E : bool operator!=(const AddressImpl<type>& other) const {
78 E : return value_ != other.value_;
79 E : }
80 :
81 E : void operator=(const AddressImpl<type>& other) {
82 E : value_ = other.value_;
83 E : }
84 E : void operator+=(int32 offset) {
85 E : value_ += offset;
86 E : }
87 E : void operator-=(int32 offset) {
88 E : value_ -= offset;
89 E : }
90 :
91 E : AddressImpl<type> operator+(size_t offset) const {
92 E : return AddressImpl<type>(value() + offset);
93 E : }
94 :
95 E : AddressImpl<type> operator-(size_t offset) const {
96 E : return AddressImpl<type>(value() - offset);
97 E : }
98 :
99 E : int32 operator-(const AddressImpl<type>& other) const {
100 E : return value_ - other.value_;
101 E : }
102 :
103 E : uint32 value() const { return value_; }
104 E : void set_value(uint32 value) {
105 E : value_ = value;
106 E : }
107 :
108 E : AddressImpl<type> AlignUp(size_t alignment) const {
109 E : DCHECK_NE(0U, alignment);
110 : // Round up to nearest multiple of alignment.
111 E : uint32 value = ((value_ + alignment - 1) / alignment) * alignment;
112 E : return AddressImpl<type>(value);
113 E : }
114 :
115 E : bool IsAligned(size_t alignment) const {
116 E : DCHECK_NE(0U, alignment);
117 E : return (value_ % alignment) == 0;
118 E : }
119 :
120 : // Determines the address alignment. If the value of the address is 0 then we
121 : // return the maximum alignment for a 32-bit address (0x80000000).
122 : // @returns the alignment of the address.
123 E : uint32 GetAlignment() const {
124 E : return common::GetAlignment(value_);
125 E : }
126 :
127 : // For serialization.
128 E : bool Save(OutArchive *out_archive) const {
129 E : return out_archive->Save(value_);
130 E : }
131 E : bool Load(InArchive *in_archive) {
132 E : return in_archive->Load(&value_);
133 E : }
134 :
135 : private:
136 : uint32 value_;
137 : };
138 :
139 : // These types represent the different addressing formats used in PE images.
140 :
141 : // A virtual address relative to the image base, often termed
142 : // RVA in documentation and in data structure comments.
143 : typedef AddressImpl<kRelativeAddressType> RelativeAddress;
144 : // An absolute address.
145 : typedef AddressImpl<kAbsoluteAddressType> AbsoluteAddress;
146 : // A file offset within an image file.
147 : typedef AddressImpl<kFileOffsetAddressType> FileOffsetAddress;
148 :
149 : std::ostream& operator<<(std::ostream& str, RelativeAddress addr);
150 : std::ostream& operator<<(std::ostream& str, AbsoluteAddress addr);
151 : std::ostream& operator<<(std::ostream& str, FileOffsetAddress addr);
152 :
153 : } // namespace core
154 :
155 : #endif // SYZYGY_CORE_ADDRESS_H_
|