Mercurial > hg > graal-compiler
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, |