1 /* 2 * Copyright (c) 2019, 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 org.graalvm.compiler.hotspot.meta; 26 27 import java.io.BufferedReader; 28 import java.io.File; 29 import java.io.FileOutputStream; 30 import java.io.IOException; 31 import java.io.InputStream; 32 import java.io.InputStreamReader; 33 import java.util.HashMap; 34 import java.util.Map; 35 import java.util.regex.Matcher; 36 import java.util.regex.Pattern; 37 38 import org.graalvm.compiler.code.CompilationResult; 39 import org.graalvm.compiler.code.CompilationResult.CodeAnnotation; 40 import org.graalvm.compiler.code.DisassemblerProvider; 41 import org.graalvm.compiler.serviceprovider.ServiceProvider; 42 43 import jdk.vm.ci.code.CodeCacheProvider; 44 import jdk.vm.ci.code.CodeUtil; 45 import jdk.vm.ci.code.CodeUtil.DefaultRefMapFormatter; 46 import jdk.vm.ci.code.CodeUtil.RefMapFormatter; 47 import jdk.vm.ci.code.InstalledCode; 48 import jdk.vm.ci.code.Register; 49 import jdk.vm.ci.code.RegisterConfig; 50 import jdk.vm.ci.code.TargetDescription; 51 import jdk.vm.ci.code.site.Call; 52 import jdk.vm.ci.code.site.DataPatch; 53 import jdk.vm.ci.code.site.Infopoint; 54 import jdk.vm.ci.code.site.Mark; 55 import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; 56 import jdk.vm.ci.services.Services; 57 58 /** 59 * This disassembles the code immediatly with objdump. 60 */ 61 @ServiceProvider(DisassemblerProvider.class) 62 public class HotSpotObjdumpDisassemblerProvider extends HotSpotDisassemblerProvider { 63 64 /** 65 * Uses objdump to disassemble the compiled code. 66 */ 67 @Override 68 public String disassembleCompiledCode(CodeCacheProvider codeCache, CompilationResult compResult) { 69 File tmp = null; 70 try { 71 tmp = File.createTempFile("compiledBinary", ".bin"); 72 try (FileOutputStream fos = new FileOutputStream(tmp)) { 73 fos.write(compResult.getTargetCode()); 74 } 75 String[] cmdline; 76 String arch = Services.getSavedProperties().get("os.arch"); 77 if (arch.equals("amd64")) { 78 cmdline = new String[]{"objdump", "-D", "-b", "binary", "-M", "x86-64", "-m", "i386", tmp.getAbsolutePath()}; 79 } else if (arch.equals("aarch64")) { 80 cmdline = new String[]{"objdump", "-D", "-b", "binary", "-m", "aarch64", tmp.getAbsolutePath()}; 81 } else { 82 return null; 83 } 84 85 Pattern p = Pattern.compile(" *(([0-9a-fA-F]+):\t.*)"); 86 87 TargetDescription target = codeCache.getTarget(); 88 RegisterConfig regConfig = codeCache.getRegisterConfig(); 89 Register fp = regConfig.getFrameRegister(); 90 RefMapFormatter slotFormatter = new DefaultRefMapFormatter(target.wordSize, fp, 0); 91 92 Map<Integer, String> annotations = new HashMap<>(); 93 for (DataPatch site : compResult.getDataPatches()) { 94 putAnnotation(annotations, site.pcOffset, "{" + site.reference.toString() + "}"); 95 } 96 for (Mark mark : compResult.getMarks()) { 97 putAnnotation(annotations, mark.pcOffset, codeCache.getMarkName(mark)); 98 } 99 for (CodeAnnotation a : compResult.getCodeAnnotations()) { 100 putAnnotation(annotations, a.position, a.toString()); 101 } 102 for (Infopoint infopoint : compResult.getInfopoints()) { 103 if (infopoint instanceof Call) { 104 Call call = (Call) infopoint; 105 if (call.debugInfo != null) { 106 putAnnotation(annotations, call.pcOffset + call.size, CodeUtil.append(new StringBuilder(100), call.debugInfo, slotFormatter).toString()); 107 } 108 putAnnotation(annotations, call.pcOffset, "{" + codeCache.getTargetName(call) + "}"); 109 } else { 110 if (infopoint.debugInfo != null) { 111 putAnnotation(annotations, infopoint.pcOffset, CodeUtil.append(new StringBuilder(100), infopoint.debugInfo, slotFormatter).toString()); 112 } 113 putAnnotation(annotations, infopoint.pcOffset, "{infopoint: " + infopoint.reason + "}"); 114 } 115 } 116 117 Process proc = Runtime.getRuntime().exec(cmdline); 118 InputStream is = proc.getInputStream(); 119 120 InputStreamReader isr = new InputStreamReader(is); 121 BufferedReader br = new BufferedReader(isr); 122 String line; 123 124 StringBuilder sb = new StringBuilder(); 125 while ((line = br.readLine()) != null) { 126 Matcher m = p.matcher(line); 127 if (m.find()) { 128 int address = Integer.parseInt(m.group(2), 16); 129 String annotation = annotations.get(address); 130 if (annotation != null) { 131 annotation = annotation.replace("\n", "\n; "); 132 sb.append("; ").append(annotation).append('\n'); 133 } 134 line = m.replaceAll("0x$1"); 135 } 136 sb.append(line).append("\n"); 137 } 138 BufferedReader ebr = new BufferedReader(new InputStreamReader(proc.getErrorStream())); 139 while ((line = ebr.readLine()) != null) { 140 System.err.println(line); 141 } 142 ebr.close(); 143 return sb.toString(); 144 } catch (IOException e) { 145 if (tmp != null) { 146 tmp.delete(); 147 } 148 e.printStackTrace(); 149 return null; 150 } 151 } 152 153 private static void putAnnotation(Map<Integer, String> annotations, int idx, String txt) { 154 String newAnnoation = annotations.getOrDefault(idx, "") + "\n" + txt; 155 annotations.put(idx, newAnnoation); 156 } 157 158 @Override 159 public String disassembleInstalledCode(CodeCacheProvider codeCache, CompilationResult compResult, InstalledCode code) { 160 return ((HotSpotCodeCacheProvider) codeCache).disassemble(code); 161 } 162 163 @Override 164 public String getName() { 165 return "hsdis-objdump"; 166 } 167 }