hotspot/src/share/tools/hsdis/hsdis-demo.c
changeset 347 df859fcca515
child 2564 85c3ae53ca1c
equal deleted inserted replaced
346:e13ccc474a28 347:df859fcca515
       
     1 /*
       
     2  * Copyright 2008 Sun Microsystems, Inc.  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 it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     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 /* hsdis-demo.c -- dump a range of addresses as native instructions
       
    26    This demonstrates the protocol required by the HotSpot PrintAssembly option.
       
    27 */
       
    28 
       
    29 #include "hsdis.h"
       
    30 
       
    31 #include "stdio.h"
       
    32 #include "stdlib.h"
       
    33 #include "string.h"
       
    34 
       
    35 void greet(const char*);
       
    36 void disassemble(void*, void*);
       
    37 void end_of_file();
       
    38 
       
    39 const char* options = NULL;
       
    40 int         raw     = 0;
       
    41 int         xml     = 0;
       
    42 
       
    43 int main(int ac, char** av) {
       
    44   int greeted = 0;
       
    45   int i;
       
    46   for (i = 1; i < ac; i++) {
       
    47     const char* arg = av[i];
       
    48     if (arg[0] == '-') {
       
    49       if (!strcmp(arg, "-xml"))
       
    50         xml ^= 1;
       
    51       else if (!strcmp(arg, "-raw"))
       
    52         raw ^= 1;
       
    53       else if (!strncmp(arg, "-options=", 9))
       
    54         options = arg+9;
       
    55       else
       
    56         { printf("Usage: %s [-xml] [name...]\n"); exit(2); }
       
    57       continue;
       
    58     }
       
    59     greet(arg);
       
    60     greeted = 1;
       
    61   }
       
    62   if (!greeted)
       
    63     greet("world");
       
    64   printf("...And now for something completely different:\n");
       
    65   disassemble((void*) &main, (void*) &end_of_file);
       
    66   printf("Cheers!\n");
       
    67 }
       
    68 
       
    69 void greet(const char* whom) {
       
    70   printf("Hello, %s!\n", whom);
       
    71 }
       
    72 
       
    73 void end_of_file() { }
       
    74 
       
    75 /* don't disassemble after this point... */
       
    76 
       
    77 #include "dlfcn.h"
       
    78 
       
    79 #ifdef HOTSPOT_LIB_ARCH
       
    80 #define LIBARCH HOTSPOT_LIB_ARCH
       
    81 #endif
       
    82 #ifdef HOTSPOT_OS
       
    83 #define OS HOTSPOT_OS
       
    84 #endif
       
    85 
       
    86 #define DECODE_INSTRUCTIONS_NAME "decode_instructions"
       
    87 #define HSDIS_NAME               "hsdis"
       
    88 static void* decode_instructions_pv = 0;
       
    89 static const char* hsdis_path[] = {
       
    90   HSDIS_NAME".so",
       
    91 #ifdef OS
       
    92   "bin/"OS"/"HSDIS_NAME".so",
       
    93 #endif
       
    94 #ifdef LIBARCH
       
    95   HSDIS_NAME"-"LIBARCH".so",
       
    96 #ifdef OS
       
    97   "bin/"OS"/"HSDIS_NAME"-"LIBARCH".so",
       
    98 #endif
       
    99 #endif
       
   100   NULL
       
   101 };
       
   102 
       
   103 static const char* load_decode_instructions() {
       
   104   void* dllib = NULL;
       
   105   const char* *next_in_path = hsdis_path;
       
   106   while (1) {
       
   107     decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
       
   108     if (decode_instructions_pv != NULL)
       
   109       return NULL;
       
   110     if (dllib != NULL)
       
   111       return "plugin does not defined "DECODE_INSTRUCTIONS_NAME;
       
   112     for (dllib = NULL; dllib == NULL; ) {
       
   113       const char* next_lib = (*next_in_path++);
       
   114       if (next_lib == NULL)
       
   115         return "cannot find plugin "HSDIS_NAME".so";
       
   116       dllib = dlopen(next_lib, RTLD_LAZY);
       
   117     }
       
   118   }
       
   119 }
       
   120 
       
   121 
       
   122 static const char* lookup(void* addr) {
       
   123 #define CHECK_NAME(fn) \
       
   124   if (addr == (void*) &fn)  return #fn;
       
   125 
       
   126   CHECK_NAME(main);
       
   127   CHECK_NAME(greet);
       
   128   return NULL;
       
   129 }
       
   130 
       
   131 /* does the event match the tag, followed by a null, space, or slash? */
       
   132 #define MATCH(event, tag) \
       
   133   (!strncmp(event, tag, sizeof(tag)-1) && \
       
   134    (!event[sizeof(tag)-1] || strchr(" /", event[sizeof(tag)-1])))
       
   135 
       
   136 
       
   137 static const char event_cookie[] = "event_cookie"; /* demo placeholder */
       
   138 static void* handle_event(void* cookie, const char* event, void* arg) {
       
   139 #define NS_DEMO "demo:"
       
   140   if (cookie != event_cookie)
       
   141     printf("*** bad event cookie %p != %p\n", cookie, event_cookie);
       
   142 
       
   143   if (xml) {
       
   144     /* We could almost do a printf(event, arg),
       
   145        but for the sake of a better demo,
       
   146        we dress the result up as valid XML.
       
   147     */
       
   148     const char* fmt = strchr(event, ' ');
       
   149     int evlen = (fmt ? fmt - event : strlen(event));
       
   150     if (!fmt) {
       
   151       if (event[0] != '/') {
       
   152         printf("<"NS_DEMO"%.*s>", evlen, event);
       
   153       } else {
       
   154         printf("</"NS_DEMO"%.*s>", evlen-1, event+1);
       
   155       }
       
   156     } else {
       
   157       if (event[0] != '/') {
       
   158         printf("<"NS_DEMO"%.*s", evlen, event);
       
   159         printf(fmt, arg);
       
   160         printf(">");
       
   161       } else {
       
   162         printf("<"NS_DEMO"%.*s_done", evlen-1, event+1);
       
   163         printf(fmt, arg);
       
   164         printf("/></"NS_DEMO"%.*s>", evlen-1, event+1);
       
   165       }
       
   166     }
       
   167   }
       
   168 
       
   169   if (MATCH(event, "insn")) {
       
   170     const char* name = lookup(arg);
       
   171     if (name)  printf("%s:\n", name);
       
   172 
       
   173     /* basic action for <insn>: */
       
   174     printf(" %p\t", arg);
       
   175 
       
   176   } else if (MATCH(event, "/insn")) {
       
   177     /* basic action for </insn>:
       
   178        (none, plugin puts the newline for us
       
   179     */
       
   180 
       
   181   } else if (MATCH(event, "mach")) {
       
   182     printf("Decoding for CPU '%s'\n", (char*) arg);
       
   183 
       
   184   } else if (MATCH(event, "addr")) {
       
   185     /* basic action for <addr/>: */
       
   186     const char* name = lookup(arg);
       
   187     if (name) {
       
   188       printf("&%s (%p)", name, arg);
       
   189       /* return non-null to notify hsdis not to print the addr */
       
   190       return arg;
       
   191     }
       
   192   }
       
   193 
       
   194   /* null return is always safe; can mean "I ignored it" */
       
   195   return NULL;
       
   196 }
       
   197 
       
   198 #define fprintf_callback \
       
   199   (decode_instructions_printf_callback_ftype)&fprintf
       
   200 
       
   201 void disassemble(void* from, void* to) {
       
   202   const char* err = load_decode_instructions();
       
   203   if (err != NULL) {
       
   204     printf("%s: %s\n", err, dlerror());
       
   205     exit(1);
       
   206   }
       
   207   printf("Decoding from %p to %p...\n", from, to);
       
   208   decode_instructions_ftype decode_instructions
       
   209     = (decode_instructions_ftype) decode_instructions_pv;
       
   210   void* res;
       
   211   if (raw && xml) {
       
   212     res = (*decode_instructions)(from, to, NULL, stdout, NULL, stdout, options);
       
   213   } else if (raw) {
       
   214     res = (*decode_instructions)(from, to, NULL, NULL, NULL, stdout, options);
       
   215   } else {
       
   216     res = (*decode_instructions)(from, to,
       
   217                                  handle_event, (void*) event_cookie,
       
   218                                  fprintf_callback, stdout,
       
   219                                  options);
       
   220   }
       
   221   if (res != to)
       
   222     printf("*** Result was %p!\n", res);
       
   223 }