src/share/tools/hsdis/hsdis.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File sadis Sdiff src/share/tools/hsdis

src/share/tools/hsdis/hsdis.c

Print this page




  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 /* hsdis.c -- dump a range of addresses as native instructions
  26    This implements the plugin protocol required by the
  27    HotSpot PrintAssembly option.
  28 */
  29 
  30 #include "hsdis.h"
  31 
  32 #include <sysdep.h>
  33 #include <libiberty.h>
  34 #include <bfd.h>
  35 #include <dis-asm.h>
  36 #include <inttypes.h>


  37 
  38 #ifndef bool
  39 #define bool int
  40 #define true 1
  41 #define false 0
  42 #endif /*bool*/
  43 
  44 /* short names for stuff in hsdis.h */
  45 typedef decode_instructions_event_callback_ftype  event_callback_t;
  46 typedef decode_instructions_printf_callback_ftype printf_callback_t;
  47 
  48 /* disassemble_info.application_data object */
  49 struct hsdis_app_data {

  50   /* the arguments to decode_instructions */
  51   uintptr_t start; uintptr_t end;
  52   event_callback_t  event_callback;  void* event_stream;
  53   printf_callback_t printf_callback; void* printf_stream;
  54   bool losing;
  55 
  56   /* the architecture being disassembled */
  57   const char* arch_name;
  58   const bfd_arch_info_type* arch_info;
  59 
  60   /* the disassembler we are going to use: */
  61   disassembler_ftype      dfn;
  62   struct disassemble_info dinfo; /* the actual struct! */
  63 
  64   char mach_option[64];
  65   char insn_options[256];
  66 };
  67 
  68 #define DECL_APP_DATA(dinfo) \
  69   struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data


  72   event_callback_t  event_callback = (app_data)->event_callback; \
  73   void*             event_stream   = (app_data)->event_stream
  74 
  75 #define DECL_PRINTF_CALLBACK(app_data) \
  76   printf_callback_t  printf_callback = (app_data)->printf_callback; \
  77   void*              printf_stream   = (app_data)->printf_stream
  78 
  79 
  80 static void print_help(struct hsdis_app_data* app_data,
  81                        const char* msg, const char* arg);
  82 static void setup_app_data(struct hsdis_app_data* app_data,
  83                            const char* options);
  84 static const char* format_insn_close(const char* close,
  85                                      disassemble_info* dinfo,
  86                                      char* buf, size_t bufsize);
  87 
  88 void*
  89 #ifdef DLL_ENTRY
  90   DLL_ENTRY
  91 #endif
  92 decode_instructions(void* start_pv, void* end_pv,

  93                     event_callback_t  event_callback_arg,  void* event_stream_arg,
  94                     printf_callback_t printf_callback_arg, void* printf_stream_arg,
  95                     const char* options) {
  96   struct hsdis_app_data app_data;
  97   memset(&app_data, 0, sizeof(app_data));
  98   app_data.start = (uintptr_t) start_pv;
  99   app_data.end   = (uintptr_t) end_pv;


 100   app_data.event_callback  = event_callback_arg;
 101   app_data.event_stream    = event_stream_arg;
 102   app_data.printf_callback = printf_callback_arg;
 103   app_data.printf_stream   = printf_stream_arg;
 104 
 105   setup_app_data(&app_data, options);
 106   char buf[128];
 107 
 108   {
 109     /* now reload everything from app_data: */
 110     DECL_EVENT_CALLBACK(&app_data);
 111     DECL_PRINTF_CALLBACK(&app_data);
 112     uintptr_t start = app_data.start;
 113     uintptr_t end   = app_data.end;
 114     uintptr_t p     = start;
 115 
 116     (*event_callback)(event_stream, "insns", (void*)start);
 117 
 118     (*event_callback)(event_stream, "mach name='%s'",
 119                       (void*) app_data.arch_info->printable_name);
 120     if (app_data.dinfo.bytes_per_line != 0) {
 121       (*event_callback)(event_stream, "format bytes-per-line='%p'/",
 122                         (void*)(intptr_t) app_data.dinfo.bytes_per_line);
 123     }
 124 
 125     while (p < end && !app_data.losing) {
 126       (*event_callback)(event_stream, "insn", (void*) p);
 127 
 128       /* reset certain state, so we can read it with confidence */
 129       app_data.dinfo.insn_info_valid    = 0;
 130       app_data.dinfo.branch_delay_insns = 0;
 131       app_data.dinfo.data_size          = 0;
 132       app_data.dinfo.insn_type          = 0;
 133 
 134       int size = (*app_data.dfn)((bfd_vma) p, &app_data.dinfo);
 135 
 136       if (size > 0)  p += size;
 137       else           app_data.losing = true;
 138 
 139       const char* insn_close = format_insn_close("/insn", &app_data.dinfo,
 140                                                  buf, sizeof(buf));
 141       (*event_callback)(event_stream, insn_close, (void*) p);
 142 
 143       /* follow each complete insn by a nice newline */
 144       (*printf_callback)(printf_stream, "\n");
 145     }
 146 
 147     (*event_callback)(event_stream, "/insns", (void*) p);
 148     return (void*) p;
 149   }
 150 }
 151 














 152 /* take the address of the function, for luck, and also test the typedef: */
 153 const decode_instructions_ftype decode_instructions_address = &decode_instructions;
 154 
 155 static const char* format_insn_close(const char* close,
 156                                      disassemble_info* dinfo,
 157                                      char* buf, size_t bufsize) {
 158   if (!dinfo->insn_info_valid)
 159     return close;
 160   enum dis_insn_type itype = dinfo->insn_type;
 161   int dsize = dinfo->data_size, delays = dinfo->branch_delay_insns;
 162   if ((itype == dis_nonbranch && (dsize | delays) == 0)
 163       || (strlen(close) + 3*20 > bufsize))
 164     return close;
 165 
 166   const char* type = "unknown";
 167   switch (itype) {
 168   case dis_nonbranch:   type = NULL;         break;
 169   case dis_branch:      type = "branch";     break;
 170   case dis_condbranch:  type = "condbranch"; break;
 171   case dis_jsr:         type = "jsr";        break;
 172   case dis_condjsr:     type = "condjsr";    break;
 173   case dis_dref:        type = "dref";       break;
 174   case dis_dref2:       type = "dref2";      break;
 175   }
 176 
 177   strcpy(buf, close);
 178   char* p = buf;
 179   if (type)    sprintf(p += strlen(p), " type='%s'", type);
 180   if (dsize)   sprintf(p += strlen(p), " dsize='%d'", dsize);
 181   if (delays)  sprintf(p += strlen(p), " delay='%d'", delays);
 182   return buf;
 183 }
 184 
 185 /* handler functions */
 186 
 187 static int
 188 hsdis_read_memory_func(bfd_vma memaddr,
 189                        bfd_byte* myaddr,
 190                        unsigned int length,
 191                        struct disassemble_info* dinfo) {
 192   uintptr_t memaddr_p = (uintptr_t) memaddr;
 193   DECL_APP_DATA(dinfo);


 194   if (memaddr_p + length > app_data->end) {
 195     /* read is out of bounds */
 196     return EIO;
 197   } else {
 198     memcpy(myaddr, (bfd_byte*) memaddr_p, length);
 199     return 0;
 200   }
 201 }
 202 
 203 static void
 204 hsdis_print_address_func(bfd_vma vma, struct disassemble_info* dinfo) {
 205   /* the actual value to print: */
 206   void* addr_value = (void*) (uintptr_t) vma;
 207   DECL_APP_DATA(dinfo);
 208   DECL_EVENT_CALLBACK(app_data);
 209 
 210   /* issue the event: */
 211   void* result =
 212     (*event_callback)(event_stream, "addr/", addr_value);
 213   if (result == NULL) {




  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 /* hsdis.c -- dump a range of addresses as native instructions
  26    This implements the plugin protocol required by the
  27    HotSpot PrintAssembly option.
  28 */
  29 
  30 #include "hsdis.h"


  31 #include <libiberty.h>
  32 #include <bfd.h>
  33 #include <dis-asm.h>
  34 #include <inttypes.h>
  35 #include <string.h>
  36 #include <errno.h>
  37 
  38 #ifndef bool
  39 #define bool int
  40 #define true 1
  41 #define false 0
  42 #endif /*bool*/
  43 
  44 /* short names for stuff in hsdis.h */
  45 typedef decode_instructions_event_callback_ftype  event_callback_t;
  46 typedef decode_instructions_printf_callback_ftype printf_callback_t;
  47 
  48 /* disassemble_info.application_data object */
  49 struct hsdis_app_data {
  50   uintptr_t start_va, end_va; /* virtual address of data */
  51   /* the arguments to decode_instructions */
  52   uintptr_t start; uintptr_t end;
  53   event_callback_t  event_callback;  void* event_stream;
  54   printf_callback_t printf_callback; void* printf_stream;
  55   bool losing;
  56 
  57   /* the architecture being disassembled */
  58   const char* arch_name;
  59   const bfd_arch_info_type* arch_info;
  60 
  61   /* the disassembler we are going to use: */
  62   disassembler_ftype      dfn;
  63   struct disassemble_info dinfo; /* the actual struct! */
  64 
  65   char mach_option[64];
  66   char insn_options[256];
  67 };
  68 
  69 #define DECL_APP_DATA(dinfo) \
  70   struct hsdis_app_data* app_data = (struct hsdis_app_data*) (dinfo)->application_data


  73   event_callback_t  event_callback = (app_data)->event_callback; \
  74   void*             event_stream   = (app_data)->event_stream
  75 
  76 #define DECL_PRINTF_CALLBACK(app_data) \
  77   printf_callback_t  printf_callback = (app_data)->printf_callback; \
  78   void*              printf_stream   = (app_data)->printf_stream
  79 
  80 
  81 static void print_help(struct hsdis_app_data* app_data,
  82                        const char* msg, const char* arg);
  83 static void setup_app_data(struct hsdis_app_data* app_data,
  84                            const char* options);
  85 static const char* format_insn_close(const char* close,
  86                                      disassemble_info* dinfo,
  87                                      char* buf, size_t bufsize);
  88 
  89 void*
  90 #ifdef DLL_ENTRY
  91   DLL_ENTRY
  92 #endif
  93 decode_instructions_virtual(void* start_va,
  94                             void* start_pv, void* end_pv,
  95                             event_callback_t  event_callback_arg,  void* event_stream_arg,
  96                             printf_callback_t printf_callback_arg, void* printf_stream_arg,
  97                             const char* options) {
  98   struct hsdis_app_data app_data;
  99   memset(&app_data, 0, sizeof(app_data));
 100   app_data.start = (uintptr_t) start_pv;
 101   app_data.end   = (uintptr_t) end_pv;
 102   app_data.start_va = (uintptr_t) start_va;
 103   app_data.end_va = app_data.start_va + app_data.end - app_data.start;
 104   app_data.event_callback  = event_callback_arg;
 105   app_data.event_stream    = event_stream_arg;
 106   app_data.printf_callback = printf_callback_arg;
 107   app_data.printf_stream   = printf_stream_arg;
 108 
 109   setup_app_data(&app_data, options);
 110   char buf[128];
 111 
 112   {
 113     /* now reload everything from app_data: */
 114     DECL_EVENT_CALLBACK(&app_data);
 115     DECL_PRINTF_CALLBACK(&app_data);
 116     uintptr_t start = app_data.start_va;
 117     uintptr_t end   = app_data.end_va;
 118     uintptr_t p     = start;
 119 
 120     (*event_callback)(event_stream, "insns", (void*)start);
 121 
 122     (*event_callback)(event_stream, "mach name='%s'",
 123                       (void*) app_data.arch_info->printable_name);
 124     if (app_data.dinfo.bytes_per_line != 0) {
 125       (*event_callback)(event_stream, "format bytes-per-line='%p'/",
 126                         (void*)(intptr_t) app_data.dinfo.bytes_per_line);
 127     }
 128 
 129     while (p < end && !app_data.losing) {
 130       (*event_callback)(event_stream, "insn", (void*) p);
 131 
 132       /* reset certain state, so we can read it with confidence */
 133       app_data.dinfo.insn_info_valid    = 0;
 134       app_data.dinfo.branch_delay_insns = 0;
 135       app_data.dinfo.data_size          = 0;
 136       app_data.dinfo.insn_type          = 0;
 137 
 138       int size = (*app_data.dfn)((bfd_vma) p, &app_data.dinfo);
 139 
 140       if (size > 0)  p += size;
 141       else           app_data.losing = true;
 142 
 143       const char* insn_close = format_insn_close("/insn", &app_data.dinfo,
 144                                                  buf, sizeof(buf));
 145       (*event_callback)(event_stream, insn_close, (void*) p);
 146 
 147       /* follow each complete insn by a nice newline */
 148       (*printf_callback)(printf_stream, "\n");
 149     }
 150 
 151     (*event_callback)(event_stream, "/insns", (void*) p);
 152     return (void*) p;
 153   }
 154 }
 155 
 156 void*
 157 #ifdef DLL_ENTRY
 158   DLL_ENTRY
 159 #endif
 160 decode_instructions(void* start_pv, void* end_pv,
 161                     event_callback_t  event_callback_arg,  void* event_stream_arg,
 162                     printf_callback_t printf_callback_arg, void* printf_stream_arg,
 163                     const char* options) {
 164   return decode_instructions_virtual(start_pv, start_pv, end_pv,
 165                                      event_callback_arg, event_stream_arg,
 166                                      printf_callback_arg, printf_stream_arg,
 167                                      options);
 168 }
 169 
 170 /* take the address of the function, for luck, and also test the typedef: */
 171 const decode_instructions_ftype decode_instructions_address = &decode_instructions;
 172 
 173 static const char* format_insn_close(const char* close,
 174                                      disassemble_info* dinfo,
 175                                      char* buf, size_t bufsize) {
 176   if (!dinfo->insn_info_valid)
 177     return close;
 178   enum dis_insn_type itype = dinfo->insn_type;
 179   int dsize = dinfo->data_size, delays = dinfo->branch_delay_insns;
 180   if ((itype == dis_nonbranch && (dsize | delays) == 0)
 181       || (strlen(close) + 3*20 > bufsize))
 182     return close;
 183 
 184   const char* type = "unknown";
 185   switch (itype) {
 186   case dis_nonbranch:   type = NULL;         break;
 187   case dis_branch:      type = "branch";     break;
 188   case dis_condbranch:  type = "condbranch"; break;
 189   case dis_jsr:         type = "jsr";        break;
 190   case dis_condjsr:     type = "condjsr";    break;
 191   case dis_dref:        type = "dref";       break;
 192   case dis_dref2:       type = "dref2";      break;
 193   }
 194 
 195   strcpy(buf, close);
 196   char* p = buf;
 197   if (type)    sprintf(p += strlen(p), " type='%s'", type);
 198   if (dsize)   sprintf(p += strlen(p), " dsize='%d'", dsize);
 199   if (delays)  sprintf(p += strlen(p), " delay='%d'", delays);
 200   return buf;
 201 }
 202 
 203 /* handler functions */
 204 
 205 static int
 206 hsdis_read_memory_func(bfd_vma memaddr,
 207                        bfd_byte* myaddr,
 208                        unsigned int length,
 209                        struct disassemble_info* dinfo) {

 210   DECL_APP_DATA(dinfo);
 211   // convert the virtual address membar into an address within memory buffer
 212   uintptr_t memaddr_p = ((uintptr_t) memaddr) - app_data->start_va + app_data->start;
 213   if (memaddr_p + length > app_data->end) {
 214     /* read is out of bounds */
 215     return EIO;
 216   } else {
 217     memcpy(myaddr, (bfd_byte*) memaddr_p, length);
 218     return 0;
 219   }
 220 }
 221 
 222 static void
 223 hsdis_print_address_func(bfd_vma vma, struct disassemble_info* dinfo) {
 224   /* the actual value to print: */
 225   void* addr_value = (void*) (uintptr_t) vma;
 226   DECL_APP_DATA(dinfo);
 227   DECL_EVENT_CALLBACK(app_data);
 228 
 229   /* issue the event: */
 230   void* result =
 231     (*event_callback)(event_stream, "addr/", addr_value);
 232   if (result == NULL) {


src/share/tools/hsdis/hsdis.c
Index Unified diffs Context diffs Sdiffs Wdiffs Patch New Old Previous File Next File