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