Path: blob/master/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/asm/Disassembler.java
41161 views
/*1* Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324package sun.jvm.hotspot.asm;2526import java.io.PrintStream;27import java.nio.file.Path;28import java.util.List;29import java.util.Iterator;30import java.util.Properties;31import sun.jvm.hotspot.code.CodeBlob;32import sun.jvm.hotspot.code.NMethod;33import sun.jvm.hotspot.debugger.Address;34import sun.jvm.hotspot.debugger.DebuggerException;35import sun.jvm.hotspot.runtime.VM;3637public class Disassembler {38private static String options = "";39private static long decode_function;4041protected long startPc;42protected byte[] code;43private CodeBlob blob;44private NMethod nmethod;4546public static void decode(InstructionVisitor visitor, CodeBlob blob) {47decode(visitor, blob, blob.codeBegin(), blob.codeEnd());48}4950public static void decode(InstructionVisitor visitor, CodeBlob blob, Address begin, Address end) {51int codeSize = (int)end.minus(begin);52long startPc = VM.getAddressValue(begin);53byte[] code = new byte[codeSize];54for (int i = 0; i < code.length; i++)55code[i] = begin.getJByteAt(i);56Disassembler dis = new Disassembler(startPc, code);57dis.decode(visitor);58}5960private Disassembler(long startPc, byte[] code) {61this.startPc = startPc;62this.code = code;6364// Lazily load hsdis65if (decode_function == 0) {66// Search for hsdis library in the following 4 locations:67// 1. <home>/lib/<vm>/libhsdis-<arch>.so68// 2. <home>/lib/<vm>/hsdis-<arch>.so69// 3. <home>/lib/hsdis-<arch>.so70// 4. hsdis-<arch>.so (using LD_LIBRARY_PATH)71Properties targetSysProps = VM.getVM().getSystemProperties();72String os = targetSysProps.getProperty("os.name");73String ext = ".so";74if (os.contains("Windows")) {75ext = ".dll";76} else if (os.contains("Mac OS")) {77ext = ".dylib";78}7980// Find the full path to libjvm.so (jvm.dll and libjvm.dylib on Windows and OSX).81String jvmPattern = "^(lib)?jvm\\" + ext + "$";82Path jvmPath = VM.getVM()83.getDebugger()84.getCDebugger()85.getLoadObjectList()86.stream()87.map(o -> Path.of(o.getName()))88.filter(p -> p.getFileName().toString().matches(jvmPattern))89.findAny()90.get();9192String arch = targetSysProps.getProperty("os.arch");93String libname = "hsdis-" + arch + ext;9495List<String> libs = List.of(96// 1. <home>/lib/<vm>/libhsdis-<arch>.so97jvmPath.resolveSibling("lib" + libname).toString(),98// 2. <home>/lib/<vm>/hsdis-<arch>.so99jvmPath.resolveSibling(libname).toString(),100// 3. <home>/lib/hsdis-<arch>.so101jvmPath.getParent().resolveSibling(libname).toString(),102// 4. hsdis-<arch>.so (using LD_LIBRARY_PATH)103libname104);105106var itr = libs.iterator();107while (itr.hasNext() && (decode_function == 0L)) {108try {109decode_function = load_library(itr.next());110} catch (DebuggerException e) {111if (!itr.hasNext()) {112throw e;113}114}115}116}117}118119private static native long load_library(String hsdis_library_name);120121private native void decode(InstructionVisitor visitor, long pc, byte[] code,122String options, long decode_function);123124private void decode(InstructionVisitor visitor) {125visitor.prologue();126decode(visitor, startPc, code, options, decode_function);127visitor.epilogue();128}129130private boolean match(String event, String tag) {131if (!event.startsWith(tag))132return false;133int taglen = tag.length();134if (taglen == event.length()) return true;135char delim = event.charAt(taglen);136return delim == ' ' || delim == '/' || delim == '=';137}138139// This is called from the native code to process various markers140// in the dissassembly.141private long handleEvent(InstructionVisitor visitor, String event, long arg) {142if (match(event, "insn")) {143try {144visitor.beginInstruction(arg);145} catch (Throwable e) {146e.printStackTrace();147}148} else if (match(event, "/insn")) {149try {150visitor.endInstruction(arg);151} catch (Throwable e) {152e.printStackTrace();153}154} else if (match(event, "addr")) {155if (arg != 0) {156visitor.printAddress(arg);157}158return arg;159} else if (match(event, "mach")) {160// output().printf("[Disassembling for mach='%s']\n", arg);161} else {162// ignore unrecognized markup163}164return 0;165}166167// This called from the native code to perform printing168private void rawPrint(InstructionVisitor visitor, String s) {169visitor.print(s);170}171}172173174