1 /* 2 * Copyright (c) 2004, 2017, 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 // shorter names for SA packages 26 27 28 // SA package name abbreviations are kept in 'sapkg' object 29 // to avoid global namespace pollution 30 var sapkg = new Object(); 31 32 sapkg.hotspot = Packages.sun.jvm.hotspot; 33 sapkg.asm = sapkg.hotspot.asm; 34 sapkg.c1 = sapkg.hotspot.c1; 35 sapkg.code = sapkg.hotspot.code; 36 sapkg.compiler = sapkg.hotspot.compiler; 37 38 // 'debugger' is a JavaScript keyword, but ES5 relaxes the 39 // restriction of using keywords as property name 40 sapkg.debugger = sapkg.hotspot.debugger; 41 42 sapkg.interpreter = sapkg.hotspot.interpreter; 43 sapkg.jdi = sapkg.hotspot.jdi; 44 sapkg.memory = sapkg.hotspot.memory; 45 sapkg.oops = sapkg.hotspot.oops; 46 sapkg.runtime = sapkg.hotspot.runtime; 47 sapkg.tools = sapkg.hotspot.tools; 48 sapkg.types = sapkg.hotspot.types; 49 sapkg.ui = sapkg.hotspot.ui; 50 sapkg.utilities = sapkg.hotspot.utilities; 51 52 // SA singletons are kept in 'sa' object 53 var sa = new Object(); 54 sa.vm = sapkg.runtime.VM.getVM(); 55 sa.dbg = sa.vm.getDebugger(); 56 sa.cdbg = sa.dbg.CDebugger; 57 sa.heap = sa.vm.universe.heap(); 58 sa.systemDictionary = sa.vm.systemDictionary; 59 sa.sysDict = sa.systemDictionary; 60 sa.symbolTable = sa.vm.symbolTable; 61 sa.symTbl = sa.symbolTable; 62 sa.threads = sa.vm.threads; 63 sa.interpreter = sa.vm.interpreter; 64 sa.typedb = sa.vm.typeDataBase; 65 sa.codeCache = sa.vm.codeCache; 66 // 'objHeap' is different from 'heap'!. 67 // This is SA's Oop factory and heap-walker 68 sa.objHeap = sa.vm.objectHeap; 69 70 // few useful global variables 71 var OS = sa.vm.OS; 72 var CPU = sa.vm.CPU; 73 var LP64 = sa.vm.LP64; 74 var isClient = sa.vm.clientCompiler; 75 var isServer = sa.vm.serverCompiler; 76 var isCore = sa.vm.isCore(); 77 var addressSize = sa.vm.addressSize; 78 var oopSize = sa.vm.oopSize; 79 80 // this "main" function is called immediately 81 // after loading this script file 82 function main(globals, jvmarg) { 83 // wrap a sun.jvm.hotspot.utilities.soql.ScriptObject 84 // object so that the properties of it can be accessed 85 // in natural object.field syntax. 86 function wrapScriptObject(so) { 87 function unwrapScriptObject(wso) { 88 var objType = typeof(wso); 89 if ((objType == 'object' || 90 objType == 'function') 91 && "__wrapped__" in wso) { 92 return wso.__wrapped__; 93 } else { 94 return wso; 95 } 96 } 97 98 function prepareArgsArray(array) { 99 var args = new Array(array.length); 100 for (var a = 0; a < array.length; a++) { 101 var elem = array[a]; 102 elem = unwrapScriptObject(elem); 103 if (typeof(elem) == 'function') { 104 args[a] = new sapkg.utilities.soql.Callable() { 105 call: function(myargs) { 106 var tmp = new Array(myargs.length); 107 for (var i = 0; i < myargs.length; i++) { 108 tmp[i] = wrapScriptObject(myargs[i]); 109 } 110 return elem.apply(this, tmp); 111 } 112 } 113 } else { 114 args[a] = elem; 115 } 116 } 117 return args; 118 } 119 120 // Handle __has__ specially to avoid metacircularity problems 121 // when called from __get__. 122 // Calling 123 // this.__has__(name) 124 // will in turn call 125 // this.__call__('__has__', name) 126 // which is not handled below 127 function __has__(name) { 128 if (typeof(name) == 'number') { 129 return so["has(int)"](name); 130 } else { 131 if (name == '__wrapped__') { 132 return true; 133 } else if (so["has(java.lang.String)"](name)) { 134 return true; 135 } else if (name.equals('toString')) { 136 return true; 137 } else { 138 return false; 139 } 140 } 141 } 142 143 if (so instanceof sapkg.utilities.soql.ScriptObject) { 144 return new JSAdapter() { 145 __getIds__: function() { 146 return so.getIds(); 147 }, 148 149 __has__ : __has__, 150 151 __delete__ : function(name) { 152 if (typeof(name) == 'number') { 153 return so["delete(int)"](name); 154 } else { 155 return so["delete(java.lang.String)"](name); 156 } 157 }, 158 159 __get__ : function(name) { 160 // don't call this.__has__(name); see comments above function __has__ 161 if (! __has__.call(this, name)) { 162 return undefined; 163 } 164 if (typeof(name) == 'number') { 165 return wrapScriptObject(so["get(int)"](name)); 166 } else { 167 if (name == '__wrapped__') { 168 return so; 169 } else { 170 var value = so["get(java.lang.String)"](name); 171 if (value instanceof sapkg.utilities.soql.Callable) { 172 return function() { 173 var args = prepareArgsArray(arguments); 174 var r; 175 try { 176 r = value.call(Java.to(args, 'java.lang.Object[]')); 177 } catch (e) { 178 println("call to " + name + " failed!"); 179 throw e; 180 } 181 return wrapScriptObject(r); 182 } 183 } else if (name == 'toString') { 184 return function() { 185 return so.toString(); 186 } 187 } else { 188 return wrapScriptObject(value); 189 } 190 } 191 } 192 } 193 }; 194 } else { 195 return so; 196 } 197 } 198 199 // set "jvm" global variable that wraps a 200 // sun.jvm.hotspot.utilities.soql.JSJavaVM instance 201 if (jvmarg != null) { 202 jvm = wrapScriptObject(jvmarg); 203 // expose "heap" global variable 204 heap = jvm.heap; 205 } 206 207 // expose all "function" type properties of 208 // sun.jvm.hotspot.utilitites.soql.JSJavaScriptEngine 209 // as global functions here. 210 globals = wrapScriptObject(globals); 211 for (var prop in globals) { 212 if (typeof(globals[prop]) == 'function') { 213 this[prop] = globals[prop]; 214 } 215 } 216 217 // define "writeln" and "write" if not defined 218 if (typeof(println) == 'undefined') { 219 println = function (str) { 220 java.lang.System.out.println(String(str)); 221 } 222 } 223 224 if (typeof(print) == 'undefined') { 225 print = function (str) { 226 java.lang.System.out.print(String(str)); 227 } 228 } 229 230 if (typeof(writeln) == 'undefined') { 231 writeln = println; 232 } 233 234 if (typeof(write) == 'undefined') { 235 write = print; 236 } 237 238 // "registerCommand" function is defined if we 239 // are running as part of "CLHSDB" tool. CLHSDB 240 // tool exposes Unix-style commands. 241 242 // if "registerCommand" function is defined 243 // then register few global functions as "commands". 244 if (typeof(registerCommand) == 'function') { 245 this.jclass = function(name) { 246 if (typeof(name) == "string") { 247 var clazz = sapkg.utilities.SystemDictionaryHelper.findInstanceKlass(name); 248 if (clazz) { 249 writeln(clazz.getName().asString() + " @" + clazz.getAddress().toString()); 250 } else { 251 writeln("class not found: " + name); 252 } 253 } else { 254 writeln("Usage: class name"); 255 } 256 } 257 registerCommand("class", "class name", "jclass"); 258 259 this.jclasses = function() { 260 forEachKlass(function (clazz) { 261 writeln(clazz.getName().asString() + " @" + clazz.getAddress().toString()); 262 }); 263 } 264 registerCommand("classes", "classes", "jclasses"); 265 266 this.dclass = function(clazz, dir) { 267 if (!clazz) { 268 writeln("Usage: dumpclass { address | name } [ directory ]"); 269 } else { 270 if (!dir) { dir = "."; } 271 dumpClass(clazz, dir); 272 } 273 } 274 registerCommand("dumpclass", "dumpclass { address | name } [ directory ]", "dclass"); 275 registerCommand("dumpheap", "dumpheap [ file ]", "dumpHeap"); 276 277 this.jseval = function(str) { 278 if (!str) { 279 writeln("Usage: jseval script"); 280 } else { 281 var res = eval(str); 282 if (res) { writeln(res); } 283 } 284 } 285 registerCommand("jseval", "jseval script", "jseval"); 286 287 this.jsload = function(file) { 288 if (!file) { 289 writeln("Usage: jsload file"); 290 } else { 291 load(file); 292 } 293 } 294 registerCommand("jsload", "jsload file", "jsload"); 295 296 this.printMem = function(addr, len) { 297 if (!addr) { 298 writeln("Usage: mem [ length ]"); 299 } else { 300 mem(addr, len); 301 } 302 } 303 registerCommand("mem", "mem address [ length ]", "printMem"); 304 305 this.sysProps = function() { 306 for (var i in jvm.sysProps) { 307 writeln(i + ' = ' + jvm.sysProps[i]); 308 } 309 } 310 registerCommand("sysprops", "sysprops", "sysProps"); 311 312 this.printWhatis = function(addr) { 313 if (!addr) { 314 writeln("Usage: whatis address"); 315 } else { 316 writeln(whatis(addr)); 317 } 318 } 319 registerCommand("whatis", "whatis address", "printWhatis"); 320 } 321 } 322 323 // debugger functionality 324 325 // string-to-Address 326 function str2addr(str) { 327 return sa.dbg.parseAddress(str); 328 } 329 330 // number-to-Address 331 if (addressSize == 4) { 332 eval("function num2addr(num) { \ 333 return str2addr('0x' + java.lang.Integer.toHexString(0xffffffff & num)); \ 334 }"); 335 } else { 336 eval("function num2addr(num) { \ 337 return str2addr('0x' + java.lang.Long.toHexString(num)); \ 338 }"); 339 } 340 341 // generic any-type-to-Address 342 // use this convenience function to accept address in any 343 // format -- number, string or an Address instance. 344 function any2addr(addr) { 345 var type = typeof(addr); 346 if (type == 'number') { 347 return num2addr(addr); 348 } else if (type == 'string') { 349 return str2addr(addr); 350 } else { 351 return addr; 352 } 353 } 354 355 // Address-to-string 356 function addr2str(addr) { 357 if (addr == null) { 358 return (addressSize == 4)? '0x00000000' : '0x0000000000000000'; 359 } else { 360 return addr + ''; 361 } 362 } 363 364 // Address-to-number 365 function addr2num(addr) { 366 return sa.dbg.getAddressValue(addr); 367 } 368 369 // symbol-to-Address 370 function sym2addr(dso, sym) { 371 return sa.dbg.lookup(dso, sym); 372 } 373 374 // returns the ClosestSymbol or null 375 function closestSymbolFor(addr) { 376 if (sa.cdbg == null) { 377 // no CDebugger support, return null 378 return null; 379 } else { 380 var dso = sa.cdbg.loadObjectContainingPC(addr); 381 if (dso != null) { 382 return dso.closestSymbolToPC(addr); 383 } else { 384 return null; 385 } 386 } 387 } 388 389 // Address-to-symbol 390 // returns nearest symbol as string if found 391 // else returns address as string 392 function addr2sym(addr) { 393 var sym = closestSymbolFor(addr); 394 if (sym != null) { 395 return sym.name + '+' + sym.offset; 396 } else { 397 return addr2str(addr); 398 } 399 } 400 401 // read 'num' words at 'addr' and return an array as result. 402 // returns Java long[] type result and not a JavaScript array. 403 function readWordsAt(addr, num) { 404 addr = any2addr(addr); 405 var res = java.lang.reflect.Array.newInstance(java.lang.Long.TYPE, num); 406 var i; 407 for (i = 0; i < num; i++) { 408 res[i] = addr2num(addr.getAddressAt(i * addressSize)); 409 } 410 return res; 411 } 412 413 // read the 'C' string at 'addr' 414 function readCStrAt(addr) { 415 addr = any2addr(addr); 416 return sapkg.utilities.CStringUtilities.getString(addr); 417 } 418 419 // read the length of the 'C' string at 'addr' 420 function readCStrLen(addr) { 421 addr = any2addr(addr); 422 return sapkg.utilities.CStringUtilities.getStringLength(addr); 423 } 424 425 // iterate through ThreadList of CDebugger 426 function forEachThread(callback) { 427 if (sa.cdbg == null) { 428 // no CDebugger support 429 return; 430 } else { 431 var itr = sa.cdbg.threadList.iterator(); 432 while (itr.hasNext()) { 433 if (callback(itr.next()) == false) return; 434 } 435 } 436 } 437 438 // read register set of a ThreadProxy as name-value pairs 439 function readRegs(threadProxy) { 440 var ctx = threadProxy.context; 441 var num = ctx.numRegisters; 442 var res = new Object(); 443 var i; 444 for (i = 0; i < num; i++) { 445 res[ctx.getRegisterName(i)]= addr2str(ctx.getRegisterAsAddress(i)); 446 } 447 return res; 448 } 449 450 // print register set for a given ThreaProxy 451 function regs(threadProxy) { 452 var res = readRegs(threadProxy); 453 for (i in res) { 454 writeln(i, '=', res[i]); 455 } 456 } 457 458 // iterate through each CFrame of a given ThreadProxy 459 function forEachCFrame(threadProxy, callback) { 460 if (sa.cdbg == null) { 461 // no CDebugger support 462 return; 463 } else { 464 var cframe = sa.cdbg.topFrameForThread(threadProxy); 465 while (cframe != null) { 466 if (callback(cframe) == false) return; 467 cframe = cframe.sender(); 468 } 469 } 470 } 471 472 // iterate through list of load objects (DLLs, DSOs) 473 function forEachLoadObject(callback) { 474 if (sa.cdbg == null) { 475 // no CDebugger support 476 return; 477 } else { 478 var itr = sa.cdbg.loadObjectList.iterator(); 479 while (itr.hasNext()) { 480 if (callback(itr.next()) == false) return; 481 } 482 } 483 } 484 485 // print 'num' words at 'addr' 486 function mem(addr, num) { 487 if (num == undefined) { 488 num = 1; 489 } 490 addr = any2addr(addr); 491 var i; 492 for (i = 0; i < num; i++) { 493 var value = addr.getAddressAt(0); 494 writeln(addr2sym(addr) + ':', addr2str(value)); 495 addr = addr.addOffsetTo(addressSize); 496 } 497 writeln(); 498 } 499 500 // System dictionary functions 501 502 // find InstanceKlass by name 503 function findInstanceKlass(name) { 504 return sapkg.utilities.SystemDictionaryHelper.findInstanceKlass(name); 505 } 506 507 // get Java system loader (i.e., application launcher loader) 508 function systemLoader() { 509 return sa.sysDict.javaSystemLoader(); 510 } 511 512 // iterate system dictionary for each 'Klass' 513 function forEachKlass(callback) { 514 var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor; 515 var visitor = new VisitorClass() { visit: callback }; 516 sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor); 517 } 518 519 // iterate system dictionary for each 'Klass' and initiating loader 520 function forEachKlassAndLoader(callback) { 521 var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; 522 var visitor = new VisitorClass() { visit: callback }; 523 sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor); 524 } 525 526 // iterate system dictionary for each primitive array klass 527 function forEachPrimArrayKlass(callback) { 528 var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; 529 sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback }); 530 } 531 532 // 'oop' to higher-level java object wrapper in which for(i in o) 533 // works by iterating java level fields and javaobject.javafield 534 // syntax works. 535 function oop2obj(oop) { 536 return object(addr2str(oop.handle)); 537 } 538 539 // higher level java object wrapper to oop 540 function obj2oop(obj) { 541 return addr2oop(str2addr(address(obj))); 542 } 543 544 // Java heap iteration 545 546 // iterates Java heap for each Oop 547 function forEachOop(callback) { 548 function empty() { } 549 sa.objHeap.iterate(new sapkg.oops.HeapVisitor() { 550 prologue: empty, 551 doObj: callback, 552 epilogue: empty 553 }); 554 } 555 556 // iterates Java heap for each Oop of given 'klass'. 557 // 'includeSubtypes' tells whether to include objects 558 // of subtypes of 'klass' or not 559 function forEachOopOfKlass(callback, klass, includeSubtypes) { 560 if (klass == undefined) { 561 klass = findInstanceKlass("java.lang.Object"); 562 } 563 564 if (includeSubtypes == undefined) { 565 includeSubtypes = true; 566 } 567 568 function empty() { } 569 sa.objHeap.iterateObjectsOfKlass( 570 new sapkg.oops.HeapVisitor() { 571 prologue: empty, 572 doObj: callback, 573 epilogue: empty 574 }, 575 klass, includeSubtypes); 576 } 577 578 // Java thread 579 580 // iterates each Thread 581 function forEachJavaThread(callback) { 582 var threads = sa.threads; 583 var thread = threads.first(); 584 while (thread != null) { 585 if (callback(thread) == false) return; 586 thread = thread.next(); 587 } 588 } 589 590 // iterate Frames of a given thread 591 function forEachFrame(javaThread, callback) { 592 var fr = javaThread.getLastFrameDbg(); 593 while (fr != null) { 594 if (callback(fr) == false) return; 595 fr = fr.sender(); 596 } 597 } 598 599 // iterate JavaVFrames of a given JavaThread 600 function forEachVFrame(javaThread, callback) { 601 var vfr = javaThread.getLastJavaVFrameDbg(); 602 while (vfr != null) { 603 if (callback(vfr) == false) return; 604 vfr = vfr.javaSender(); 605 } 606 } 607 608 function printStackTrace(javaThread) { 609 write("Thread "); 610 javaThread.printThreadIDOn(java.lang.System.out); 611 writeln(); 612 forEachVFrame(javaThread, function (vf) { 613 var method = vf.method; 614 write(' - ', method.externalNameAndSignature(), '@bci =', vf.getBCI()); 615 var line = method.getLineNumberFromBCI(vf.getBCI()); 616 if (line != -1) { write(', line=', line); } 617 if (vf.isCompiledFrame()) { write(" (Compiled Frame)"); } 618 if (vf.isInterpretedFrame()) { write(" (Interpreted Frame)"); } 619 writeln(); 620 }); 621 writeln(); 622 writeln(); 623 } 624 625 // print Java stack trace for all threads 626 function where(javaThread) { 627 if (javaThread == undefined) { 628 forEachJavaThread(function (jt) { printStackTrace(jt); }); 629 } else { 630 printStackTrace(javaThread); 631 } 632 } 633 634 // vmStructs access -- type database functions 635 636 // find a VM type 637 function findVMType(typeName) { 638 return sa.typedb.lookupType(typeName); 639 } 640 641 // iterate VM types 642 function forEachVMType(callback) { 643 var itr = sa.typedb.types; 644 while (itr.hasNext()) { 645 if (callback(itr.next()) == false) return; 646 } 647 } 648 649 // find VM int constant 650 function findVMIntConst(name) { 651 return sa.typedb.lookupIntConstant(name); 652 } 653 654 // find VM long constant 655 function findVMLongConst(name) { 656 return sa.typedb.lookupLongConstant(name); 657 } 658 659 // iterate VM int constants 660 function forEachVMIntConst(callback) { 661 var itr = sa.typedb.intConstants; 662 while (itr.hasNext()) { 663 if (callback(itr.next()) == false) return; 664 } 665 } 666 667 // iterate VM long constants 668 function forEachVMLongConst(callback) { 669 var itr = sa.typedb.longConstants; 670 while (itr.hasNext()) { 671 if (callback(itr.next()) == false) return; 672 } 673 } 674 675 // returns VM Type at address 676 function vmTypeof(addr) { 677 addr = any2addr(addr); 678 return sa.typedb.guessTypeForAddress(addr); 679 } 680 681 // does the given 'addr' points to an object of given 'type'? 682 // OR any valid Type at all (if type is undefined) 683 function isOfVMType(addr, type) { 684 addr = any2addr(addr); 685 if (type == undefined) { 686 return vmTypeof(addr) != null; 687 } else { 688 if (typeof(type) == 'string') { 689 type = findVMType(type); 690 } 691 return sa.typedb.addressTypeIsEqualToType(addr, type); 692 } 693 } 694 695 // reads static field value 696 function readVMStaticField(field) { 697 var type = field.type; 698 if (type.isCIntegerType() || type.isJavaPrimitiveType()) { 699 return field.value; 700 } else if (type.isPointerType()) { 701 return field.address; 702 } else if (type.isOopType()) { 703 return field.oopHandle; 704 } else { 705 return field.staticFieldAddress; 706 } 707 } 708 709 // reads given instance field of VM object at 'addr' 710 function readVMInstanceField(field, addr) { 711 var type = field.type; 712 if (type.isCIntegerType() || type.isJavaPrimitiveType()) { 713 return field.getValue(addr); 714 } else if (type.isPointerType()) { 715 return field.getAddress(addr); 716 } else if (type.isOopType()) { 717 return field.getOopHandle(addr); 718 } else { 719 return addr.addOffsetTo(field.offset); 720 } 721 } 722 723 // returns name-value of pairs of VM type at given address. 724 // If address is unspecified, reads static fields as name-value pairs. 725 function readVMType(type, addr) { 726 if (typeof(type) == 'string') { 727 type = findVMType(type); 728 } 729 if (addr != undefined) { 730 addr = any2addr(addr); 731 } 732 733 var result = new Object(); 734 var staticOnly = (addr == undefined); 735 while (type != null) { 736 var itr = type.fields; 737 while (itr.hasNext()) { 738 var field = itr.next(); 739 var isStatic = field.isStatic(); 740 if (staticOnly && isStatic) { 741 result[field.name] = readVMStaticField(field); 742 } else if (!staticOnly && !isStatic) { 743 result[field.name] = readVMInstanceField(field, addr); 744 } 745 } 746 type = type.superclass; 747 } 748 return result; 749 } 750 751 function printVMType(type, addr) { 752 if (typeof(type) == 'string') { 753 type = findVMType(type); 754 } 755 var obj = readVMType(type, addr); 756 while (type != null) { 757 var itr = type.fields; 758 while (itr.hasNext()) { 759 var field = itr.next(); 760 var name = field.name; 761 var value = obj[name]; 762 if (value != undefined) { 763 writeln(field.type.name, type.name + '::' + name, '=', value); 764 } 765 } 766 type = type.superclass; 767 } 768 } 769 770 // define readXXX and printXXX functions for each VM struct/class Type 771 tmp = new Object(); 772 tmp.itr = sa.typedb.types; 773 while (tmp.itr.hasNext()) { 774 tmp.type = tmp.itr.next(); 775 tmp.name = tmp.type.name; 776 if (tmp.type.isPointerType() || tmp.type.isOopType() || 777 tmp.type.isCIntegerType() || tmp.type.isJavaPrimitiveType() || 778 tmp.name.equals('address') || 779 tmp.name.equals("<opaque>")) { 780 // ignore; 781 continue; 782 } else { 783 // some type names have ':', '<', '>', '*', ' '. replace to make it as a 784 // JavaScript identifier 785 tmp.name = ("" + tmp.name).replace(/[:<>* ]/g, '_'); 786 eval("function read" + tmp.name + "(addr) {" + 787 " return readVMType('" + tmp.name + "', addr);}"); 788 eval("function print" + tmp.name + "(addr) {" + 789 " printVMType('" + tmp.name + "', addr); }"); 790 791 /* FIXME: do we need this? 792 if (typeof(registerCommand) != 'undefined') { 793 var name = "print" + tmp.name; 794 registerCommand(name, name + " [address]", name); 795 } 796 */ 797 } 798 } 799 //clean-up the temporary 800 delete tmp; 801 802 // VMObject factory 803 804 // VM type to SA class map 805 var vmType2Class = new Object(); 806 807 // C2 only classes 808 try{ 809 vmType2Class["ExceptionBlob"] = sapkg.code.ExceptionBlob; 810 vmType2Class["UncommonTrapBlob"] = sapkg.code.UncommonTrapBlob; 811 } catch(e) { 812 // Ignore exception. C2 specific objects might be not 813 // available in client VM 814 } 815 816 817 // This is *not* exhaustive. Add more if needed. 818 // code blobs 819 vmType2Class["BufferBlob"] = sapkg.code.BufferBlob; 820 vmType2Class["nmethod"] = sapkg.code.NMethod; 821 vmType2Class["RuntimeStub"] = sapkg.code.RuntimeStub; 822 vmType2Class["SafepointBlob"] = sapkg.code.SafepointBlob; 823 vmType2Class["C2IAdapter"] = sapkg.code.C2IAdapter; 824 vmType2Class["DeoptimizationBlob"] = sapkg.code.DeoptimizationBlob; 825 vmType2Class["I2CAdapter"] = sapkg.code.I2CAdapter; 826 vmType2Class["OSRAdapter"] = sapkg.code.OSRAdapter; 827 vmType2Class["PCDesc"] = sapkg.code.PCDesc; 828 829 // interpreter 830 vmType2Class["InterpreterCodelet"] = sapkg.interpreter.InterpreterCodelet; 831 832 // Java Threads 833 vmType2Class["JavaThread"] = sapkg.runtime.JavaThread; 834 vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread; 835 vmType2Class["SurrogateLockerThread"] = sapkg.runtime.JavaThread; 836 vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread; 837 838 // gc 839 vmType2Class["GenCollectedHeap"] = sapkg.memory.GenCollectedHeap; 840 vmType2Class["DefNewGeneration"] = sapkg.memory.DefNewGeneration; 841 vmType2Class["TenuredGeneration"] = sapkg.memory.TenuredGeneration; 842 843 // generic VMObject factory for a given address 844 // This is equivalent to VirtualConstructor. 845 function newVMObject(addr) { 846 addr = any2addr(addr); 847 var result = null; 848 forEachVMType(function (type) { 849 if (isOfVMType(addr, type)) { 850 var clazz = vmType2Class[type.name]; 851 if (clazz != undefined) { 852 result = new clazz(addr); 853 } 854 return false; 855 } else { 856 return true; 857 } 858 }); 859 return result; 860 } 861 862 function vmobj2addr(vmobj) { 863 return vmobj.address; 864 } 865 866 function addr2vmobj(addr) { 867 return newVMObject(addr); 868 } 869 870 // Miscellaneous utilities 871 872 // returns PointerLocation that describes the given pointer 873 function findPtr(addr) { 874 addr = any2addr(addr); 875 return sapkg.utilities.PointerFinder.find(addr); 876 } 877 878 // is given address a valid Oop? 879 function isOop(addr) { 880 addr = any2addr(addr); 881 var oopHandle = addr.addOffsetToAsOopHandle(0); 882 return sapkg.utilities.RobustOopDeterminator.oopLooksValid(oopHandle); 883 } 884 885 // returns description of given pointer as a String 886 function whatis(addr) { 887 addr = any2addr(addr); 888 var ptrLoc = findPtr(addr); 889 if (ptrLoc.isUnknown()) { 890 var vmType = vmTypeof(addr); 891 if (vmType != null) { 892 return "pointer to " + vmType.name; 893 } else { 894 var sym = closestSymbolFor(addr); 895 if (sym != null) { 896 return sym.name + '+' + sym.offset; 897 } else { 898 return ptrLoc.toString(); 899 } 900 } 901 } else { 902 return ptrLoc.toString(); 903 } 904 }