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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.asm; 26 27 public abstract class Disassembler { 28 protected long startPc; 29 protected byte[] code; 30 31 public Disassembler(long startPc, byte[] code) { 32 this.startPc = startPc; 33 this.code = code; 34 } 35 36 public long getStartPC() { 37 return startPc; 38 } 39 40 public byte[] getCode() { 41 return code; 42 } 43 44 public abstract void decode(InstructionVisitor visitor); 45 } | 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.asm; 26 27 import java.io.PrintStream; 28 import java.util.Observer; 29 import java.util.Observable; 30 import sun.jvm.hotspot.code.CodeBlob; 31 import sun.jvm.hotspot.code.NMethod; 32 import sun.jvm.hotspot.debugger.Address; 33 import sun.jvm.hotspot.runtime.VM; 34 35 public class Disassembler { 36 static final int COMMENT_COLUMN = 40; 37 static final String BYTES_COMMENT = ";..."; /* funky byte display comment */ 38 39 private static String libname; 40 private static String options; 41 private static long decode_function; 42 private static int instructionAlignment; 43 44 static { 45 VM.registerVMInitializedObserver(new Observer() { 46 public void update(Observable o, Object data) { 47 options = ""; 48 instructionAlignment = 1; 49 libname = null; 50 String cpu = VM.getVM().getCPU(); 51 if (cpu.equals("sparc")) { 52 libname = "hsdis-sparc"; 53 instructionAlignment = 4; 54 if (VM.getVM().isLP64()) { 55 options = "v9only"; 56 } 57 } else if (cpu.equals("x86")) { 58 libname = "hsdis-i386"; 59 } else if (cpu.equals("amd64")) { 60 libname = "hsdis-amd64"; 61 } else if (cpu.equals("ia64")) { 62 libname = "hsdis-ia64"; 63 } 64 } 65 }); 66 } 67 68 protected long startPc; 69 protected byte[] code; 70 private String _option_buf = ""; 71 private boolean _print_pc; 72 private long _cur_insn; 73 private int _bytes_per_line; // arch-specific formatting option 74 private CodeBlob blob; 75 private NMethod nmethod; 76 private int instruction_alignment; 77 78 public static void decode(InstructionVisitor visitor, CodeBlob blob) { 79 decode(visitor, blob, blob.instructionsBegin(), blob.instructionsEnd()); 80 } 81 82 public static void decode(InstructionVisitor visitor, CodeBlob blob, Address begin, Address end) { 83 int codeSize = (int)end.minus(begin); 84 long startPc = addressToLong(begin); 85 byte[] code = new byte[codeSize]; 86 for (int i = 0; i < code.length; i++) 87 code[i] = begin.getJByteAt(i); 88 Disassembler dis = new Disassembler(startPc, code); 89 dis.decode(visitor); 90 } 91 92 private Disassembler(long startPc, byte[] code) { 93 this.startPc = startPc; 94 this.code = code; 95 96 // Lazily load hsdis 97 if (decode_function == 0) { 98 decode_function = load_library(libname); 99 if (decode_function == 0) { 100 throw new InternalError("Can't open " + libname); 101 } 102 } 103 } 104 105 public long getStartPC() { 106 return startPc; 107 } 108 109 public byte[] getCode() { 110 return code; 111 } 112 113 private static native long load_library(String hsdis_library_name); 114 115 private native void decode(InstructionVisitor visitor, long pc, byte[] code, 116 String options, long decode_function); 117 118 private void decode(InstructionVisitor visitor) { 119 visitor.prologue(); 120 decode(visitor, startPc, code, options, decode_function); 121 visitor.epilogue(); 122 } 123 124 private boolean match(String event, String tag) { 125 if (!event.startsWith(tag)) 126 return false; 127 int taglen = tag.length(); 128 if (taglen == event.length()) return true; 129 char delim = event.charAt(taglen); 130 return delim == ' ' || delim == '/' || delim == '='; 131 } 132 133 private long handle_event(InstructionVisitor visitor, String event, long arg) { 134 if (match(event, "insn")) { 135 start_insn(visitor, arg); 136 } else if (match(event, "/insn")) { 137 end_insn(visitor, arg); 138 } else if (match(event, "addr")) { 139 if (arg != 0) { 140 print_address(visitor, arg); 141 return arg; 142 } 143 } else if (match(event, "mach")) { 144 // output().printf("[Disassembling for mach='%s']\n", arg); 145 } else if (match(event, "format bytes-per-line")) { 146 _bytes_per_line = (int)arg; 147 } else { 148 // ignore unrecognized markup 149 } 150 return 0; 151 } 152 153 void start_insn(InstructionVisitor visitor, long pc) { 154 _cur_insn = pc; 155 print_insn_labels(visitor); 156 visitor.beginInstruction(pc); 157 } 158 159 void end_insn(InstructionVisitor visitor, long pc) { 160 long pc0 = _cur_insn; 161 if (nmethod != null) 162 print_code_comment_on(visitor, COMMENT_COLUMN, pc0, pc); 163 visitor.endInstruction(pc); 164 } 165 166 long cur_insn() { return _cur_insn; } 167 168 protected static long addressToLong(sun.jvm.hotspot.debugger.Address addr) { 169 return VM.getVM().getDebugger().getAddressValue(addr); 170 } 171 172 void print_insn_labels(InstructionVisitor visitor) { 173 long p = cur_insn(); 174 if (nmethod != null) { 175 if (p == addressToLong(nmethod.getEntryPoint())) visitor.print("[Entry Point]\n"); 176 if (p == addressToLong(nmethod.getVerifiedEntryPoint())) visitor.print("[Verified Entry Point]\n"); 177 if (p == addressToLong(nmethod.exceptionBegin())) visitor.print("[Exception Handler]\n"); 178 if (p == addressToLong(nmethod.stubBegin())) visitor.print("[Stub Code]\n"); 179 // if (p == addressToLong(nmethod.getConstsBegin())) visitor.print("[Constants]\n"); 180 } 181 CodeBlob cb = blob; 182 // if (cb != null) { 183 // cb.print_block_comment(st, (long)(p - addressToLong(cb.instructionsBegin()))); 184 // } 185 if (_print_pc) { 186 visitor.print(" " + p + ": "); 187 } 188 } 189 190 public void raw_print(InstructionVisitor visitor, String s) { 191 visitor.print(s); 192 } 193 194 public void print_address(InstructionVisitor visitor, long adr) { 195 if (adr == 0) { 196 visitor.print("NULL"); 197 return; 198 } 199 200 int small_num = (int)adr; 201 if (adr == small_num && -1 <= small_num && small_num <= 9) { 202 visitor.print(Integer.toString(small_num)); 203 return; 204 } 205 206 207 // if (StubRoutines::contains(adr)) { 208 // StubCodeDesc* desc = StubCodeDesc::desc_for(adr); 209 // if (desc == null) 210 // desc = StubCodeDesc::desc_for(adr + frame::pc_return_offset); 211 // if (desc != null) { 212 // visitor.print("Stub::%s", desc.name()); 213 // if (desc.begin() != adr) 214 // visitor.print("%+d 0x%p",adr - desc.begin(), adr); 215 // else if (WizardMode) visitor.print(" " INTPTR_FORMAT, adr); 216 // return; 217 // } 218 // visitor.print("Stub::<unknown> " INTPTR_FORMAT, adr); 219 // return; 220 // } 221 // 222 // BarrierSet* bs = Universe::heap().barrier_set(); 223 // if (bs.kind() == BarrierSet::CardTableModRef && 224 // adr == (address)((CardTableModRefBS*)(bs)).byte_map_base) { 225 // visitor.print("word_map_base"); 226 // if (WizardMode) visitor.print(" " INTPTR_FORMAT, (long)adr); 227 // return; 228 // } 229 // 230 // Oop obj; 231 // if (nmethod != null && 232 // (obj = nmethod.embeddedOop_at(cur_insn())) != null && 233 // addresstoLong(obj) == adr) { 234 // obj.printValueOn(st); 235 // return; 236 // } 237 238 // Fall through to a simple numeral. 239 visitor.printAddress(adr); 240 } 241 242 void print_code_comment_on(InstructionVisitor visitor, int column, long begin, long end) { 243 // // First, find an oopmap in (begin, end]. 244 // // We use the odd half-closed interval so that oop maps and scope descs 245 // // which are tied to the byte after a call are printed with the call itself. 246 // Address base = nm.instructionsBegin(); 247 // OopMapSet oms = nm.oop_maps(); 248 // if (oms != null) { 249 // for (int i = 0, imax = oms.size(); i < imax; i++) { 250 // OopMap* om = oms.at(i); 251 // address pc = base + om.offset(); 252 // if (pc > begin) { 253 // if (pc <= end) { 254 // st.move_to(column); 255 // st.print("; "); 256 // om.print_on(st); 257 // } 258 // break; 259 // } 260 // } 261 // } 262 263 // // Print any debug info present at this pc. 264 // ScopeDesc* sd = scope_desc_in(begin, end); 265 // if (sd != null) { 266 // st.move_to(column); 267 // if (sd.bci() == SynchronizationEntryBCI) { 268 // st.print(";*synchronization entry"); 269 // } else { 270 // if (sd.method().is_null()) { 271 // st.print("method is null"); 272 // } else if (sd.method().is_native()) { 273 // st.print("method is native"); 274 // } else { 275 // address bcp = sd.method().bcp_from(sd.bci()); 276 // Bytecodes::Code bc = Bytecodes::java_code_at(bcp); 277 // st.print(";*%s", Bytecodes::name(bc)); 278 // switch (bc) { 279 // case Bytecodes::_invokevirtual: 280 // case Bytecodes::_invokespecial: 281 // case Bytecodes::_invokestatic: 282 // case Bytecodes::_invokeinterface: 283 // { 284 // Bytecode_invoke* invoke = Bytecode_invoke_at(sd.method(), sd.bci()); 285 // st.print(" "); 286 // if (invoke.name() != null) 287 // invoke.name().print_symbol_on(st); 288 // else 289 // st.print("<UNKNOWN>"); 290 // break; 291 // } 292 // case Bytecodes::_getfield: 293 // case Bytecodes::_putfield: 294 // case Bytecodes::_getstatic: 295 // case Bytecodes::_putstatic: 296 // { 297 // methodHandle sdm = sd.method(); 298 // Bytecode_field* field = Bytecode_field_at(sdm(), sdm.bcp_from(sd.bci())); 299 // constantPoolOop sdmc = sdm.constants(); 300 // symbolOop name = sdmc.name_ref_at(field.index()); 301 // st.print(" "); 302 // if (name != null) 303 // name.print_symbol_on(st); 304 // else 305 // st.print("<UNKNOWN>"); 306 // } 307 // } 308 // } 309 // } 310 311 // // Print all scopes 312 // for (;sd != null; sd = sd.sender()) { 313 // st.move_to(column); 314 // st.print("; -"); 315 // if (sd.method().is_null()) { 316 // st.print("method is null"); 317 // } else { 318 // sd.method().print_short_name(st); 319 // } 320 // int lineno = sd.method().line_number_from_bci(sd.bci()); 321 // if (lineno != -1) { 322 // st.print("@%d (line %d)", sd.bci(), lineno); 323 // } else { 324 // st.print("@%d", sd.bci()); 325 // } 326 // st.println(); 327 // } 328 // } 329 330 // // Print relocation information 331 // const char* str = reloc_string_for(begin, end); 332 // if (str != null) { 333 // if (sd != null) st.println(); 334 // st.move_to(column); 335 // st.print("; {%s}", str); 336 // } 337 // int cont_offset = ImplicitExceptionTable(this).at(begin - instructions_begin()); 338 // if (cont_offset != 0) { 339 // st.move_to(column); 340 // st.print("; implicit exception: dispatches to " INTPTR_FORMAT, instructions_begin() + cont_offset); 341 // } 342 343 } 344 345 } |