Path: blob/master/src/hotspot/share/compiler/abstractDisassembler.cpp
40930 views
/*1* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved.2* Copyright (c) 2019 SAP SE. 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 it6* under the terms of the GNU General Public License version 2 only, as7* published by the Free Software Foundation.8*9* This code is distributed in the hope that it will be useful, but WITHOUT10* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or11* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License12* version 2 for more details (a copy is included in the LICENSE file that13* accompanied this code).14*15* You should have received a copy of the GNU General Public License version16* 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 USA20* or visit www.oracle.com if you need additional information or have any21* questions.22*23*/2425// AbstractDisassembler is the base class for26// platform-specific Disassembler classes.2728#include "precompiled.hpp"29#include "asm/assembler.inline.hpp"30#include "compiler/abstractDisassembler.hpp"31#include "oops/oop.inline.hpp"32#include "utilities/debug.hpp"33#include "utilities/ostream.hpp"3435// Default values for what is being printed as line prefix when disassembling a single instruction.36// Can be overridden by command line parameter PrintAssemblyOptions.37bool AbstractDisassembler::_show_data_hex = true;38bool AbstractDisassembler::_show_data_int = false;39bool AbstractDisassembler::_show_data_float = false;40bool AbstractDisassembler::_align_instr = true;41bool AbstractDisassembler::_show_pc = true;42bool AbstractDisassembler::_show_offset = false;43bool AbstractDisassembler::_show_structs = true;44bool AbstractDisassembler::_show_comment = true;45bool AbstractDisassembler::_show_block_comment = true;4647// set "true" to see what's in memory bit by bit48// might prove cumbersome on platforms where instr_len is hard to find out49bool AbstractDisassembler::_show_bytes = false;5051// Return #bytes printed. Callers may use that for output alignment.52// Print instruction address, and offset from blob begin.53// Offset width (2, 4, 6, 8 bytes) is adapted to size of blob.54// Working assumption: we are at st->bol() upon entry. If not, it's the55// caller's responsibility to guarantee proper alignment.56int AbstractDisassembler::print_location(address here, address begin, address end, outputStream* st, bool align, bool print_header) {57const int pos_0 = st->position();5859if (show_pc() || show_offset()) {60st->print(" ");61}6263if (show_pc()) {64if (print_header) {65st->print(" %*s", 18, "Address");66} else {67st->print(" " PTR_FORMAT, p2i(here));68}69}7071if (show_offset()) {72#ifdef ASSERT73if ((uintptr_t)begin > (uintptr_t)here) st->print(">>begin(" PTR_FORMAT ") > here(" PTR_FORMAT ")<<", p2i(begin), p2i(here));74if ((uintptr_t)end < (uintptr_t)here) st->print(">> end(" PTR_FORMAT ") < here(" PTR_FORMAT ")<<", p2i(end), p2i(here));75assert((uintptr_t)begin <= (uintptr_t)end, "inverted address range");76#endif77const int blob_len = end - begin;78const int offset = here - begin;79const int width = (blob_len < (1<< 8)) ? 2 : (blob_len < (1<<16)) ? 4 : (blob_len < (1<<24)) ? 6 : 8;80if (print_header) {81st->print(" %*s", width+5, "offset");82} else {83st->print(" (+0x%*.*x)", width, width, offset);84}85}8687if ((show_pc() || show_offset()) && !print_header) {88st->print(": ");89}9091if (align) {92const uint tabspacing = 8;93const uint pos = st->position();94const uint aligned_pos = ((pos+tabspacing-1)/tabspacing)*tabspacing /* - 1 */;95st->fill_to(aligned_pos);96}9798return st->position() - pos_0;99}100101102// Return #bytes printed. Callers may use that for output alignment.103// Print instruction in hexadecimal representation, using 2-byte blocks.104// Used with real disassemblies. Not so useful with abstract disassemblies.105int AbstractDisassembler::print_instruction(address here, int len, int max_len, outputStream* st, bool align, bool print_header) {106if (show_bytes()) {107const int block_bytes = 2;108const int pos_0 = st->position();109address pos = here;110111//---< print instruction bytes in blocks >---112// must print byte by byte: address might be unaligned.113for (; pos <= here + len - block_bytes; pos += block_bytes) {114for (address byte = pos; byte < pos + block_bytes; byte++) {115st->print("%2.2x", *byte);116}117st->print(" ");118}119120//---< Print the remaining bytes of the instruction >---121if ((len & (block_bytes - 1)) != 0) {122for (; pos < here + len; pos++) {123st->print("%2.2x", *pos);124}125}126127//---< filler for shorter than max_len instructions >---128for (int i = len+1; i < max_len; i++) {129st->print(" ");130}131132st->print(" "); // separator space.133print_delimiter(st);134return st->position() - pos_0;135}136137if (align) {138const uint tabspacing = 8;139const uint pos = st->position();140const uint aligned_pos = ((pos+tabspacing-1)/tabspacing)*tabspacing /* - 1 */;141st->fill_to(aligned_pos);142}143144return 0;145}146147148// Return #bytes printed. Callers may use that for output alignment.149// Print data (e.g. constant pool entries) in hex format.150// Depending on the alignment, short, int, and long entities are printed.151// If selected, data is formatted as int/long and float/double values in addition.152int AbstractDisassembler::print_hexdata(address here, int len, outputStream* st, bool print_header) {153const int tsize = 8;154const int pos_0 = st->position();155int pos = pos_0;156int align = ((pos+tsize-1)/tsize)*tsize;157st->fill_to(align);158159//---< printing hex data >---160if (show_data_hex()) {161switch (len) {162case 1: if (print_header) {163st->print("hex1");164} else {165st->print("0x%02x", *here);166}167st->fill_to(align += tsize);168case 2: if (print_header) {169st->print(" hex2");170} else {171if (((uintptr_t)(here)&0x01) == 0) {172st->print("0x%04x", *((jushort*)here));173}174}175st->fill_to(align += tsize);176case 4: if (print_header) {177st->print(" hex4");178} else {179if (((uintptr_t)(here)&0x03) == 0) {180st->print("0x%08x", *((juint*)here));181}182}183st->fill_to(align += 2*tsize);184case 8: if (print_header) {185st->print(" hex8");186} else {187if (((uintptr_t)(here)&0x07) == 0) {188st->print(PTR_FORMAT, *((uintptr_t*)here));189}190}191st->fill_to(align += 3*tsize);192break;193default: ;194}195pos = st->position();196align = ((pos+tsize-1)/tsize)*tsize;197st->fill_to(align);198}199200//---< printing int/long data >---201if (show_data_int()) {202switch (len) {203case 4: if (print_header) {204st->print(" int");205} else {206if (((uintptr_t)(here)&0x03) == 0) {207st->print("%12.1d", *((jint*)here));208}209}210st->fill_to(align += 2*tsize);211case 8: if (print_header) {212st->print(" long");213} else {214if (((uintptr_t)(here)&0x07) == 0) {215st->print(JLONG_FORMAT_W(23), *((jlong*)here));216}217}218st->fill_to(align += 3*tsize);219break;220default: ;221}222pos = st->position();223align = ((pos+tsize-1)/tsize)*tsize;224st->fill_to(align);225}226227//---< printing float/double data >---228if (show_data_float()) {229switch (len) {230case 4: if (print_header) {231st->print(" float");232} else {233if (((uintptr_t)(here)&0x03) == 0) {234st->print("%15.7e", (double)*((float*)here));235}236}237st->fill_to(align += 2*tsize);238case 8: if (print_header) {239st->print(" double");240} else {241if (((uintptr_t)(here)&0x07) == 0) {242st->print("%23.15e", *((double*)here));243}244}245st->fill_to(align += 3*tsize);246break;247default: ;248}249}250251return st->position() - pos_0;252}253254255// Return #bytes printed. Callers may use that for output alignment.256// Print an instruction delimiter.257int AbstractDisassembler::print_delimiter(outputStream* st) {258if (align_instr()) { st->print("| "); return 2; }259else return 0;260}261262263// Decodes the one instruction at address start in a platform-independent format.264// Returns the start of the next instruction (which is 'start' plus 'instruction_size_in_bytes').265// The parameter max_instr_size_in_bytes is used for output alignment purposes only.266address AbstractDisassembler::decode_instruction_abstract(address start,267outputStream* st,268const int instruction_size_in_bytes,269const int max_instr_size_in_bytes) {270assert(instruction_size_in_bytes > 0, "no zero-size instructions!");271assert(max_instr_size_in_bytes >= instruction_size_in_bytes, "inconsistent call parameters");272273//---< current instruction is at the start address >---274unsigned char* current = (unsigned char*) start;275int filler_limit = align_instr() ? max_instr_size_in_bytes : ((instruction_size_in_bytes+abstract_instruction_bytes_per_block-1)/abstract_instruction_bytes_per_block)276*abstract_instruction_bytes_per_block;277278//---< print the instruction's bytes >---279for (int i = 1; i <= instruction_size_in_bytes; i++) {280st->print("%02x", *current);281++current;282if (abstract_instruction_bytes_per_block <= max_instr_size_in_bytes) {283if (i%abstract_instruction_bytes_per_block == 0) st->print(" ");284} else {285if (i == instruction_size_in_bytes) st->print(" ");286}287}288289//---< print some filler spaces to column-align instructions >---290for (int i = instruction_size_in_bytes+1; i <= filler_limit; i++) {291st->print(" ");292if (abstract_instruction_bytes_per_block <= max_instr_size_in_bytes) {293if (i%abstract_instruction_bytes_per_block == 0) st->print(" ");294} else {295if (i == instruction_size_in_bytes) st->print(" ");296}297}298299//---< the address of the next instruction >---300return (address) current;301}302303304// Decodes all instructions in the given range [start..end)305// calling decode_instruction_abstract for each instruction.306// The format is platform dependent only to the extend that307// it respects the actual instruction length where possible.308// Does not print any markers or decorators.309void AbstractDisassembler::decode_range_abstract(address range_start, address range_end,310address start, address end,311outputStream* st,312const int max_instr_size_in_bytes) {313assert(st != NULL, "need an output stream (no default)!");314int idx = 0;315address pos = range_start;316317while ((pos != NULL) && (pos < range_end)) {318int instr_size_in_bytes = Assembler::instr_len(pos);319320if (idx == 0) print_location(pos, start, end, st, false, false);321else print_delimiter(st);322323//---< print the instruction's bytes >---324// don't access storage beyond end of range325if (pos + instr_size_in_bytes <= range_end) {326pos = decode_instruction_abstract(pos, st, instr_size_in_bytes, max_instr_size_in_bytes);327} else {328// If the range to be decoded contains garbage at the end (e.g. 0xcc initializer bytes),329// instruction size calculation may run out of sync. Just terminate in that case.330pos = range_end;331}332333idx += instr_size_in_bytes;334if (start_newline(idx)) {335st->cr();336idx = 0;337}338}339}340341342// Decodes all instructions in the given range [start..end).343// The output is enclosed in [MachCode] and [/MachCode] tags for later recognition.344// The format is platform dependent only to the extend that345// it respects the actual instruction length where possible.346void AbstractDisassembler::decode_abstract(address start, address end, outputStream* ost,347const int max_instr_size_in_bytes) {348int idx = 0;349address pos = start;350351outputStream* st = (ost == NULL) ? tty : ost;352353//---< Open the output (Marker for post-mortem disassembler) >---354st->bol();355st->print_cr("[MachCode]");356357decode_range_abstract(start, end, start, end, st, max_instr_size_in_bytes);358359//---< Close the output (Marker for post-mortem disassembler) >---360st->bol();361st->print_cr("[/MachCode]");362}363364365