1 : // Copyright 2014 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 : #include "syzygy/core/section_offset_address.h"
16 :
17 : #include <iostream>
18 : #include "base/logging.h"
19 : #include "base/strings/stringprintf.h"
20 : #include "syzygy/common/align.h"
21 :
22 : namespace core {
23 :
24 : namespace {
25 :
26 : // The minimum alignment of a PE section.
27 : // See http://msdn.microsoft.com/library/windows/desktop/ms680339.aspx
28 : const uint32 kPESectionMinAlignment = 512;
29 :
30 : // Host function for compile asserts.
31 : void SectionOffsetAddressCompileAsserts() {
32 : static_assert(sizeof(SectionOffsetAddress) == 2 * sizeof(uint32),
33 : "SectionOffsetAddress should be 8 bytes.");
34 : }
35 :
36 : } // namespace
37 :
38 E : const SectionOffsetAddress SectionOffsetAddress::kInvalidAddress(~0U, ~0U);
39 :
40 : SectionOffsetAddress::SectionOffset::SectionOffset(
41 : uint32 section_id, uint32 offset)
42 : : section_id(section_id),
43 E : offset(offset) {
44 E : }
45 :
46 : bool SectionOffsetAddress::SectionOffset::operator<(
47 E : const SectionOffset& other) const {
48 E : if (section_id < other.section_id)
49 E : return true;
50 E : if (section_id > other.section_id)
51 E : return false;
52 E : return offset < other.offset;
53 E : }
54 :
55 : bool SectionOffsetAddress::SectionOffset::operator<=(
56 E : const SectionOffset& other) const {
57 E : if (section_id < other.section_id)
58 E : return true;
59 E : if (section_id > other.section_id)
60 E : return false;
61 E : return offset <= other.offset;
62 E : }
63 :
64 : bool SectionOffsetAddress::SectionOffset::operator>(
65 E : const SectionOffset& other) const {
66 E : if (section_id > other.section_id)
67 E : return true;
68 E : if (section_id < other.section_id)
69 E : return false;
70 E : return offset > other.offset;
71 E : }
72 :
73 : bool SectionOffsetAddress::SectionOffset::operator>=(
74 E : const SectionOffset& other) const {
75 E : if (section_id > other.section_id)
76 E : return true;
77 E : if (section_id < other.section_id)
78 E : return false;
79 E : return offset >= other.offset;
80 E : }
81 :
82 : bool SectionOffsetAddress::SectionOffset::operator==(
83 E : const SectionOffset& other) const {
84 E : return section_id == other.section_id && offset == other.offset;
85 E : }
86 :
87 : bool SectionOffsetAddress::SectionOffset::operator!=(
88 E : const SectionOffset& other) const {
89 E : return section_id != other.section_id || offset != other.offset;
90 E : }
91 :
92 E : SectionOffsetAddress::SectionOffsetAddress() : value_(0, 0) {
93 E : }
94 :
95 : SectionOffsetAddress::SectionOffsetAddress(uint32 section_id, uint32 offset)
96 E : : value_(section_id, offset) {
97 E : }
98 :
99 : SectionOffsetAddress::SectionOffsetAddress(const SectionOffsetAddress& other)
100 E : : value_(other.value_) {
101 E : }
102 :
103 E : bool SectionOffsetAddress::operator<(const SectionOffsetAddress& other) const {
104 E : return value_ < other.value_;
105 E : }
106 :
107 E : bool SectionOffsetAddress::operator<=(const SectionOffsetAddress& other) const {
108 E : return value_ <= other.value_;
109 E : }
110 :
111 E : bool SectionOffsetAddress::operator>(const SectionOffsetAddress& other) const {
112 E : return value_ > other.value_;
113 E : }
114 :
115 E : bool SectionOffsetAddress::operator>=(const SectionOffsetAddress& other) const {
116 E : return value_ >= other.value_;
117 E : }
118 :
119 E : bool SectionOffsetAddress::operator==(const SectionOffsetAddress& other) const {
120 E : return value_ == other.value_;
121 E : }
122 :
123 E : bool SectionOffsetAddress::operator!=(const SectionOffsetAddress& other) const {
124 E : return value_ != other.value_;
125 E : }
126 :
127 E : void SectionOffsetAddress::operator=(const SectionOffsetAddress& other) {
128 E : value_ = other.value_;
129 E : }
130 :
131 E : void SectionOffsetAddress::operator+=(int32 offset) {
132 E : value_.offset += offset;
133 E : }
134 :
135 E : void SectionOffsetAddress::operator-=(int32 offset) {
136 E : value_.offset -= offset;
137 E : }
138 :
139 E : SectionOffsetAddress SectionOffsetAddress::operator+(size_t offset) const {
140 E : return SectionOffsetAddress(section_id(), value_.offset + offset);
141 E : }
142 :
143 E : SectionOffsetAddress SectionOffsetAddress::operator-(size_t offset) const {
144 E : return SectionOffsetAddress(section_id(), value_.offset - offset);
145 E : }
146 :
147 E : SectionOffsetAddress SectionOffsetAddress::AlignUp(size_t alignment) const {
148 E : DCHECK_NE(0U, alignment);
149 : // Sections are aligned on a power of 2 greater or equal to 512
150 : // (see http://msdn.microsoft.com/library/windows/desktop/ms680339.aspx).
151 : // Without knowing the exact alignment of the section, it is impossible to
152 : // guarantee an alignment on a power of 2 greater than 512.
153 E : DCHECK_LE(alignment, kPESectionMinAlignment);
154 :
155 : return SectionOffsetAddress(
156 E : section_id(), common::AlignUp(offset(), alignment));
157 E : }
158 :
159 E : bool SectionOffsetAddress::IsAligned(size_t alignment) const {
160 E : DCHECK_NE(0U, alignment);
161 E : DCHECK_LE(alignment, kPESectionMinAlignment);
162 :
163 E : return common::IsAligned(offset(), alignment);
164 E : }
165 :
166 E : uint32 SectionOffsetAddress::GetAlignment() const {
167 E : uint32 alignment = common::GetAlignment(offset());
168 E : if (alignment > kPESectionMinAlignment)
169 E : return kPESectionMinAlignment;
170 E : return alignment;
171 E : }
172 :
173 E : bool SectionOffsetAddress::Save(OutArchive *out_archive) const {
174 E : return out_archive->Save(section_id()) && out_archive->Save(offset());
175 E : }
176 :
177 E : bool SectionOffsetAddress::Load(InArchive *in_archive) {
178 : return in_archive->Load(&value_.section_id) &&
179 E : in_archive->Load(&value_.offset);
180 E : }
181 :
182 i : std::ostream& operator<<(std::ostream& str, const SectionOffsetAddress& addr) {
183 : str << base::StringPrintf(
184 i : "SectionOffset(0x%08X, 0x%08X)", addr.section_id(), addr.offset());
185 i : return str;
186 i : }
187 :
188 : } // namespace core
|