1 /*
   2  * Copyright (c) 2002, 2008, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * 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   public Address getCompOopAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  76     return debugger.readCompOopAddress(addr + offset);
  77   }
  78 
  79   public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  80     return debugger.readCompKlassAddress(addr + offset);
  81   }
  82 
  83   //
  84   // Java-related routines
  85   //
  86 
  87   public boolean getJBooleanAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  88     return debugger.readJBoolean(addr + offset);
  89   }
  90 
  91   public byte getJByteAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  92     return debugger.readJByte(addr + offset);
  93   }
  94 
  95   public char getJCharAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
  96     return debugger.readJChar(addr + offset);
  97   }
  98 
  99   public double getJDoubleAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 100     return debugger.readJDouble(addr + offset);
 101   }
 102 
 103   public float getJFloatAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 104     return debugger.readJFloat(addr + offset);
 105   }
 106 
 107   public int getJIntAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 108     return debugger.readJInt(addr + offset);
 109   }
 110 
 111   public long getJLongAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 112     return debugger.readJLong(addr + offset);
 113   }
 114 
 115   public short getJShortAt(long offset) throws UnalignedAddressException, UnmappedAddressException {
 116     return debugger.readJShort(addr + offset);
 117   }
 118 
 119   public OopHandle getOopHandleAt(long offset)
 120     throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
 121     return debugger.readOopHandle(addr + offset);
 122   }
 123 
 124   public OopHandle getCompOopHandleAt(long offset)
 125     throws UnalignedAddressException, UnmappedAddressException, NotInHeapException {
 126     return debugger.readCompOopHandle(addr + offset);
 127   }
 128   //
 129   // C/C++-related mutators
 130   //
 131 
 132   public void setCIntegerAt(long offset, long numBytes, long value) {
 133     throw new DebuggerException("Unimplemented");
 134   }
 135   public void setAddressAt(long offset, Address value) {
 136     throw new DebuggerException("Unimplemented");
 137   }
 138 
 139   //
 140   // Java-related mutators
 141   //
 142 
 143   // Mutators -- not implemented for now (FIXME)
 144   public void       setJBooleanAt      (long offset, boolean value)
 145     throws UnmappedAddressException, UnalignedAddressException {
 146     throw new DebuggerException("Unimplemented");
 147   }
 148   public void       setJByteAt         (long offset, byte value)
 149     throws UnmappedAddressException, UnalignedAddressException {
 150     throw new DebuggerException("Unimplemented");
 151   }
 152   public void       setJCharAt         (long offset, char value)
 153     throws UnmappedAddressException, UnalignedAddressException {
 154     throw new DebuggerException("Unimplemented");
 155   }
 156   public void       setJDoubleAt       (long offset, double value)
 157     throws UnmappedAddressException, UnalignedAddressException {
 158     throw new DebuggerException("Unimplemented");
 159   }
 160   public void       setJFloatAt        (long offset, float value)
 161     throws UnmappedAddressException, UnalignedAddressException {
 162     throw new DebuggerException("Unimplemented");
 163   }
 164   public void       setJIntAt          (long offset, int value)
 165     throws UnmappedAddressException, UnalignedAddressException {
 166     throw new DebuggerException("Unimplemented");
 167   }
 168   public void       setJLongAt         (long offset, long value)
 169     throws UnmappedAddressException, UnalignedAddressException {
 170     throw new DebuggerException("Unimplemented");
 171   }
 172   public void       setJShortAt        (long offset, short value)
 173     throws UnmappedAddressException, UnalignedAddressException {
 174     throw new DebuggerException("Unimplemented");
 175   }
 176   public void       setOopHandleAt     (long offset, OopHandle value)
 177     throws UnmappedAddressException, UnalignedAddressException {
 178     throw new DebuggerException("Unimplemented");
 179   }
 180 
 181   //
 182   // Arithmetic operations -- necessary evil.
 183   //
 184 
 185   public Address    addOffsetTo       (long offset) throws UnsupportedOperationException {
 186     long value = addr + offset;
 187     if (value == 0) {
 188       return null;
 189     }
 190     return new WindbgAddress(debugger, value);
 191   }
 192 
 193   public OopHandle  addOffsetToAsOopHandle(long offset) throws UnsupportedOperationException {
 194     long value = addr + offset;
 195     if (value == 0) {
 196       return null;
 197     }
 198     return new WindbgOopHandle(debugger, value);
 199   }
 200 
 201   /** (FIXME: any signed/unsigned issues? Should this work for
 202       OopHandles?) */
 203   public long       minus(Address arg) {
 204     if (arg == null) {
 205       return addr;
 206     }
 207     return addr - ((WindbgAddress) arg).addr;
 208   }
 209 
 210   // Two's complement representation.
 211   // All negative numbers are larger than positive numbers.
 212   // Numbers with the same sign can be compared normally.
 213   // Test harness is below in main().
 214 
 215   public boolean    lessThan          (Address a) {
 216     if (a == null) {
 217       return false;
 218     }
 219     WindbgAddress arg = (WindbgAddress) a;
 220     if ((addr >= 0) && (arg.addr < 0)) {
 221       return true;
 222     }
 223     if ((addr < 0) && (arg.addr >= 0)) {
 224       return false;
 225     }
 226     return (addr < arg.addr);
 227   }
 228 
 229   public boolean    lessThanOrEqual   (Address a) {
 230     if (a == null) {
 231       return false;
 232     }
 233     WindbgAddress arg = (WindbgAddress) a;
 234     if ((addr >= 0) && (arg.addr < 0)) {
 235       return true;
 236     }
 237     if ((addr < 0) && (arg.addr >= 0)) {
 238       return false;
 239     }
 240     return (addr <= arg.addr);
 241   }
 242 
 243   public boolean    greaterThan       (Address a) {
 244     if (a == null) {
 245       return true;
 246     }
 247     WindbgAddress arg = (WindbgAddress) a;
 248     if ((addr >= 0) && (arg.addr < 0)) {
 249       return false;
 250     }
 251     if ((addr < 0) && (arg.addr >= 0)) {
 252       return true;
 253     }
 254     return (addr > arg.addr);
 255   }
 256 
 257   public boolean    greaterThanOrEqual(Address a) {
 258     if (a == null) {
 259       return true;
 260     }
 261     WindbgAddress arg = (WindbgAddress) a;
 262     if ((addr >= 0) && (arg.addr < 0)) {
 263       return false;
 264     }
 265     if ((addr < 0) && (arg.addr >= 0)) {
 266       return true;
 267     }
 268     return (addr >= arg.addr);
 269   }
 270 
 271   public Address    andWithMask(long mask) throws UnsupportedOperationException {
 272     long value = addr & mask;
 273     if (value == 0) {
 274       return null;
 275     }
 276     return new WindbgAddress(debugger, value);
 277   }
 278 
 279   public Address    orWithMask(long mask) throws UnsupportedOperationException {
 280     long value = addr | mask;
 281     if (value == 0) {
 282       return null;
 283     }
 284     return new WindbgAddress(debugger, value);
 285   }
 286 
 287   public Address    xorWithMask(long mask) throws UnsupportedOperationException {
 288     long value = addr ^ mask;
 289     if (value == 0) {
 290       return null;
 291     }
 292     return new WindbgAddress(debugger, value);
 293   }
 294 
 295 
 296   //--------------------------------------------------------------------------------
 297   // Internals only below this point
 298   //
 299 
 300   long getValue() {
 301     return addr;
 302   }
 303 
 304 
 305   private static void check(boolean arg, String failMessage) {
 306     if (!arg) {
 307       System.err.println(failMessage + ": FAILED");
 308       System.exit(1);
 309     }
 310   }
 311 
 312   // Test harness
 313   public static void main(String[] args) {
 314     // p/n indicates whether the interior address is really positive
 315     // or negative. In unsigned terms, p1 < p2 < n1 < n2.
 316 
 317     WindbgAddress p1 = new WindbgAddress(null, 0x7FFFFFFFFFFFFFF0L);
 318     WindbgAddress p2 = (WindbgAddress) p1.addOffsetTo(10);
 319     WindbgAddress n1 = (WindbgAddress) p2.addOffsetTo(10);
 320     WindbgAddress n2 = (WindbgAddress) n1.addOffsetTo(10);
 321 
 322     // lessThan positive tests
 323     check(p1.lessThan(p2), "lessThan 1");
 324     check(p1.lessThan(n1), "lessThan 2");
 325     check(p1.lessThan(n2), "lessThan 3");
 326     check(p2.lessThan(n1), "lessThan 4");
 327     check(p2.lessThan(n2), "lessThan 5");
 328     check(n1.lessThan(n2), "lessThan 6");
 329 
 330     // lessThan negative tests
 331     check(!p1.lessThan(p1), "lessThan 7");
 332     check(!p2.lessThan(p2), "lessThan 8");
 333     check(!n1.lessThan(n1), "lessThan 9");
 334     check(!n2.lessThan(n2), "lessThan 10");
 335 
 336     check(!p2.lessThan(p1), "lessThan 11");
 337     check(!n1.lessThan(p1), "lessThan 12");
 338     check(!n2.lessThan(p1), "lessThan 13");
 339     check(!n1.lessThan(p2), "lessThan 14");
 340     check(!n2.lessThan(p2), "lessThan 15");
 341     check(!n2.lessThan(n1), "lessThan 16");
 342 
 343     // lessThanOrEqual positive tests
 344     check(p1.lessThanOrEqual(p1), "lessThanOrEqual 1");
 345     check(p2.lessThanOrEqual(p2), "lessThanOrEqual 2");
 346     check(n1.lessThanOrEqual(n1), "lessThanOrEqual 3");
 347     check(n2.lessThanOrEqual(n2), "lessThanOrEqual 4");
 348 
 349     check(p1.lessThanOrEqual(p2), "lessThanOrEqual 5");
 350     check(p1.lessThanOrEqual(n1), "lessThanOrEqual 6");
 351     check(p1.lessThanOrEqual(n2), "lessThanOrEqual 7");
 352     check(p2.lessThanOrEqual(n1), "lessThanOrEqual 8");
 353     check(p2.lessThanOrEqual(n2), "lessThanOrEqual 9");
 354     check(n1.lessThanOrEqual(n2), "lessThanOrEqual 10");
 355 
 356     // lessThanOrEqual negative tests
 357     check(!p2.lessThanOrEqual(p1), "lessThanOrEqual 11");
 358     check(!n1.lessThanOrEqual(p1), "lessThanOrEqual 12");
 359     check(!n2.lessThanOrEqual(p1), "lessThanOrEqual 13");
 360     check(!n1.lessThanOrEqual(p2), "lessThanOrEqual 14");
 361     check(!n2.lessThanOrEqual(p2), "lessThanOrEqual 15");
 362     check(!n2.lessThanOrEqual(n1), "lessThanOrEqual 16");
 363 
 364     // greaterThan positive tests
 365     check(n2.greaterThan(p1), "greaterThan 1");
 366     check(n2.greaterThan(p2), "greaterThan 2");
 367     check(n2.greaterThan(n1), "greaterThan 3");
 368     check(n1.greaterThan(p1), "greaterThan 4");
 369     check(n1.greaterThan(p2), "greaterThan 5");
 370     check(p2.greaterThan(p1), "greaterThan 6");
 371 
 372     // greaterThan negative tests
 373     check(!p1.greaterThan(p1), "greaterThan 7");
 374     check(!p2.greaterThan(p2), "greaterThan 8");
 375     check(!n1.greaterThan(n1), "greaterThan 9");
 376     check(!n2.greaterThan(n2), "greaterThan 10");
 377 
 378     check(!p1.greaterThan(n2), "greaterThan 11");
 379     check(!p2.greaterThan(n2), "greaterThan 12");
 380     check(!n1.greaterThan(n2), "greaterThan 13");
 381     check(!p1.greaterThan(n1), "greaterThan 14");
 382     check(!p2.greaterThan(n1), "greaterThan 15");
 383     check(!p1.greaterThan(p2), "greaterThan 16");
 384 
 385     // greaterThanOrEqual positive tests
 386     check(p1.greaterThanOrEqual(p1), "greaterThanOrEqual 1");
 387     check(p2.greaterThanOrEqual(p2), "greaterThanOrEqual 2");
 388     check(n1.greaterThanOrEqual(n1), "greaterThanOrEqual 3");
 389     check(n2.greaterThanOrEqual(n2), "greaterThanOrEqual 4");
 390 
 391     check(n2.greaterThanOrEqual(p1), "greaterThanOrEqual 5");
 392     check(n2.greaterThanOrEqual(p2), "greaterThanOrEqual 6");
 393     check(n2.greaterThanOrEqual(n1), "greaterThanOrEqual 7");
 394     check(n1.greaterThanOrEqual(p1), "greaterThanOrEqual 8");
 395     check(n1.greaterThanOrEqual(p2), "greaterThanOrEqual 9");
 396     check(p2.greaterThanOrEqual(p1), "greaterThanOrEqual 10");
 397 
 398     // greaterThanOrEqual negative tests
 399     check(!p1.greaterThanOrEqual(n2), "greaterThanOrEqual 11");
 400     check(!p2.greaterThanOrEqual(n2), "greaterThanOrEqual 12");
 401     check(!n1.greaterThanOrEqual(n2), "greaterThanOrEqual 13");
 402     check(!p1.greaterThanOrEqual(n1), "greaterThanOrEqual 14");
 403     check(!p2.greaterThanOrEqual(n1), "greaterThanOrEqual 15");
 404     check(!p1.greaterThanOrEqual(p2), "greaterThanOrEqual 16");
 405 
 406     System.err.println("WindbgAddress: all tests passed successfully.");
 407   }
 408 }