use crate::debugger::debugee::Debugee;
use crate::debugger::debugee::dwarf::DebugInformation;
use crate::debugger::error::Error;
use gimli::Range;
use std::fmt::{Display, Formatter};
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug, Default, PartialOrd, Ord)]
pub struct RelocatedAddress(usize);
impl RelocatedAddress {
#[inline(always)]
pub fn remove_vas_region_offset(self, offset: usize) -> GlobalAddress {
GlobalAddress(self.0 - offset)
}
pub fn into_global(self, debugee: &Debugee) -> Result<GlobalAddress, Error> {
Ok(self.remove_vas_region_offset(debugee.mapping_offset_for_pc(self)?))
}
#[inline(always)]
pub fn offset(self, offset: isize) -> RelocatedAddress {
if offset >= 0 {
self.0 + offset as usize
} else {
self.0 - offset.unsigned_abs()
}
.into()
}
#[inline(always)]
pub fn as_u64(self) -> u64 {
u64::from(self)
}
#[inline(always)]
pub fn as_usize(self) -> usize {
usize::from(self)
}
}
impl From<usize> for RelocatedAddress {
fn from(addr: usize) -> Self {
RelocatedAddress(addr)
}
}
impl From<u64> for RelocatedAddress {
fn from(addr: u64) -> Self {
RelocatedAddress(addr as usize)
}
}
impl From<RelocatedAddress> for usize {
fn from(addr: RelocatedAddress) -> Self {
addr.0
}
}
impl From<RelocatedAddress> for u64 {
fn from(addr: RelocatedAddress) -> Self {
addr.0 as u64
}
}
impl Display for RelocatedAddress {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:#016X}", self.0))
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Debug, Default, Ord)]
pub struct GlobalAddress(usize);
impl GlobalAddress {
fn relocate(self, offset: usize) -> RelocatedAddress {
RelocatedAddress(self.0 + offset)
}
pub fn relocate_to_segment(
self,
debugee: &Debugee,
segment: &DebugInformation,
) -> Result<RelocatedAddress, Error> {
let offset = debugee.mapping_offset_for_file(segment)?;
Ok(self.relocate(offset))
}
pub fn relocate_to_segment_by_pc(
self,
debugee: &Debugee,
pc: RelocatedAddress,
) -> Result<RelocatedAddress, Error> {
let offset = debugee.mapping_offset_for_pc(pc)?;
Ok(self.relocate(offset))
}
pub fn in_range(self, range: &Range) -> bool {
u64::from(self) >= range.begin && u64::from(self) < range.end
}
pub fn in_ranges(self, ranges: &[Range]) -> bool {
ranges.iter().any(|range| self.in_range(range))
}
}
impl From<usize> for GlobalAddress {
fn from(addr: usize) -> Self {
GlobalAddress(addr)
}
}
impl From<u64> for GlobalAddress {
fn from(addr: u64) -> Self {
GlobalAddress(addr as usize)
}
}
impl Display for GlobalAddress {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{:#016X}", self.0))
}
}
impl From<GlobalAddress> for usize {
fn from(addr: GlobalAddress) -> Self {
addr.0
}
}
impl From<GlobalAddress> for u64 {
fn from(addr: GlobalAddress) -> Self {
addr.0 as u64
}
}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
pub enum Address {
Relocated(RelocatedAddress),
Global(GlobalAddress),
}
impl Display for Address {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Address::Relocated(addr) => addr.fmt(f),
Address::Global(addr) => addr.fmt(f),
}
}
}