comparison src/share/tools/hsdis/hsdis.c @ 6782:5a98bf7d847b

6879063: SA should use hsdis for disassembly Summary: We should in SA to use hsdis for it like the JVM does to replace the current java based disassembler. Reviewed-by: twisti, jrose, sla Contributed-by: yumin.qi@oracle.com
author minqi
date Mon, 24 Sep 2012 12:44:00 -0700
parents de34c646c3f7
children 3d701c802d01
comparison
equal deleted inserted replaced
6780:8440414b0fd8 6782:5a98bf7d847b
1 /* 1 /*
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 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 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
25 /* hsdis.c -- dump a range of addresses as native instructions 25 /* hsdis.c -- dump a range of addresses as native instructions
26 This implements the plugin protocol required by the 26 This implements the plugin protocol required by the
27 HotSpot PrintAssembly option. 27 HotSpot PrintAssembly option.
28 */ 28 */
29 29
30 #include "hsdis.h"
31
32 #include <sysdep.h>
33 #include <libiberty.h> 30 #include <libiberty.h>
34 #include <bfd.h> 31 #include <bfd.h>
35 #include <dis-asm.h> 32 #include <dis-asm.h>
36 #include <inttypes.h> 33 #include <inttypes.h>
34 #include <string.h>
35 #include <errno.h>
36 #include "hsdis.h"
37 37
38 #ifndef bool 38 #ifndef bool
39 #define bool int 39 #define bool int
40 #define true 1 40 #define true 1
41 #define false 0 41 #define false 0
45 typedef decode_instructions_event_callback_ftype event_callback_t; 45 typedef decode_instructions_event_callback_ftype event_callback_t;
46 typedef decode_instructions_printf_callback_ftype printf_callback_t; 46 typedef decode_instructions_printf_callback_ftype printf_callback_t;
47 47
48 /* disassemble_info.application_data object */ 48 /* disassemble_info.application_data object */
49 struct hsdis_app_data { 49 struct hsdis_app_data {
50 /* the arguments to decode_instructions */ 50 /* virtual address of data */
51 uintptr_t start; uintptr_t end; 51 uintptr_t start_va, end_va;
52 /* the instructions to be decoded */
53 unsigned char* buffer;
54 uintptr_t length;
52 event_callback_t event_callback; void* event_stream; 55 event_callback_t event_callback; void* event_stream;
53 printf_callback_t printf_callback; void* printf_stream; 56 printf_callback_t printf_callback; void* printf_stream;
54 bool losing; 57 bool losing;
58 bool do_newline;
55 59
56 /* the architecture being disassembled */ 60 /* the architecture being disassembled */
57 const char* arch_name; 61 const char* arch_name;
58 const bfd_arch_info_type* arch_info; 62 const bfd_arch_info_type* arch_info;
59 63
62 struct disassemble_info dinfo; /* the actual struct! */ 66 struct disassemble_info dinfo; /* the actual struct! */
63 67
64 char mach_option[64]; 68 char mach_option[64];
65 char insn_options[256]; 69 char insn_options[256];
66 }; 70 };
71
72 static void* decode(struct hsdis_app_data* app_data, const char* options);
67 73
68 #define DECL_APP_DATA(dinfo) \ 74 #define DECL_APP_DATA(dinfo) \
69 struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data 75 struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data
70 76
71 #define DECL_EVENT_CALLBACK(app_data) \ 77 #define DECL_EVENT_CALLBACK(app_data) \
87 93
88 void* 94 void*
89 #ifdef DLL_ENTRY 95 #ifdef DLL_ENTRY
90 DLL_ENTRY 96 DLL_ENTRY
91 #endif 97 #endif
98 decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
99 unsigned char* buffer, uintptr_t length,
100 event_callback_t event_callback_arg, void* event_stream_arg,
101 printf_callback_t printf_callback_arg, void* printf_stream_arg,
102 const char* options) {
103 struct hsdis_app_data app_data;
104 memset(&app_data, 0, sizeof(app_data));
105 app_data.start_va = start_va;
106 app_data.end_va = end_va;
107 app_data.buffer = buffer;
108 app_data.length = length;
109 app_data.event_callback = event_callback_arg;
110 app_data.event_stream = event_stream_arg;
111 app_data.printf_callback = printf_callback_arg;
112 app_data.printf_stream = printf_stream_arg;
113 app_data.do_newline = false;
114
115 return decode(&app_data, options);
116 }
117
118 /* This is the compatability interface for older version of hotspot */
119 void*
120 #ifdef DLL_ENTRY
121 DLL_ENTRY
122 #endif
92 decode_instructions(void* start_pv, void* end_pv, 123 decode_instructions(void* start_pv, void* end_pv,
93 event_callback_t event_callback_arg, void* event_stream_arg, 124 event_callback_t event_callback_arg, void* event_stream_arg,
94 printf_callback_t printf_callback_arg, void* printf_stream_arg, 125 printf_callback_t printf_callback_arg, void* printf_stream_arg,
95 const char* options) { 126 const char* options) {
96 struct hsdis_app_data app_data; 127 decode_instructions_virtual((uintptr_t)start_pv,
97 memset(&app_data, 0, sizeof(app_data)); 128 (uintptr_t)end_pv,
98 app_data.start = (uintptr_t) start_pv; 129 (unsigned char*)start_pv,
99 app_data.end = (uintptr_t) end_pv; 130 (uintptr_t)end_pv - (uintptr_t)start_pv,
100 app_data.event_callback = event_callback_arg; 131 event_callback_arg,
101 app_data.event_stream = event_stream_arg; 132 event_stream_arg,
102 app_data.printf_callback = printf_callback_arg; 133 printf_callback_arg,
103 app_data.printf_stream = printf_stream_arg; 134 printf_stream_arg,
104 135 options);
105 setup_app_data(&app_data, options); 136 }
137
138 static void* decode(struct hsdis_app_data* app_data, const char* options) {
139 setup_app_data(app_data, options);
106 char buf[128]; 140 char buf[128];
107 141
108 { 142 {
109 /* now reload everything from app_data: */ 143 /* now reload everything from app_data: */
110 DECL_EVENT_CALLBACK(&app_data); 144 DECL_EVENT_CALLBACK(app_data);
111 DECL_PRINTF_CALLBACK(&app_data); 145 DECL_PRINTF_CALLBACK(app_data);
112 uintptr_t start = app_data.start; 146 uintptr_t start = app_data->start_va;
113 uintptr_t end = app_data.end; 147 uintptr_t end = app_data->end_va;
114 uintptr_t p = start; 148 uintptr_t p = start;
115 149
116 (*event_callback)(event_stream, "insns", (void*)start); 150 (*event_callback)(event_stream, "insns", (void*)start);
117 151
118 (*event_callback)(event_stream, "mach name='%s'", 152 (*event_callback)(event_stream, "mach name='%s'",
119 (void*) app_data.arch_info->printable_name); 153 (void*) app_data->arch_info->printable_name);
120 if (app_data.dinfo.bytes_per_line != 0) { 154 if (app_data->dinfo.bytes_per_line != 0) {
121 (*event_callback)(event_stream, "format bytes-per-line='%p'/", 155 (*event_callback)(event_stream, "format bytes-per-line='%p'/",
122 (void*)(intptr_t) app_data.dinfo.bytes_per_line); 156 (void*)(intptr_t) app_data->dinfo.bytes_per_line);
123 } 157 }
124 158
125 while (p < end && !app_data.losing) { 159 while (p < end && !app_data->losing) {
126 (*event_callback)(event_stream, "insn", (void*) p); 160 (*event_callback)(event_stream, "insn", (void*) p);
127 161
128 /* reset certain state, so we can read it with confidence */ 162 /* reset certain state, so we can read it with confidence */
129 app_data.dinfo.insn_info_valid = 0; 163 app_data->dinfo.insn_info_valid = 0;
130 app_data.dinfo.branch_delay_insns = 0; 164 app_data->dinfo.branch_delay_insns = 0;
131 app_data.dinfo.data_size = 0; 165 app_data->dinfo.data_size = 0;
132 app_data.dinfo.insn_type = 0; 166 app_data->dinfo.insn_type = 0;
133 167
134 int size = (*app_data.dfn)((bfd_vma) p, &app_data.dinfo); 168 int size = (*app_data->dfn)((bfd_vma) p, &app_data->dinfo);
135 169
136 if (size > 0) p += size; 170 if (size > 0) p += size;
137 else app_data.losing = true; 171 else app_data->losing = true;
138 172
139 const char* insn_close = format_insn_close("/insn", &app_data.dinfo, 173 if (!app_data->losing) {
140 buf, sizeof(buf)); 174 const char* insn_close = format_insn_close("/insn", &app_data->dinfo,
141 (*event_callback)(event_stream, insn_close, (void*) p); 175 buf, sizeof(buf));
142 176 (*event_callback)(event_stream, insn_close, (void*) p) != NULL;
143 /* follow each complete insn by a nice newline */ 177
144 (*printf_callback)(printf_stream, "\n"); 178 if (app_data->do_newline) {
179 /* follow each complete insn by a nice newline */
180 (*printf_callback)(printf_stream, "\n");
181 }
182 }
145 } 183 }
146 184
147 (*event_callback)(event_stream, "/insns", (void*) p); 185 (*event_callback)(event_stream, "/insns", (void*) p);
148 return (void*) p; 186 return (void*) p;
149 } 187 }
150 } 188 }
151 189
152 /* take the address of the function, for luck, and also test the typedef: */ 190 /* take the address of the function, for luck, and also test the typedef: */
153 const decode_instructions_ftype decode_instructions_address = &decode_instructions; 191 const decode_instructions_ftype decode_instructions_address = &decode_instructions_virtual;
154 192
155 static const char* format_insn_close(const char* close, 193 static const char* format_insn_close(const char* close,
156 disassemble_info* dinfo, 194 disassemble_info* dinfo,
157 char* buf, size_t bufsize) { 195 char* buf, size_t bufsize) {
158 if (!dinfo->insn_info_valid) 196 if (!dinfo->insn_info_valid)
187 static int 225 static int
188 hsdis_read_memory_func(bfd_vma memaddr, 226 hsdis_read_memory_func(bfd_vma memaddr,
189 bfd_byte* myaddr, 227 bfd_byte* myaddr,
190 unsigned int length, 228 unsigned int length,
191 struct disassemble_info* dinfo) { 229 struct disassemble_info* dinfo) {
192 uintptr_t memaddr_p = (uintptr_t) memaddr;
193 DECL_APP_DATA(dinfo); 230 DECL_APP_DATA(dinfo);
194 if (memaddr_p + length > app_data->end) { 231 /* convert the virtual address memaddr into an address within memory buffer */
232 uintptr_t offset = ((uintptr_t) memaddr) - app_data->start_va;
233 if (offset + length > app_data->length) {
195 /* read is out of bounds */ 234 /* read is out of bounds */
196 return EIO; 235 return EIO;
197 } else { 236 } else {
198 memcpy(myaddr, (bfd_byte*) memaddr_p, length); 237 memcpy(myaddr, (bfd_byte*) (app_data->buffer + offset), length);
199 return 0; 238 return 0;
200 } 239 }
201 } 240 }
202 241
203 static void 242 static void
405 } 444 }
406 445
407 static const char* native_arch_name() { 446 static const char* native_arch_name() {
408 const char* res = NULL; 447 const char* res = NULL;
409 #ifdef LIBARCH_i386 448 #ifdef LIBARCH_i386
410 res = "i386"; 449 res = "i386";
411 #endif 450 #endif
412 #ifdef LIBARCH_amd64 451 #ifdef LIBARCH_amd64
413 res = "i386:x86-64"; 452 res = "i386:x86-64";
414 #endif 453 #endif
415 #ifdef LIBARCH_sparc 454 #ifdef LIBARCH_sparc
416 res = "sparc:v8plusb"; 455 res = "sparc:v8plusb";
417 #endif 456 #endif
418 #ifdef LIBARCH_sparcv9 457 #ifdef LIBARCH_sparcv9
419 res = "sparc:v9b"; 458 res = "sparc:v9b";
420 #endif 459 #endif
421 if (res == NULL) 460 if (res == NULL)
422 res = "architecture not set in Makefile!"; 461 res = "architecture not set in Makefile!";
423 return res; 462 return res;
424 } 463 }
466 505
467 dinfo->read_memory_func = &read_zero_data_only; 506 dinfo->read_memory_func = &read_zero_data_only;
468 dinfo->fprintf_func = &print_to_dev_null; 507 dinfo->fprintf_func = &print_to_dev_null;
469 (*dfn)(0, dinfo); 508 (*dfn)(0, dinfo);
470 509
471 // put it back: 510 /* put it back */
472 dinfo->read_memory_func = read_memory_func; 511 dinfo->read_memory_func = read_memory_func;
473 dinfo->fprintf_func = fprintf_func; 512 dinfo->fprintf_func = fprintf_func;
474 } 513 }
475 514
476 static void init_disassemble_info_from_bfd(struct disassemble_info* dinfo, 515 static void init_disassemble_info_from_bfd(struct disassemble_info* dinfo,