1 /*
   2  * Copyright 2002 Sun Microsystems, Inc.  All Rights Reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  20  * CA 95054 USA or visit www.sun.com if you need additional information or
  21  * have any questions.
  22  *  
  23  */
  24 
  25 package sun.jvm.hotspot.debugger.windbg;
  26 
  27 import sun.jvm.hotspot.debugger.*;
  28 
  29 class WindbgAddress implements Address {
  30   protected WindbgDebugger debugger;
  31   protected long addr;
  32 
  33   WindbgAddress(WindbgDebugger debugger, long addr) {
  34     this.debugger = debugger;
  35     this.addr = addr;
  36   }
  37 
  38   //
  39   // Basic Java routines
  40   //
  41 
  42   public boolean equals(Object arg) {
  43     if (arg == null) {
  44       return false;
  45     }
  46 
  47     if (!(arg instanceof WindbgAddress)) {
  48       return false;
  49     }
  50 
  51     return (addr == ((WindbgAddress) arg).addr);
  52   }
  53 
  54   public int hashCode() {
  55     // FIXME: suggestions on a better hash code?
  56     return (int) addr;
  57   }
  58 
  59   public String toString() {
  60     return debugger.addressValueToString(addr);
  61   }
  62 
  63   //
  64   // C/C++-related routines
  65   //
  66 
  67   public long getCIntegerAt(long offset, long numBytes, boolean isUnsigned) throws UnalignedAddressException, UnmappedAddressException {
  68     return debugger.readCInteger(addr + offset, numBytes, isUnsigned);
  69   }
  70 
  71   public Address getAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  72     return debugger.readAddress(addr + offset);
  73   }
  74 
  75   //
  76   // Java-related routines
  77   //
  78 
  79   public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  80     return debugger.readJBoolean(addr + offset);
  81   }
  82 
  83   public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  84     return debugger.readJByte(addr + offset);
  85   }
  86 
  87   public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  88     return debugger.readJChar(addr + offset);
  89   }
  90 
  91   public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  92     return debugger.readJDouble(addr + offset);
  93   }
  94 
  95   public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  96     return debugger.readJFloat(addr + offset);
  97   }
  98 
  99   public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 100     return debugger.readJInt(addr + offset);
 101   }
 102 
 103   public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 104     return debugger.readJLong(addr + offset);
 105   }
 106 
 107   public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 108     return debugger.readJShort(addr + offset);
 109   }
 110 
 111   public OopHandle getOopHandleAt(long offset)
 112     throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
 113     return debugger.readOopHandle(addr + offset);
 114   }
 115 
 116   //
 117   // C/C++-related mutators
 118   //
 119 
 120   public void setCIntegerAt(long offset, long numBytes, long value) {
 121     throw new DebuggerException("Unimplemented");
 122   }
 123   public void setAddressAt(long offset, Address value) {
 124     throw new DebuggerException("Unimplemented");
 125   }
 126 
 127   //
 128   // Java-related mutators
 129   //
 130 
 131   // Mutators -- not implemented for now (FIXME)
 132   public void       setJBooleanAt      (long offset, boolean value)
 133     throws UnmappedAddressException, UnalignedAddressException {
 134     throw new DebuggerException("Unimplemented");
 135   }
 136   public void       setJByteAt         (long offset, byte value)
 137     throws UnmappedAddressException, UnalignedAddressException {
 138     throw new DebuggerException("Unimplemented");
 139   }
 140   public void       setJCharAt         (long offset, char value)
 141     throws UnmappedAddressException, UnalignedAddressException {
 142     throw new DebuggerException("Unimplemented");
 143   }
 144   public void       setJDoubleAt       (long offset, double value)
 145     throws UnmappedAddressException, UnalignedAddressException {
 146     throw new DebuggerException("Unimplemented");
 147   }
 148   public void       setJFloatAt        (long offset, float value)
 149     throws UnmappedAddressException, UnalignedAddressException {
 150     throw new DebuggerException("Unimplemented");
 151   }
 152   public void       setJIntAt          (long offset, int value)
 153     throws UnmappedAddressException, UnalignedAddressException {
 154     throw new DebuggerException("Unimplemented");
 155   }
 156   public void       setJLongAt         (long offset, long value)
 157     throws UnmappedAddressException, UnalignedAddressException {
 158     throw new DebuggerException("Unimplemented");
 159   }
 160   public void       setJShortAt        (long offset, short value)
 161     throws UnmappedAddressException, UnalignedAddressException {
 162     throw new DebuggerException("Unimplemented");
 163   }
 164   public void       setOopHandleAt     (long offset, OopHandle value)
 165     throws UnmappedAddressException, UnalignedAddressException {
 166     throw new DebuggerException("Unimplemented");
 167   }
 168 
 169   //
 170   // Arithmetic operations -- necessary evil.
 171   //
 172 
 173   public Address    addOffsetTo       (long offset) throws UnsupportedOperationException {
 174     long value = addr + offset;
 175     if (value == 0) {
 176       return null;
 177     }
 178     return new WindbgAddress(debugger, value);
 179   }
 180 
 181   public OopHandle  addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException {
 182     long value = addr + offset;
 183     if (value == 0) {
 184       return null;
 185     }
 186     return new WindbgOopHandle(debugger, value);
 187   }
 188 
 189   /** (FIXME: any signed/unsigned issues? Should this work for
 190       OopHandles?) */
 191   public long       minus(Address arg) {
 192     if (arg == null) {
 193       return addr;
 194     }
 195     return addr - ((WindbgAddress) arg).addr;
 196   }
 197 
 198   // Two's complement representation.
 199   // All negative numbers are larger than positive numbers.
 200   // Numbers with the same sign can be compared normally.
 201   // Test harness is below in main().
 202 
 203   public boolean    lessThan          (Address a) {
 204     if (a == null) {
 205       return false;
 206     }
 207     WindbgAddress arg = (WindbgAddress) a;
 208     if ((addr >= 0) && (arg.addr < 0)) {
 209       return true;
 210     }
 211     if ((addr < 0) && (arg.addr >= 0)) {
 212       return false;
 213     }
 214     return (addr < arg.addr);
 215   }
 216 
 217   public boolean    lessThanOrEqual   (Address a) {
 218     if (a == null) {
 219       return false;
 220     }
 221     WindbgAddress arg = (WindbgAddress) a;
 222     if ((addr >= 0) && (arg.addr < 0)) {
 223       return true;
 224     }
 225     if ((addr < 0) && (arg.addr >= 0)) {
 226       return false;
 227     }
 228     return (addr <= arg.addr);
 229   }
 230 
 231   public boolean    greaterThan       (Address a) {
 232     if (a == null) {
 233       return true;
 234     }
 235     WindbgAddress arg = (WindbgAddress) a;
 236     if ((addr >= 0) && (arg.addr < 0)) {
 237       return false;
 238     }
 239     if ((addr < 0) && (arg.addr >= 0)) {
 240       return true;
 241     }
 242     return (addr > arg.addr);
 243   }
 244 
 245   public boolean    greaterThanOrEqual(Address a) {
 246     if (a == null) {
 247       return true;
 248     }
 249     WindbgAddress arg = (WindbgAddress) a;
 250     if ((addr >= 0) && (arg.addr < 0)) {
 251       return false;
 252     }
 253     if ((addr < 0) && (arg.addr >= 0)) {
 254       return true;
 255     }
 256     return (addr >= arg.addr);
 257   }
 258 
 259   public Address    andWithMask(long mask) throws UnsupportedOperationException {
 260     long value = addr & mask;
 261     if (value == 0) {
 262       return null;
 263     }
 264     return new WindbgAddress(debugger, value);
 265   }
 266 
 267   public Address    orWithMask(long mask) throws UnsupportedOperationException {
 268     long value = addr | mask;
 269     if (value == 0) {
 270       return null;
 271     }
 272     return new WindbgAddress(debugger, value);
 273   }
 274 
 275   public Address    xorWithMask(long mask) throws UnsupportedOperationException {
 276     long value = addr ^ mask;
 277     if (value == 0) {
 278       return null;
 279     }
 280     return new WindbgAddress(debugger, value);
 281   }
 282 
 283 
 284   //--------------------------------------------------------------------------------
 285   // Internals only below this point
 286   //
 287 
 288   long getValue() {
 289     return addr;
 290   }
 291 
 292 
 293   private static void check(boolean arg, String failMessage) {
 294     if (!arg) {
 295       System.err.println(failMessage + ": FAILED");
 296       System.exit(1);
 297     }
 298   }
 299 
 300   // Test harness
 301   public static void main(String[] args) {
 302     // p/n indicates whether the interior address is really positive
 303     // or negative. In unsigned terms, p1 < p2 < n1 < n2.
 304 
 305     WindbgAddress p1 = new WindbgAddress(null, 0x7FFFFFFFFFFFFFF0L);
 306     WindbgAddress p2 = (WindbgAddress) p1.addOffsetTo(10);
 307     WindbgAddress n1 = (WindbgAddress) p2.addOffsetTo(10);
 308     WindbgAddress n2 = (WindbgAddress) n1.addOffsetTo(10);
 309     
 310     // lessThan positive tests
 311     check(p1.lessThan(p2), "lessThan 1");
 312     check(p1.lessThan(n1), "lessThan 2");
 313     check(p1.lessThan(n2), "lessThan 3");
 314     check(p2.lessThan(n1), "lessThan 4");
 315     check(p2.lessThan(n2), "lessThan 5");
 316     check(n1.lessThan(n2), "lessThan 6");
 317 
 318     // lessThan negative tests
 319     check(!p1.lessThan(p1), "lessThan 7");
 320     check(!p2.lessThan(p2), "lessThan 8");
 321     check(!n1.lessThan(n1), "lessThan 9");
 322     check(!n2.lessThan(n2), "lessThan 10");
 323 
 324     check(!p2.lessThan(p1), "lessThan 11");
 325     check(!n1.lessThan(p1), "lessThan 12");
 326     check(!n2.lessThan(p1), "lessThan 13");
 327     check(!n1.lessThan(p2), "lessThan 14");
 328     check(!n2.lessThan(p2), "lessThan 15");
 329     check(!n2.lessThan(n1), "lessThan 16");
 330 
 331     // lessThanOrEqual positive tests
 332     check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1");
 333     check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2");
 334     check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3");
 335     check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4");
 336 
 337     check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5");
 338     check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6");
 339     check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7");
 340     check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8");
 341     check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9");
 342     check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10");
 343 
 344     // lessThanOrEqual negative tests
 345     check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11");
 346     check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12");
 347     check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13");
 348     check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14");
 349     check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15");
 350     check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16");
 351 
 352     // greaterThan positive tests
 353     check(n2.greaterThan(p1), "greaterThan 1");
 354     check(n2.greaterThan(p2), "greaterThan 2");
 355     check(n2.greaterThan(n1), "greaterThan 3");
 356     check(n1.greaterThan(p1), "greaterThan 4");
 357     check(n1.greaterThan(p2), "greaterThan 5");
 358     check(p2.greaterThan(p1), "greaterThan 6");
 359 
 360     // greaterThan negative tests
 361     check(!p1.greaterThan(p1), "greaterThan 7");
 362     check(!p2.greaterThan(p2), "greaterThan 8");
 363     check(!n1.greaterThan(n1), "greaterThan 9");
 364     check(!n2.greaterThan(n2), "greaterThan 10");
 365 
 366     check(!p1.greaterThan(n2), "greaterThan 11");
 367     check(!p2.greaterThan(n2), "greaterThan 12");
 368     check(!n1.greaterThan(n2), "greaterThan 13");
 369     check(!p1.greaterThan(n1), "greaterThan 14");
 370     check(!p2.greaterThan(n1), "greaterThan 15");
 371     check(!p1.greaterThan(p2), "greaterThan 16");
 372     
 373     // greaterThanOrEqual positive tests
 374     check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1");
 375     check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2");
 376     check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3");
 377     check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4");
 378     
 379     check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5");
 380     check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6");
 381     check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7");
 382     check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8");
 383     check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9");
 384     check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10");
 385 
 386     // greaterThanOrEqual negative tests
 387     check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11");
 388     check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12");
 389     check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13");
 390     check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14");
 391     check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15");
 392     check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16");
 393 
 394     System.err.println("WindbgAddress: all tests passed successfully.");
 395   }
 396 }