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