1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
|
using System;
namespace Mono.Debugger
{
// <summary>
// This is used to store an address in the target's address space.
// Addresses are only valid in the target that was used to get them.
//
// You should always use this struct to pass addresses around, it is a
// valuetype and has operators to compare, add, increment, decrement
// addresses.
//
// Note that it is not allowed to compare addresses from different
// targets, you'll get an ArgumentException() if you attempt to do so.
// This is also the reason why you should never use the `Address' property
// unless you know exactly what you're doing: by using this whole valuetype
// to pass addresses around, it'll protect you against accidentally using
// an address in another target.
// </summary>
[Serializable]
public struct TargetAddress : IComparable
{
private ulong address;
private AddressDomain domain;
// <remarks>
// Don't use this in a comparision, use IsNull instead.
// (TargetAddress.Null is in the null domain and comparision between
// different domains is not allowed).
// </remarks>
public static TargetAddress Null = new TargetAddress (AddressDomain.Global, 0);
// <summary>
// This is not what it looks like.
// Never use this constructor unless you know exactly what you're doing.
// </summary>
public TargetAddress (AddressDomain domain, long address)
{
this.domain = domain;
// FIXME: hack
// address &= 0x00000000ffffffffL;
this.address = (ulong) address;
}
// <summary>
// This is not what it looks like.
// Never use this property unless you know exactly what you're doing.
// </summary>
public long Address {
get {
return (long) address;
}
}
// <summary>
// The `domain' in which this address lives.
// Normally, this is in instance of the IInferior object, but it can also
// be anything else. It is used to ensure that addresses are only used in
// the domain they came from.
// </summary>
public AddressDomain Domain {
get {
return domain;
}
}
// <summary>
// Use this to check whether an address is null.
// </summary>
public bool IsNull {
get {
return (address == 0) && (domain.IsGlobal);
}
}
public override string ToString ()
{
return String.Format ("0x{0}", FormatAddress ((long) address));
}
public static string FormatAddress (long address)
{
int bits = 8;
string saddr = address.ToString ("x");
for (int i = saddr.Length; i < bits; i++)
saddr = "0" + saddr;
return saddr;
}
static void check_domains (TargetAddress a, TargetAddress b)
{
if (a.domain.Equals (b.domain))
return;
throw new ArgumentException (String.Format (
"Cannot compare addresses from different domains {0} and {1}",
a.Domain, b.Domain));
}
public int CompareTo (object obj)
{
TargetAddress addr = (TargetAddress) obj;
check_domains (addr, this);
if (address < addr.address)
return -1;
else if (address > addr.address)
return 1;
else
return 0;
}
public override bool Equals (object o)
{
if (o == null || !(o is TargetAddress))
return false;
TargetAddress b = (TargetAddress)o;
return address == b.address;
}
public override int GetHashCode ()
{
return (int)address;
}
//
// Operators
//
public static bool operator < (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.address < b.address;
}
public static bool operator > (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.address > b.address;
}
public static bool operator == (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.Equals (b);
}
public static bool operator != (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.address != b.address;
}
public static bool operator <= (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.address <= b.address;
}
public static bool operator >= (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
return a.address >= b.address;
}
public static TargetAddress operator + (TargetAddress a, long offset)
{
return new TargetAddress (a.domain, (long) (a.address + (ulong) offset));
}
public static TargetAddress operator - (TargetAddress a, long offset)
{
return new TargetAddress (a.domain, (long) (a.address - (ulong) offset));
}
public static TargetAddress operator ++ (TargetAddress a)
{
a.address++;
return a;
}
public static TargetAddress operator -- (TargetAddress a)
{
a.address--;
return a;
}
public static long operator - (TargetAddress a, TargetAddress b)
{
check_domains (a, b);
if (a > b)
return (long) (a.address - b.address);
else
return - (long) (b.address - a.address);
}
}
}
|