1 /* 2 * Copyright (c) 2004, 2016, 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 function loadObjectContainingPC(addr) { 375 if (sa.cdbg == null) { 376 // no CDebugger support, return null 377 return null; 378 } 379 380 return sa.cdbg.loadObjectContainingPC(addr); 381 } 382 383 // returns the ClosestSymbol or null 384 function closestSymbolFor(addr) { 385 var dso = loadObjectContainingPC(addr); 386 if (dso != null) { 387 return dso.closestSymbolToPC(addr); 388 } 389 390 return null; 391 } 392 393 // Address-to-symbol 394 // returns nearest symbol as string if found 395 // else returns address as string 396 function addr2sym(addr) { 397 var sym = closestSymbolFor(addr); 398 if (sym != null) { 399 return sym.name + '+' + sym.offset; 400 } else { 401 return addr2str(addr); 402 } 403 } 404 405 // read 'num' words at 'addr' and return an array as result. 406 // returns Java long[] type result and not a JavaScript array. 407 function readWordsAt(addr, num) { 408 addr = any2addr(addr); 409 var res = java.lang.reflect.Array.newInstance(java.lang.Long.TYPE, num); 410 var i; 411 for (i = 0; i < num; i++) { 412 res[i] = addr2num(addr.getAddressAt(i * addressSize)); 413 } 414 return res; 415 } 416 417 // read the 'C' string at 'addr' 418 function readCStrAt(addr) { 419 addr = any2addr(addr); 420 return sapkg.utilities.CStringUtilities.getString(addr); 421 } 422 423 // read the length of the 'C' string at 'addr' 424 function readCStrLen(addr) { 425 addr = any2addr(addr); 426 return sapkg.utilities.CStringUtilities.getStringLength(addr); 427 } 428 429 // iterate through ThreadList of CDebugger 430 function forEachThread(callback) { 431 if (sa.cdbg == null) { 432 // no CDebugger support 433 return; 434 } else { 435 var itr = sa.cdbg.threadList.iterator(); 436 while (itr.hasNext()) { 437 if (callback(itr.next()) == false) return; 438 } 439 } 440 } 441 442 // read register set of a ThreadProxy as name-value pairs 443 function readRegs(threadProxy) { 444 var ctx = threadProxy.context; 445 var num = ctx.numRegisters; 446 var res = new Object(); 447 var i; 448 for (i = 0; i < num; i++) { 449 res[ctx.getRegisterName(i)]= addr2str(ctx.getRegisterAsAddress(i)); 450 } 451 return res; 452 } 453 454 // print register set for a given ThreaProxy 455 function regs(threadProxy) { 456 var res = readRegs(threadProxy); 457 for (i in res) { 458 writeln(i, '=', res[i]); 459 } 460 } 461 462 // iterate through each CFrame of a given ThreadProxy 463 function forEachCFrame(threadProxy, callback) { 464 if (sa.cdbg == null) { 465 // no CDebugger support 466 return; 467 } else { 468 var cframe = sa.cdbg.topFrameForThread(threadProxy); 469 while (cframe != null) { 470 if (callback(cframe) == false) return; 471 cframe = cframe.sender(); 472 } 473 } 474 } 475 476 // iterate through list of load objects (DLLs, DSOs) 477 function forEachLoadObject(callback) { 478 if (sa.cdbg == null) { 479 // no CDebugger support 480 return; 481 } else { 482 var itr = sa.cdbg.loadObjectList.iterator(); 483 while (itr.hasNext()) { 484 if (callback(itr.next()) == false) return; 485 } 486 } 487 } 488 489 // print 'num' words at 'addr' 490 function mem(addr, num) { 491 if (num == undefined) { 492 num = 1; 493 } 494 addr = any2addr(addr); 495 var i; 496 for (i = 0; i < num; i++) { 497 var value = addr.getAddressAt(0); 498 writeln(addr2sym(addr) + ':', addr2str(value)); 499 addr = addr.addOffsetTo(addressSize); 500 } 501 writeln(); 502 } 503 504 // System dictionary functions 505 506 // find InstanceKlass by name 507 function findInstanceKlass(name) { 508 return sapkg.utilities.SystemDictionaryHelper.findInstanceKlass(name); 509 } 510 511 // get Java system loader (i.e., application launcher loader) 512 function systemLoader() { 513 return sa.sysDict.javaSystemLoader(); 514 } 515 516 // iterate system dictionary for each 'Klass' 517 function forEachKlass(callback) { 518 var VisitorClass = sapkg.memory.SystemDictionary.ClassVisitor; 519 var visitor = new VisitorClass() { visit: callback }; 520 sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassVisitor)"](visitor); 521 } 522 523 // iterate system dictionary for each 'Klass' and initiating loader 524 function forEachKlassAndLoader(callback) { 525 var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; 526 var visitor = new VisitorClass() { visit: callback }; 527 sa.sysDict["classesDo(sun.jvm.hotspot.memory.SystemDictionary.ClassAndLoaderVisitor)"](visitor); 528 } 529 530 // iterate system dictionary for each primitive array klass 531 function forEachPrimArrayKlass(callback) { 532 var VisitorClass = sapkg.memory.SystemDictionary.ClassAndLoaderVisitor; 533 sa.sysDict.primArrayClassesDo(new VisitorClass() { visit: callback }); 534 } 535 536 // 'oop' to higher-level java object wrapper in which for(i in o) 537 // works by iterating java level fields and javaobject.javafield 538 // syntax works. 539 function oop2obj(oop) { 540 return object(addr2str(oop.handle)); 541 } 542 543 // higher level java object wrapper to oop 544 function obj2oop(obj) { 545 return addr2oop(str2addr(address(obj))); 546 } 547 548 // Java heap iteration 549 550 // iterates Java heap for each Oop 551 function forEachOop(callback) { 552 function empty() { } 553 sa.objHeap.iterate(new sapkg.oops.HeapVisitor() { 554 prologue: empty, 555 doObj: callback, 556 epilogue: empty 557 }); 558 } 559 560 // iterates Java heap for each Oop of given 'klass'. 561 // 'includeSubtypes' tells whether to include objects 562 // of subtypes of 'klass' or not 563 function forEachOopOfKlass(callback, klass, includeSubtypes) { 564 if (klass == undefined) { 565 klass = findInstanceKlass("java.lang.Object"); 566 } 567 568 if (includeSubtypes == undefined) { 569 includeSubtypes = true; 570 } 571 572 function empty() { } 573 sa.objHeap.iterateObjectsOfKlass( 574 new sapkg.oops.HeapVisitor() { 575 prologue: empty, 576 doObj: callback, 577 epilogue: empty 578 }, 579 klass, includeSubtypes); 580 } 581 582 // Java thread 583 584 // iterates each Thread 585 function forEachJavaThread(callback) { 586 var threads = sa.threads; 587 var thread = threads.first(); 588 while (thread != null) { 589 if (callback(thread) == false) return; 590 thread = thread.next(); 591 } 592 } 593 594 // iterate Frames of a given thread 595 function forEachFrame(javaThread, callback) { 596 var fr = javaThread.getLastFrameDbg(); 597 while (fr != null) { 598 if (callback(fr) == false) return; 599 fr = fr.sender(); 600 } 601 } 602 603 // iterate JavaVFrames of a given JavaThread 604 function forEachVFrame(javaThread, callback) { 605 var vfr = javaThread.getLastJavaVFrameDbg(); 606 while (vfr != null) { 607 if (callback(vfr) == false) return; 608 vfr = vfr.javaSender(); 609 } 610 } 611 612 function printStackTrace(javaThread) { 613 write("Thread "); 614 javaThread.printThreadIDOn(java.lang.System.out); 615 writeln(); 616 forEachVFrame(javaThread, function (vf) { 617 var method = vf.method; 618 write(' - ', method.externalNameAndSignature(), '@bci =', vf.getBCI()); 619 var line = method.getLineNumberFromBCI(vf.getBCI()); 620 if (line != -1) { write(', line=', line); } 621 if (vf.isCompiledFrame()) { write(" (Compiled Frame)"); } 622 if (vf.isInterpretedFrame()) { write(" (Interpreted Frame)"); } 623 writeln(); 624 }); 625 writeln(); 626 writeln(); 627 } 628 629 // print Java stack trace for all threads 630 function where(javaThread) { 631 if (javaThread == undefined) { 632 forEachJavaThread(function (jt) { printStackTrace(jt); }); 633 } else { 634 printStackTrace(javaThread); 635 } 636 } 637 638 // vmStructs access -- type database functions 639 640 // find a VM type 641 function findVMType(typeName) { 642 return sa.typedb.lookupType(typeName); 643 } 644 645 // iterate VM types 646 function forEachVMType(callback) { 647 var itr = sa.typedb.types; 648 while (itr.hasNext()) { 649 if (callback(itr.next()) == false) return; 650 } 651 } 652 653 // find VM int constant 654 function findVMIntConst(name) { 655 return sa.typedb.lookupIntConstant(name); 656 } 657 658 // find VM long constant 659 function findVMLongConst(name) { 660 return sa.typedb.lookupLongConstant(name); 661 } 662 663 // iterate VM int constants 664 function forEachVMIntConst(callback) { 665 var itr = sa.typedb.intConstants; 666 while (itr.hasNext()) { 667 if (callback(itr.next()) == false) return; 668 } 669 } 670 671 // iterate VM long constants 672 function forEachVMLongConst(callback) { 673 var itr = sa.typedb.longConstants; 674 while (itr.hasNext()) { 675 if (callback(itr.next()) == false) return; 676 } 677 } 678 679 // returns VM Type at address 680 function vmTypeof(addr) { 681 addr = any2addr(addr); 682 return sa.typedb.guessTypeForAddress(addr); 683 } 684 685 // does the given 'addr' points to an object of given 'type'? 686 // OR any valid Type at all (if type is undefined) 687 function isOfVMType(addr, type) { 688 addr = any2addr(addr); 689 if (type == undefined) { 690 return vmTypeof(addr) != null; 691 } else { 692 if (typeof(type) == 'string') { 693 type = findVMType(type); 694 } 695 return sa.typedb.addressTypeIsEqualToType(addr, type); 696 } 697 } 698 699 // reads static field value 700 function readVMStaticField(field) { 701 var type = field.type; 702 if (type.isCIntegerType() || type.isJavaPrimitiveType()) { 703 return field.value; 704 } else if (type.isPointerType()) { 705 return field.address; 706 } else if (type.isOopType()) { 707 return field.oopHandle; 708 } else { 709 return field.staticFieldAddress; 710 } 711 } 712 713 // reads given instance field of VM object at 'addr' 714 function readVMInstanceField(field, addr) { 715 var type = field.type; 716 if (type.isCIntegerType() || type.isJavaPrimitiveType()) { 717 return field.getValue(addr); 718 } else if (type.isPointerType()) { 719 return field.getAddress(addr); 720 } else if (type.isOopType()) { 721 return field.getOopHandle(addr); 722 } else { 723 return addr.addOffsetTo(field.offset); 724 } 725 } 726 727 // returns name-value of pairs of VM type at given address. 728 // If address is unspecified, reads static fields as name-value pairs. 729 function readVMType(type, addr) { 730 if (typeof(type) == 'string') { 731 type = findVMType(type); 732 } 733 if (addr != undefined) { 734 addr = any2addr(addr); 735 } 736 737 var result = new Object(); 738 var staticOnly = (addr == undefined); 739 while (type != null) { 740 var itr = type.fields; 741 while (itr.hasNext()) { 742 var field = itr.next(); 743 var isStatic = field.isStatic(); 744 if (staticOnly && isStatic) { 745 result[field.name] = readVMStaticField(field); 746 } else if (!staticOnly && !isStatic) { 747 result[field.name] = readVMInstanceField(field, addr); 748 } 749 } 750 type = type.superclass; 751 } 752 return result; 753 } 754 755 function printVMType(type, addr) { 756 if (typeof(type) == 'string') { 757 type = findVMType(type); 758 } 759 var obj = readVMType(type, addr); 760 while (type != null) { 761 var itr = type.fields; 762 while (itr.hasNext()) { 763 var field = itr.next(); 764 var name = field.name; 765 var value = obj[name]; 766 if (value != undefined) { 767 writeln(field.type.name, type.name + '::' + name, '=', value); 768 } 769 } 770 type = type.superclass; 771 } 772 } 773 774 // define readXXX and printXXX functions for each VM struct/class Type 775 tmp = new Object(); 776 tmp.itr = sa.typedb.types; 777 while (tmp.itr.hasNext()) { 778 tmp.type = tmp.itr.next(); 779 tmp.name = tmp.type.name; 780 if (tmp.type.isPointerType() || tmp.type.isOopType() || 781 tmp.type.isCIntegerType() || tmp.type.isJavaPrimitiveType() || 782 tmp.name.equals('address') || 783 tmp.name.equals("<opaque>")) { 784 // ignore; 785 continue; 786 } else { 787 // some type names have ':', '<', '>', '*', ' '. replace to make it as a 788 // JavaScript identifier 789 tmp.name = ("" + tmp.name).replace(/[:<>* ]/g, '_'); 790 eval("function read" + tmp.name + "(addr) {" + 791 " return readVMType('" + tmp.name + "', addr);}"); 792 eval("function print" + tmp.name + "(addr) {" + 793 " printVMType('" + tmp.name + "', addr); }"); 794 795 /* FIXME: do we need this? 796 if (typeof(registerCommand) != 'undefined') { 797 var name = "print" + tmp.name; 798 registerCommand(name, name + " [address]", name); 799 } 800 */ 801 } 802 } 803 //clean-up the temporary 804 delete tmp; 805 806 // VMObject factory 807 808 // VM type to SA class map 809 var vmType2Class = new Object(); 810 811 // C2 only classes 812 try{ 813 vmType2Class["ExceptionBlob"] = sapkg.code.ExceptionBlob; 814 vmType2Class["UncommonTrapBlob"] = sapkg.code.UncommonTrapBlob; 815 } catch(e) { 816 // Ignore exception. C2 specific objects might be not 817 // available in client VM 818 } 819 820 821 // This is *not* exhaustive. Add more if needed. 822 // code blobs 823 vmType2Class["BufferBlob"] = sapkg.code.BufferBlob; 824 vmType2Class["nmethod"] = sapkg.code.NMethod; 825 vmType2Class["RuntimeStub"] = sapkg.code.RuntimeStub; 826 vmType2Class["SafepointBlob"] = sapkg.code.SafepointBlob; 827 vmType2Class["C2IAdapter"] = sapkg.code.C2IAdapter; 828 vmType2Class["DeoptimizationBlob"] = sapkg.code.DeoptimizationBlob; 829 vmType2Class["I2CAdapter"] = sapkg.code.I2CAdapter; 830 vmType2Class["OSRAdapter"] = sapkg.code.OSRAdapter; 831 vmType2Class["PCDesc"] = sapkg.code.PCDesc; 832 833 // interpreter 834 vmType2Class["InterpreterCodelet"] = sapkg.interpreter.InterpreterCodelet; 835 836 // Java Threads 837 vmType2Class["JavaThread"] = sapkg.runtime.JavaThread; 838 vmType2Class["CompilerThread"] = sapkg.runtime.CompilerThread; 839 vmType2Class["CodeCacheSweeperThread"] = sapkg.runtime.CodeCacheSweeperThread; 840 vmType2Class["DebuggerThread"] = sapkg.runtime.DebuggerThread; 841 842 // gc 843 vmType2Class["GenCollectedHeap"] = sapkg.memory.GenCollectedHeap; 844 vmType2Class["DefNewGeneration"] = sapkg.memory.DefNewGeneration; 845 vmType2Class["TenuredGeneration"] = sapkg.memory.TenuredGeneration; 846 847 // generic VMObject factory for a given address 848 // This is equivalent to VirtualConstructor. 849 function newVMObject(addr) { 850 addr = any2addr(addr); 851 var result = null; 852 forEachVMType(function (type) { 853 if (isOfVMType(addr, type)) { 854 var clazz = vmType2Class[type.name]; 855 if (clazz != undefined) { 856 result = new clazz(addr); 857 } 858 return false; 859 } else { 860 return true; 861 } 862 }); 863 return result; 864 } 865 866 function vmobj2addr(vmobj) { 867 return vmobj.address; 868 } 869 870 function addr2vmobj(addr) { 871 return newVMObject(addr); 872 } 873 874 // Miscellaneous utilities 875 876 // returns PointerLocation that describes the given pointer 877 function findPtr(addr) { 878 addr = any2addr(addr); 879 return sapkg.utilities.PointerFinder.find(addr); 880 } 881 882 // is given address a valid Oop? 883 function isOop(addr) { 884 addr = any2addr(addr); 885 var oopHandle = addr.addOffsetToAsOopHandle(0); 886 return sapkg.utilities.RobustOopDeterminator.oopLooksValid(oopHandle); 887 } 888 889 // returns description of given pointer as a String 890 function whatis(addr) { 891 addr = any2addr(addr); 892 var ptrLoc = findPtr(addr); 893 if (!ptrLoc.isUnknown()) { 894 return ptrLoc.toString(); 895 } 896 897 var vmType = vmTypeof(addr); 898 if (vmType != null) { 899 return "pointer to " + vmType.name; 900 } 901 902 var dso = loadObjectContainingPC(addr); 903 if (dso == null) { 904 return ptrLoc.toString(); 905 } 906 907 var sym = dso.closestSymbolToPC(addr); 908 if (sym != null) { 909 return sym.name + '+' + sym.offset; 910 } 911 912 var s = dso.getName(); 913 var p = s.lastIndexOf("/"); 914 var base = dso.getBase(); 915 return s.substring(p+1, s.length) + '+' + addr.minus(base); 916 }