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