001/* 002 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 004 * 005 * This code is free software; you can redistribute it and/or modify it 006 * under the terms of the GNU General Public License version 2 only, as 007 * published by the Free Software Foundation. 008 * 009 * This code is distributed in the hope that it will be useful, but WITHOUT 010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 011 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 012 * version 2 for more details (a copy is included in the LICENSE file that 013 * accompanied this code). 014 * 015 * You should have received a copy of the GNU General Public License version 016 * 2 along with this work; if not, write to the Free Software Foundation, 017 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 018 * 019 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 020 * or visit www.oracle.com if you need additional information or have any 021 * questions. 022 */ 023package com.oracle.graal.code; 024 025import java.lang.reflect.*; 026import java.util.*; 027 028import jdk.internal.jvmci.code.*; 029import jdk.internal.jvmci.code.CodeUtil.*; 030import jdk.internal.jvmci.code.CompilationResult.*; 031import jdk.internal.jvmci.service.*; 032 033/** 034 * {@link HexCodeFile} based implementation of {@link DisassemblerProvider}. 035 */ 036@ServiceProvider(DisassemblerProvider.class) 037public class HexCodeFileDisassemblerProvider implements DisassemblerProvider { 038 039 @Override 040 public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) { 041 assert compResult != null; 042 return disassemble(codeCache, compResult, null); 043 } 044 045 public String getName() { 046 return "hcf"; 047 } 048 049 @Override 050 public String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) { 051 assert installedCode != null; 052 return installedCode.isValid() ? disassemble(codeCache, compResult, installedCode) : null; 053 } 054 055 private static String disassemble(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode installedCode) { 056 TargetDescription target = codeCache.getTarget(); 057 RegisterConfig regConfig = codeCache.getRegisterConfig(); 058 byte[] code = installedCode == null ? Arrays.copyOf(compResult.getTargetCode(), compResult.getTargetCodeSize()) : installedCode.getCode(); 059 if (code == null) { 060 // Method was deoptimized/invalidated 061 return ""; 062 } 063 long start = installedCode == null ? 0L : installedCode.getStart(); 064 HexCodeFile hcf = new HexCodeFile(code, start, target.arch.getName(), target.wordSize * 8); 065 if (compResult != null) { 066 HexCodeFile.addAnnotations(hcf, compResult.getAnnotations()); 067 addExceptionHandlersComment(compResult, hcf); 068 Register fp = regConfig.getFrameRegister(); 069 RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.arch, target.wordSize, fp, 0); 070 for (Infopoint infopoint : compResult.getInfopoints()) { 071 if (infopoint instanceof Call) { 072 Call call = (Call) infopoint; 073 if (call.debugInfo != null) { 074 hcf.addComment(call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); 075 } 076 addOperandComment(hcf, call.pcOffset, "{" + codeCache.getTargetName(call) + "}"); 077 } else { 078 if (infopoint.debugInfo != null) { 079 hcf.addComment(infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString()); 080 } 081 addOperandComment(hcf, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}"); 082 } 083 } 084 for (DataPatch site : compResult.getDataPatches()) { 085 hcf.addOperandComment(site.pcOffset, "{" + site.reference.toString() + "}"); 086 } 087 for (Mark mark : compResult.getMarks()) { 088 hcf.addComment(mark.pcOffset, codeCache.getMarkName(mark)); 089 } 090 } 091 String hcfEmbeddedString = hcf.toEmbeddedString(); 092 return HexCodeFileDisTool.tryDisassemble(hcfEmbeddedString); 093 } 094 095 private static void addExceptionHandlersComment(CompilationResult compResult, HexCodeFile hcf) { 096 if (!compResult.getExceptionHandlers().isEmpty()) { 097 String nl = HexCodeFile.NEW_LINE; 098 StringBuilder buf = new StringBuilder("------ Exception Handlers ------").append(nl); 099 for (CompilationResult.ExceptionHandler e : compResult.getExceptionHandlers()) { 100 buf.append(" ").append(e.pcOffset).append(" -> ").append(e.handlerPos).append(nl); 101 hcf.addComment(e.pcOffset, "[exception -> " + e.handlerPos + "]"); 102 hcf.addComment(e.handlerPos, "[exception handler for " + e.pcOffset + "]"); 103 } 104 hcf.addComment(0, buf.toString()); 105 } 106 } 107 108 private static void addOperandComment(HexCodeFile hcf, int pos, String comment) { 109 String oldValue = hcf.addOperandComment(pos, comment); 110 assert oldValue == null : "multiple comments for operand of instruction at " + pos + ": " + comment + ", " + oldValue; 111 } 112 113 /** 114 * Interface to the tool for disassembling an {@link HexCodeFile#toEmbeddedString() embedded} 115 * {@link HexCodeFile}. 116 */ 117 static class HexCodeFileDisTool { 118 static final Method processMethod; 119 static { 120 Method toolMethod = null; 121 try { 122 Class<?> toolClass = Class.forName("com.oracle.max.hcfdis.HexCodeFileDis", true, ClassLoader.getSystemClassLoader()); 123 toolMethod = toolClass.getDeclaredMethod("processEmbeddedString", String.class); 124 } catch (Exception e) { 125 // Tool not available on the class path 126 } 127 processMethod = toolMethod; 128 } 129 130 public static String tryDisassemble(String hcfEmbeddedString) { 131 if (processMethod != null) { 132 try { 133 return (String) processMethod.invoke(null, hcfEmbeddedString); 134 } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { 135 // If the tool is available, for now let's be noisy when it fails 136 throw new InternalError(e); 137 } 138 } 139 return hcfEmbeddedString; 140 } 141 } 142 143}