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