1 /* 2 * Copyright (c) 2002, 2020, 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.asm; 26 27 import java.io.PrintStream; 28 import sun.jvm.hotspot.code.CodeBlob; 29 import sun.jvm.hotspot.code.NMethod; 30 import sun.jvm.hotspot.debugger.Address; 31 import sun.jvm.hotspot.runtime.VM; 32 33 public class Disassembler { 34 private static String options = ""; 35 private static long decode_function; 36 37 protected long startPc; 38 protected byte[] code; 39 private CodeBlob blob; 40 private NMethod nmethod; 41 42 public static void decode(InstructionVisitor visitor, CodeBlob blob) { 43 decode(visitor, blob, blob.codeBegin(), blob.codeEnd()); 44 } 45 46 public static void decode(InstructionVisitor visitor, CodeBlob blob, Address begin, Address end) { 47 int codeSize = (int)end.minus(begin); 48 long startPc = VM.getAddressValue(begin); 49 byte[] code = new byte[codeSize]; 50 for (int i = 0; i < code.length; i++) 51 code[i] = begin.getJByteAt(i); 52 Disassembler dis = new Disassembler(startPc, code); 53 dis.decode(visitor); 54 } 55 56 private Disassembler(long startPc, byte[] code) { 57 this.startPc = startPc; 58 this.code = code; 59 60 // Lazily load hsdis 61 if (decode_function == 0) { 62 StringBuilder path = new StringBuilder(System.getProperty("java.home")); 63 String sep = System.getProperty("file.separator"); 64 String os = System.getProperty("os.name"); 65 String libname = "hsdis"; 66 String arch = System.getProperty("os.arch"); 67 if (os.lastIndexOf("Windows", 0) != -1) { 68 if (arch.equals("x86")) { 69 libname += "-i386"; 70 } else if (arch.equals("amd64")) { 71 libname += "-amd64"; 72 } else { 73 libname += "-" + arch; 74 } 75 path.append(sep + "bin" + sep); 76 libname += ".dll"; 77 } else if (os.lastIndexOf("Linux", 0) != -1) { 78 if (arch.equals("x86") || arch.equals("i386")) { 79 path.append(sep + "lib" + sep + "i386" + sep); 80 libname += "-i386.so"; 81 } else if (arch.equals("amd64") || arch.equals("x86_64")) { 82 path.append(sep + "lib" + sep + "amd64" + sep); 83 libname += "-amd64.so"; 84 } else { 85 path.append(sep + "lib" + sep + arch + sep); 86 libname += "-" + arch + ".so"; 87 } 88 } else if (os.lastIndexOf("Mac OS X", 0) != -1) { 89 path.append(sep + "lib" + sep); 90 libname += "-amd64" + ".dylib"; // x86_64 => amd64 91 } else { 92 path.append(sep + "lib" + sep + "arch" + sep); 93 libname += "-" + arch + ".so"; 94 } 95 decode_function = load_library(path.toString(), libname); 96 } 97 } 98 99 private static native long load_library(String installed_jrepath, String hsdis_library_name); 100 101 private native void decode(InstructionVisitor visitor, long pc, byte[] code, 102 String options, long decode_function); 103 104 private void decode(InstructionVisitor visitor) { 105 visitor.prologue(); 106 decode(visitor, startPc, code, options, decode_function); 107 visitor.epilogue(); 108 } 109 110 private boolean match(String event, String tag) { 111 if (!event.startsWith(tag)) 112 return false; 113 int taglen = tag.length(); 114 if (taglen == event.length()) return true; 115 char delim = event.charAt(taglen); 116 return delim == ' ' || delim == '/' || delim == '='; 117 } 118 119 // This is called from the native code to process various markers 120 // in the dissassembly. 121 private long handleEvent(InstructionVisitor visitor, String event, long arg) { 122 if (match(event, "insn")) { 123 try { 124 visitor.beginInstruction(arg); 125 } catch (Throwable e) { 126 e.printStackTrace(); 127 } 128 } else if (match(event, "/insn")) { 129 try { 130 visitor.endInstruction(arg); 131 } catch (Throwable e) { 132 e.printStackTrace(); 133 } 134 } else if (match(event, "addr")) { 135 if (arg != 0) { 136 visitor.printAddress(arg); 137 } 138 return arg; 139 } else if (match(event, "mach")) { 140 // output().printf("[Disassembling for mach='%s']\n", arg); 141 } else { 142 // ignore unrecognized markup 143 } 144 return 0; 145 } 146 147 // This called from the native code to perform printing 148 private void rawPrint(InstructionVisitor visitor, String s) { 149 visitor.print(s); 150 } 151 }