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