lpus/src/address.rs
2020-07-02 02:47:15 +07:00

178 lines
4.3 KiB
Rust

use std::cmp::Ordering;
use std::fmt;
use std::ops::{Add, AddAssign, Sub, SubAssign};
use std::rc::Rc;
// pub struct Object {
// name: String,
// address: Address
// }
//
// impl Object {
// pub fn get<F>(&self, resolver: &F) -> u64
// where F: Fn(u64) -> u64 {
// // this function returns address of Object
// self.address.get(resolver)
// }
// }
pub struct Address {
base: u64,
pointer: Option<Rc<Address>>,
offset: u64,
// TODO: resolver
// It would be nice to have an address resolver
// Then implement Deref trait to call get()
// resolver uses DriverState address decompose
// lifetime issue occur
}
impl Address {
pub fn from_base(base: u64) -> Self {
Address {
base: base,
pointer: None,
offset: 0,
}
}
pub fn from_ptr(pointer: Address) -> Self {
Address {
base: 0,
pointer: Some(Rc::new(pointer)),
offset: 0,
}
}
fn deref<F>(&self, resolver: &F) -> Address
where
F: Fn(u64) -> u64,
{
match &self.pointer {
Some(p) => {
let addr = p.deref(resolver);
// println!("deref: {} -> {}; resolve: 0x{:x}", self, addr, addr.base + addr.offset);
let base = if addr.base != 0 {
resolver(addr.base + addr.offset)
} else {
0
};
Address {
base: base,
pointer: None,
offset: self.offset,
}
}
None => Address {
base: self.base,
pointer: None,
offset: self.offset,
},
}
}
pub fn get<F>(&self, resolver: &F) -> u64
where
F: Fn(u64) -> u64,
{
if self.pointer.is_some() {
self.deref(resolver).get(resolver)
} else if self.base == 0 {
0
} else {
self.base + self.offset
}
}
pub fn address(&self) -> u64 {
self.base + self.offset
}
// pub fn to(&self, name: &str) -> Object {
// Object {
// name: name.to_string(),
// address: self.clone()
// }
// }
}
impl Add<u64> for Address {
type Output = Self;
fn add(self, other: u64) -> Self {
Self {
base: self.base,
pointer: self.pointer.map(|p| Rc::clone(&p)),
offset: self.offset + other,
}
}
}
impl AddAssign<u64> for Address {
fn add_assign(&mut self, other: u64) {
*self = Self {
base: self.base,
pointer: self.pointer.clone(),
offset: self.offset + other,
}
}
}
impl Sub<u64> for Address {
type Output = Self;
fn sub(self, other: u64) -> Self {
Self {
base: self.base,
pointer: self.pointer.map(|p| Rc::clone(&p)),
offset: self.offset - other,
}
}
}
impl SubAssign<u64> for Address {
fn sub_assign(&mut self, other: u64) {
*self = Self {
base: self.base,
pointer: self.pointer.clone(),
offset: self.offset - other,
}
}
}
impl PartialEq for Address {
fn eq(&self, other: &Self) -> bool {
self.pointer.is_none()
&& other.pointer.is_none()
&& self.base == other.base
&& self.offset == other.offset
}
}
impl PartialOrd for Address {
fn partial_cmp(&self, other: &Address) -> Option<Ordering> {
if self.pointer.is_some() || other.pointer.is_some() {
None
} else {
let this = self.base + self.offset;
let that = other.base + other.offset;
Some(this.cmp(&that))
}
}
}
impl fmt::Display for Address {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(p) = &self.pointer {
write!(f, "*({}) + 0x{:x}", *p, self.offset)
} else if self.offset != 0 {
write!(f, "0x{:x} + 0x{:x}", self.base, self.offset)
} else {
write!(f, "0x{:x}", self.base)
}
}
}
impl Clone for Address {
fn clone(&self) -> Self {
Address {
base: self.base,
pointer: self.pointer.clone(),
offset: self.offset,
}
}
}