1 // Copyright (C) 2019 Alibaba Cloud Computing. All rights reserved. 2 // 3 // Portions Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 // 5 // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style license that can be 7 // found in the LICENSE-BSD-3-Clause file. 8 // 9 // SPDX-License-Identifier: Apache-2.0 OR BSD-3-Clause 10 11 //! Traits to represent an address within an address space. 12 //! 13 //! Two traits are defined to represent an address within an address space: 14 //! - [`AddressValue`](trait.AddressValue.html): stores the raw value of an address. Typically 15 //! `u32`,`u64` or `usize` is used to store the raw value. But pointers, such as `*u8`, can't be used 16 //! because they don't implement the [`Add`](https://doc.rust-lang.org/std/ops/trait.Add.html) and 17 //! [`Sub`](https://doc.rust-lang.org/std/ops/trait.Sub.html) traits. 18 //! - [Address](trait.Address.html): encapsulates an [`AddressValue`](trait.AddressValue.html) 19 //! object and defines methods to access and manipulate it. 20 21 use std::cmp::{Eq, Ord, PartialEq, PartialOrd}; 22 use std::fmt::Debug; 23 use std::ops::{Add, BitAnd, BitOr, Not, Sub}; 24 25 /// Simple helper trait used to store a raw address value. 26 pub trait AddressValue { 27 /// Type of the raw address value. 28 type V: Copy 29 + PartialEq 30 + Eq 31 + PartialOrd 32 + Ord 33 + Not<Output = Self::V> 34 + Add<Output = Self::V> 35 + Sub<Output = Self::V> 36 + BitAnd<Output = Self::V> 37 + BitOr<Output = Self::V> 38 + Debug 39 + From<u8>; 40 41 /// Return the value zero, coerced into the value type `Self::V` zero() -> Self::V42 fn zero() -> Self::V { 43 0u8.into() 44 } 45 46 /// Return the value zero, coerced into the value type `Self::V` one() -> Self::V47 fn one() -> Self::V { 48 1u8.into() 49 } 50 } 51 52 /// Trait to represent an address within an address space. 53 /// 54 /// To simplify the design and implementation, assume the same raw data type `(AddressValue::V)` 55 /// could be used to store address, size and offset for the address space. Thus the `Address` trait 56 /// could be used to manage address, size and offset. On the other hand, type aliases may be 57 /// defined to improve code readability. 58 /// 59 /// One design rule is applied to the `Address` trait, namely that operators (+, -, &, | etc) are 60 /// not supported and it forces clients to explicitly invoke corresponding methods. But there are 61 /// always exceptions: 62 /// `Address` (BitAnd|BitOr) `AddressValue` are supported. 63 pub trait Address: 64 AddressValue 65 + Sized 66 + Default 67 + Copy 68 + Eq 69 + PartialEq 70 + Ord 71 + PartialOrd 72 + BitAnd<<Self as AddressValue>::V, Output = Self> 73 + BitOr<<Self as AddressValue>::V, Output = Self> 74 { 75 /// Creates an address from a raw address value. 76 fn new(addr: Self::V) -> Self; 77 78 /// Returns the raw value of the address. 79 fn raw_value(&self) -> Self::V; 80 81 /// Returns the bitwise and of the address with the given mask. 82 fn mask(&self, mask: Self::V) -> Self::V { 83 self.raw_value() & mask 84 } 85 86 /// Computes the offset from this address to the given base address. 87 /// 88 /// Returns `None` if there is underflow. 89 fn checked_offset_from(&self, base: Self) -> Option<Self::V>; 90 91 /// Computes the offset from this address to the given base address. 92 /// 93 /// In the event of overflow, follows standard Rust behavior, i.e. panic in debug builds, 94 /// silently wrap in release builds. 95 /// 96 /// Note that, unlike the `unchecked_*` methods in std, this method never invokes undefined 97 /// behavior. 98 /// # Examples 99 /// 100 /// ``` 101 /// # use vm_memory::{Address, GuestAddress}; 102 /// # 103 /// let base = GuestAddress(0x100); 104 /// let addr = GuestAddress(0x150); 105 /// assert_eq!(addr.unchecked_offset_from(base), 0x50); 106 /// ``` 107 fn unchecked_offset_from(&self, base: Self) -> Self::V { 108 self.raw_value() - base.raw_value() 109 } 110 111 /// Returns self, aligned to the given power of two. 112 fn checked_align_up(&self, power_of_two: Self::V) -> Option<Self> { 113 let mask = power_of_two - Self::one(); 114 assert_ne!(power_of_two, Self::zero()); 115 assert_eq!(power_of_two & mask, Self::zero()); 116 self.checked_add(mask).map(|x| x & !mask) 117 } 118 119 /// Returns self, aligned to the given power of two. 120 /// Only use this when the result is guaranteed not to overflow. 121 fn unchecked_align_up(&self, power_of_two: Self::V) -> Self { 122 let mask = power_of_two - Self::one(); 123 self.unchecked_add(mask) & !mask 124 } 125 126 /// Computes `self + other`, returning `None` if overflow occurred. 127 fn checked_add(&self, other: Self::V) -> Option<Self>; 128 129 /// Computes `self + other`. 130 /// 131 /// Returns a tuple of the addition result along with a boolean indicating whether an arithmetic 132 /// overflow would occur. If an overflow would have occurred then the wrapped address 133 /// is returned. 134 fn overflowing_add(&self, other: Self::V) -> (Self, bool); 135 136 /// Computes `self + offset`. 137 /// 138 /// In the event of overflow, follows standard Rust behavior, i.e. panic in debug builds, 139 /// silently wrap in release builds. 140 /// 141 /// Note that, unlike the `unchecked_*` methods in std, this method never invokes undefined 142 /// behavior.. 143 fn unchecked_add(&self, offset: Self::V) -> Self; 144 145 /// Subtracts two addresses, checking for underflow. If underflow happens, `None` is returned. 146 fn checked_sub(&self, other: Self::V) -> Option<Self>; 147 148 /// Computes `self - other`. 149 /// 150 /// Returns a tuple of the subtraction result along with a boolean indicating whether an 151 /// arithmetic overflow would occur. If an overflow would have occurred then the wrapped 152 /// address is returned. 153 fn overflowing_sub(&self, other: Self::V) -> (Self, bool); 154 155 /// Computes `self - other`. 156 /// 157 /// In the event of underflow, follows standard Rust behavior, i.e. panic in debug builds, 158 /// silently wrap in release builds. 159 /// 160 /// Note that, unlike the `unchecked_*` methods in std, this method never invokes undefined 161 /// behavior. 162 fn unchecked_sub(&self, other: Self::V) -> Self; 163 } 164 165 macro_rules! impl_address_ops { 166 ($T:ident, $V:ty) => { 167 impl AddressValue for $T { 168 type V = $V; 169 } 170 171 impl Address for $T { 172 fn new(value: $V) -> $T { 173 $T(value) 174 } 175 176 fn raw_value(&self) -> $V { 177 self.0 178 } 179 180 fn checked_offset_from(&self, base: $T) -> Option<$V> { 181 self.0.checked_sub(base.0) 182 } 183 184 fn checked_add(&self, other: $V) -> Option<$T> { 185 self.0.checked_add(other).map($T) 186 } 187 188 fn overflowing_add(&self, other: $V) -> ($T, bool) { 189 let (t, ovf) = self.0.overflowing_add(other); 190 ($T(t), ovf) 191 } 192 193 fn unchecked_add(&self, offset: $V) -> $T { 194 $T(self.0 + offset) 195 } 196 197 fn checked_sub(&self, other: $V) -> Option<$T> { 198 self.0.checked_sub(other).map($T) 199 } 200 201 fn overflowing_sub(&self, other: $V) -> ($T, bool) { 202 let (t, ovf) = self.0.overflowing_sub(other); 203 ($T(t), ovf) 204 } 205 206 fn unchecked_sub(&self, other: $V) -> $T { 207 $T(self.0 - other) 208 } 209 } 210 211 impl Default for $T { 212 fn default() -> $T { 213 Self::new(0 as $V) 214 } 215 } 216 217 impl BitAnd<$V> for $T { 218 type Output = $T; 219 220 fn bitand(self, other: $V) -> $T { 221 $T(self.0 & other) 222 } 223 } 224 225 impl BitOr<$V> for $T { 226 type Output = $T; 227 228 fn bitor(self, other: $V) -> $T { 229 $T(self.0 | other) 230 } 231 } 232 }; 233 } 234 235 #[cfg(test)] 236 mod tests { 237 use super::*; 238 239 #[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)] 240 struct MockAddress(pub u64); 241 impl_address_ops!(MockAddress, u64); 242 243 #[test] 244 fn test_new() { 245 assert_eq!(MockAddress::new(0), MockAddress(0)); 246 assert_eq!(MockAddress::new(std::u64::MAX), MockAddress(std::u64::MAX)); 247 } 248 249 #[test] 250 fn test_offset_from() { 251 let base = MockAddress(0x100); 252 let addr = MockAddress(0x150); 253 assert_eq!(addr.unchecked_offset_from(base), 0x50u64); 254 assert_eq!(addr.checked_offset_from(base), Some(0x50u64)); 255 assert_eq!(base.checked_offset_from(addr), None); 256 } 257 258 #[test] 259 fn test_equals() { 260 let a = MockAddress(0x300); 261 let b = MockAddress(0x300); 262 let c = MockAddress(0x301); 263 assert_eq!(a, MockAddress(a.raw_value())); 264 assert_eq!(a, b); 265 assert_eq!(b, a); 266 assert_ne!(a, c); 267 assert_ne!(c, a); 268 } 269 270 #[test] 271 fn test_cmp() { 272 let a = MockAddress(0x300); 273 let b = MockAddress(0x301); 274 assert!(a < b); 275 } 276 277 #[test] 278 fn test_checked_align_up() { 279 assert_eq!( 280 MockAddress::new(0x128).checked_align_up(8), 281 Some(MockAddress(0x128)) 282 ); 283 assert_eq!( 284 MockAddress::new(0x128).checked_align_up(16), 285 Some(MockAddress(0x130)) 286 ); 287 assert_eq!( 288 MockAddress::new(std::u64::MAX - 0x3fff).checked_align_up(0x10000), 289 None 290 ); 291 } 292 293 #[test] 294 #[should_panic] 295 fn test_checked_align_up_invalid() { 296 let _ = MockAddress::new(0x128).checked_align_up(12); 297 } 298 299 #[test] 300 fn test_unchecked_align_up() { 301 assert_eq!( 302 MockAddress::new(0x128).unchecked_align_up(8), 303 MockAddress(0x128) 304 ); 305 assert_eq!( 306 MockAddress::new(0x128).unchecked_align_up(16), 307 MockAddress(0x130) 308 ); 309 } 310 311 #[test] 312 fn test_mask() { 313 let a = MockAddress(0x5050); 314 assert_eq!(MockAddress(0x5000), a & 0xff00u64); 315 assert_eq!(0x5000, a.mask(0xff00u64)); 316 assert_eq!(MockAddress(0x5055), a | 0x0005u64); 317 } 318 319 fn check_add(a: u64, b: u64, expected_overflow: bool, expected_result: u64) { 320 assert_eq!( 321 (MockAddress(expected_result), expected_overflow), 322 MockAddress(a).overflowing_add(b) 323 ); 324 if expected_overflow { 325 assert!(MockAddress(a).checked_add(b).is_none()); 326 #[cfg(debug_assertions)] 327 assert!(std::panic::catch_unwind(|| MockAddress(a).unchecked_add(b)).is_err()); 328 } else { 329 assert_eq!( 330 Some(MockAddress(expected_result)), 331 MockAddress(a).checked_add(b) 332 ); 333 assert_eq!( 334 MockAddress(expected_result), 335 MockAddress(a).unchecked_add(b) 336 ); 337 } 338 } 339 340 #[test] 341 fn test_add() { 342 // without overflow 343 // normal case 344 check_add(10, 10, false, 20); 345 // edge case 346 check_add(std::u64::MAX - 1, 1, false, std::u64::MAX); 347 348 // with overflow 349 check_add(std::u64::MAX, 1, true, 0); 350 } 351 352 fn check_sub(a: u64, b: u64, expected_overflow: bool, expected_result: u64) { 353 assert_eq!( 354 (MockAddress(expected_result), expected_overflow), 355 MockAddress(a).overflowing_sub(b) 356 ); 357 if expected_overflow { 358 assert!(MockAddress(a).checked_sub(b).is_none()); 359 assert!(MockAddress(a).checked_offset_from(MockAddress(b)).is_none()); 360 #[cfg(debug_assertions)] 361 assert!(std::panic::catch_unwind(|| MockAddress(a).unchecked_sub(b)).is_err()); 362 } else { 363 assert_eq!( 364 Some(MockAddress(expected_result)), 365 MockAddress(a).checked_sub(b) 366 ); 367 assert_eq!( 368 Some(expected_result), 369 MockAddress(a).checked_offset_from(MockAddress(b)) 370 ); 371 assert_eq!( 372 MockAddress(expected_result), 373 MockAddress(a).unchecked_sub(b) 374 ); 375 } 376 } 377 378 #[test] 379 fn test_sub() { 380 // without overflow 381 // normal case 382 check_sub(20, 10, false, 10); 383 // edge case 384 check_sub(1, 1, false, 0); 385 386 // with underflow 387 check_sub(0, 1, true, std::u64::MAX); 388 } 389 390 #[test] 391 fn test_default() { 392 assert_eq!(MockAddress::default(), MockAddress(0)); 393 } 394 395 #[test] 396 fn test_bit_and() { 397 let a = MockAddress(0x0ff0); 398 assert_eq!(a & 0xf00f, MockAddress(0)); 399 } 400 401 #[test] 402 fn test_bit_or() { 403 let a = MockAddress(0x0ff0); 404 assert_eq!(a | 0xf00f, MockAddress(0xffff)); 405 } 406 } 407