Exemplo n.º 1
0
static
void transfer_register (ThreadId tid, int abs_regno, void * buf,
                        transfer_direction dir, int size, Bool *mod)
{
   ThreadState* tst = VG_(get_ThreadState)(tid);
   int set = abs_regno / num_regs;
   int regno = abs_regno % num_regs;
   *mod = False;

   VexGuestARMState* arm = (VexGuestARMState*) get_arch (set, tst);

   switch (regno) { 
   
   
   case 0:  VG_(transfer) (&arm->guest_R0,   buf, dir, size, mod); break;
   case 1:  VG_(transfer) (&arm->guest_R1,   buf, dir, size, mod); break;
   case 2:  VG_(transfer) (&arm->guest_R2,   buf, dir, size, mod); break;
   case 3:  VG_(transfer) (&arm->guest_R3,   buf, dir, size, mod); break;
   case 4:  VG_(transfer) (&arm->guest_R4,   buf, dir, size, mod); break;
   case 5:  VG_(transfer) (&arm->guest_R5,   buf, dir, size, mod); break;
   case 6:  VG_(transfer) (&arm->guest_R6,   buf, dir, size, mod); break;
   case 7:  VG_(transfer) (&arm->guest_R7,   buf, dir, size, mod); break;
   case 8:  VG_(transfer) (&arm->guest_R8,   buf, dir, size, mod); break;
   case 9:  VG_(transfer) (&arm->guest_R9,   buf, dir, size, mod); break;
   case 10: VG_(transfer) (&arm->guest_R10,  buf, dir, size, mod); break;
   case 11: VG_(transfer) (&arm->guest_R11,  buf, dir, size, mod); break;
   case 12: VG_(transfer) (&arm->guest_R12,  buf, dir, size, mod); break;
   case 13: VG_(transfer) (&arm->guest_R13,  buf, dir, size, mod); break;
   case 14: VG_(transfer) (&arm->guest_R14,  buf, dir, size, mod); break;
   case 15: { 
      VG_(transfer) (&arm->guest_R15T, buf, dir, size, mod);
      if (dir == gdbserver_to_valgrind && *mod) {
         
         
         arm->guest_R15T = thumb_pc(arm->guest_R15T);
      }
      break;
   }
   case 16:
   case 17:
   case 18:
   case 19:
   case 20: 
   case 21:
   case 22:
   case 23:
   case 24: *mod = False; break;
   case 25: {
      UInt cpsr = LibVEX_GuestARM_get_cpsr (arm);
      if (dir == valgrind_to_gdbserver) {
         VG_(transfer) (&cpsr, buf, dir, size, mod); 
      } else {
#      if 0
         UInt newcpsr;
         VG_(transfer) (&newcpsr, buf, dir, size, mod);
         *mod = newcpsr != cpsr;
         
         LibVEX_GuestARM_put_flags (newcpsr, arm);
#      else
         *mod = False;
#      endif
      }
      break;
   }
   case 26: VG_(transfer) (&arm->guest_D0,  buf, dir, size, mod); break;
   case 27: VG_(transfer) (&arm->guest_D1,  buf, dir, size, mod); break;
   case 28: VG_(transfer) (&arm->guest_D2,  buf, dir, size, mod); break;
   case 29: VG_(transfer) (&arm->guest_D3,  buf, dir, size, mod); break;
   case 30: VG_(transfer) (&arm->guest_D4,  buf, dir, size, mod); break;
   case 31: VG_(transfer) (&arm->guest_D5,  buf, dir, size, mod); break;
   case 32: VG_(transfer) (&arm->guest_D6,  buf, dir, size, mod); break;
   case 33: VG_(transfer) (&arm->guest_D7,  buf, dir, size, mod); break;
   case 34: VG_(transfer) (&arm->guest_D8,  buf, dir, size, mod); break;
   case 35: VG_(transfer) (&arm->guest_D9,  buf, dir, size, mod); break;
   case 36: VG_(transfer) (&arm->guest_D10, buf, dir, size, mod); break;
   case 37: VG_(transfer) (&arm->guest_D11, buf, dir, size, mod); break;
   case 38: VG_(transfer) (&arm->guest_D12, buf, dir, size, mod); break;
   case 39: VG_(transfer) (&arm->guest_D13, buf, dir, size, mod); break;
   case 40: VG_(transfer) (&arm->guest_D14, buf, dir, size, mod); break;
   case 41: VG_(transfer) (&arm->guest_D15, buf, dir, size, mod); break;
   case 42: VG_(transfer) (&arm->guest_D16, buf, dir, size, mod); break;
   case 43: VG_(transfer) (&arm->guest_D17, buf, dir, size, mod); break;
   case 44: VG_(transfer) (&arm->guest_D18, buf, dir, size, mod); break;
   case 45: VG_(transfer) (&arm->guest_D19, buf, dir, size, mod); break;
   case 46: VG_(transfer) (&arm->guest_D20, buf, dir, size, mod); break;
   case 47: VG_(transfer) (&arm->guest_D21, buf, dir, size, mod); break;
   case 48: VG_(transfer) (&arm->guest_D22, buf, dir, size, mod); break;
   case 49: VG_(transfer) (&arm->guest_D23, buf, dir, size, mod); break;
   case 50: VG_(transfer) (&arm->guest_D24, buf, dir, size, mod); break;
   case 51: VG_(transfer) (&arm->guest_D25, buf, dir, size, mod); break;
   case 52: VG_(transfer) (&arm->guest_D26, buf, dir, size, mod); break;
   case 53: VG_(transfer) (&arm->guest_D27, buf, dir, size, mod); break;
   case 54: VG_(transfer) (&arm->guest_D28, buf, dir, size, mod); break;
   case 55: VG_(transfer) (&arm->guest_D29, buf, dir, size, mod); break;
   case 56: VG_(transfer) (&arm->guest_D30, buf, dir, size, mod); break;
   case 57: VG_(transfer) (&arm->guest_D31, buf, dir, size, mod); break;
   case 58: VG_(transfer) (&arm->guest_FPSCR, buf, dir, size, mod); break;
   default: vg_assert(0);
   }
}
Exemplo n.º 2
0
/* handle_gdb_valgrind_command handles the provided mon string command.
   If command is recognised, return 1 else return 0.
   Note that in case of ambiguous command, 1 is returned.

   *sink_wanted_at_return is modified if one of the commands 
   'v.set *_output' is handled.
*/
static
int handle_gdb_valgrind_command (char *mon, OutputSink *sink_wanted_at_return)
{
   UWord ret = 0;
   char s[strlen(mon)+1]; /* copy for strtok_r */
   char *wcmd;
   HChar *ssaveptr;
   const char *endptr;
   int   kwdid;
   int int_value;

   vg_assert (initial_valgrind_sink_saved);

   strcpy (s, mon);
   wcmd = strtok_r (s, " ", &ssaveptr);
   /* NB: if possible, avoid introducing a new command below which
      starts with the same 3 first letters as an already existing
      command. This ensures a shorter abbreviation for the user. */
   switch (VG_(keyword_id) ("help v.set v.info v.wait v.kill v.translate"
                            " v.do",
                            wcmd, kwd_report_duplicated_matches)) {
   case -2:
      ret = 1;
      break;
   case -1: 
      break;
   case  0: /* help */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      if (wcmd == NULL) {
         int_value = 0;
      } else {
         switch (VG_(keyword_id) ("debug", wcmd, kwd_report_all)) {
         case -2: int_value = 0; break;
         case -1: int_value = 0; break;
         case  0: int_value = 1; break;
         default: vg_assert (0);
         }
      }

      VG_(gdb_printf) (
"general valgrind monitor commands:\n"
"  help [debug]            : monitor command help. With debug: + debugging commands\n"
"  v.wait [<ms>]           : sleep <ms> (default 0) then continue\n"
"  v.info all_errors       : show all errors found so far\n"
"  v.info last_error       : show last error found\n"
"  v.info location <addr>  : show information about location <addr>\n"
"  v.info n_errs_found [msg] : show the nr of errors found so far and the given msg\n"
"  v.info open_fds         : show open file descriptors (only if --track-fds=yes)\n"
"  v.kill                  : kill the Valgrind process\n"
"  v.set gdb_output        : set valgrind output to gdb\n"
"  v.set log_output        : set valgrind output to log\n"
"  v.set mixed_output      : set valgrind output to log, interactive output to gdb\n"
"  v.set merge-recursive-frames <num> : merge recursive calls in max <num> frames\n"
"  v.set vgdb-error <errornr> : debug me at error >= <errornr> \n");
      if (int_value) { VG_(gdb_printf) (
"debugging valgrind internals monitor commands:\n"
"  v.do   expensive_sanity_check_general : do an expensive sanity check now\n"
"  v.info gdbserver_status : show gdbserver status\n"
"  v.info memory [aspacemgr] : show valgrind heap memory stats\n"
"     (with aspacemgr arg, also shows valgrind segments on log ouput)\n"
"  v.info exectxt          : show stacktraces and stats of all execontexts\n"
"  v.info scheduler        : show valgrind thread state and stacktrace\n"
"  v.info stats            : show various valgrind and tool stats\n"
"  v.info unwind <addr> [<len>] : show unwind debug info for <addr> .. <addr+len>\n"
"  v.set debuglog <level>  : set valgrind debug log level to <level>\n"
"  v.set hostvisibility [yes*|no] : (en/dis)ables access by gdb/gdbserver to\n"
"    Valgrind internal host status/memory\n"
"  v.translate <addr> [<traceflags>]  : debug translation of <addr> with <traceflags>\n"
"    (default traceflags 0b00100000 : show after instrumentation)\n"
"   An additional flag  0b100000000 allows to show gdbserver instrumentation\n");
      }
      break;
   case  1: /* v.set */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (kwdid = VG_(keyword_id) 
              ("vgdb-error debuglog merge-recursive-frames"
               " gdb_output log_output mixed_output hostvisibility",
               wcmd, kwd_report_all)) {
      case -2:
      case -1: 
         break;
      case 0: /* vgdb-error */
      case 1: /* debuglog */
      case 2: /* merge-recursive-frames */
         wcmd = strtok_r (NULL, " ", &ssaveptr);
         if (wcmd == NULL) {
            int_value = 0;
            endptr = "empty"; /* to report an error below */
         } else {
            HChar *the_end;
            int_value = strtol (wcmd, &the_end, 10);
            endptr = the_end;
         }
         if (*endptr != '\0') {
            VG_(gdb_printf) ("missing or malformed integer value\n");
         } else if (kwdid == 0) {
            VG_(printf) ("vgdb-error value changed from %d to %d\n",
                             VG_(dyn_vgdb_error), int_value);
            VG_(dyn_vgdb_error) = int_value;
         } else if (kwdid == 1) {
            VG_(printf) ("debuglog value changed from %d to %d\n",
                             VG_(debugLog_getLevel)(), int_value);
            VG_(debugLog_startup) (int_value, "gdbsrv");
         } else if (kwdid == 2) {
            VG_(printf)
               ("merge-recursive-frames value changed from %d to %d\n",
                VG_(clo_merge_recursive_frames), int_value);
            VG_(clo_merge_recursive_frames) = int_value;
         } else {
            vg_assert (0);
         }
         break;
      case 3: /* gdb_output */
         (*sink_wanted_at_return).fd = -2;
         command_output_to_log = False;
         VG_(gdb_printf) ("valgrind output will go to gdb\n");
         break;
      case 4: /* log_output */
         (*sink_wanted_at_return).fd = initial_valgrind_sink.fd;
         command_output_to_log = True;
         VG_(gdb_printf) ("valgrind output will go to log\n");
         break;
      case 5: /* mixed output */
         (*sink_wanted_at_return).fd = initial_valgrind_sink.fd;
         command_output_to_log = False;
         VG_(gdb_printf)
            ("valgrind output will go to log, "
             "interactive output will go to gdb\n");
         break;
      case 6: /* hostvisibility */
         wcmd = strtok_r (NULL, " ", &ssaveptr);
         if (wcmd != NULL) {
            switch (VG_(keyword_id) ("yes no", wcmd, kwd_report_all)) {
            case -2:
            case -1: break;
            case  0: 
               hostvisibility = True;
               break;
            case 1:
               hostvisibility = False;
               break;
            default: vg_assert (0);
            }
         } else {
            hostvisibility = True;
         }
         if (hostvisibility) {
            const DebugInfo *tooldi 
               = VG_(find_DebugInfo) ((Addr)handle_gdb_valgrind_command);
            /* Normally, we should always find the tooldi. In case we
               do not, suggest a 'likely somewhat working' address: */
            const Addr tool_text_start
               = tooldi ?
               VG_(DebugInfo_get_text_avma) (tooldi) : 0x38000000;
            const NSegment *toolseg
               = tooldi ?
                 VG_(am_find_nsegment) (VG_(DebugInfo_get_text_avma) (tooldi))
                 : NULL;
            VG_(gdb_printf) 
               ("Enabled access to Valgrind memory/status by GDB\n"
                "If not yet done, tell GDB which valgrind file(s) to use, "
                "typically:\n"
                "add-symbol-file %s %p\n", 
                toolseg ? VG_(am_get_filename)(toolseg)
                : "<toolfile> <address> e.g.",
                (void*)tool_text_start);
         } else
            VG_(gdb_printf)
               ("Disabled access to Valgrind memory/status by GDB\n");
         break;
      default:
         vg_assert (0);
      }
      break;
   case  2: /* v.info */ {
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (kwdid = VG_(keyword_id) 
              ("all_errors n_errs_found last_error gdbserver_status memory"
               " scheduler stats open_fds exectxt location unwind",
               wcmd, kwd_report_all)) {
      case -2:
      case -1: 
         break;
      case 0: // all_errors
         // A verbosity of minimum 2 is needed to show the errors.
         VG_(show_all_errors)(/* verbosity */ 2, /* xml */ False);
         break;
      case  1: // n_errs_found
         VG_(printf) ("n_errs_found %d n_errs_shown %d (vgdb-error %d) %s\n",
                      VG_(get_n_errs_found) (),
                      VG_(get_n_errs_shown) (),
                      VG_(dyn_vgdb_error),
                      wordn (mon, 3));
         break;
      case 2: // last_error
         VG_(show_last_error)();
         break;
      case  3: // gdbserver_status
         VG_(gdbserver_status_output)();
         break;
      case  4: /* memory */
         VG_(printf) ("%'13llu bytes have already been mmap-ed ANONYMOUS.\n",
                      VG_(am_get_anonsize_total)());
         VG_(print_all_arena_stats) ();
         if (VG_(clo_profile_heap))
            VG_(print_arena_cc_analysis) ();
         wcmd = strtok_r (NULL, " ", &ssaveptr);
         if (wcmd != NULL) {
            switch (VG_(keyword_id) ("aspacemgr", wcmd, kwd_report_all)) {
            case -2:
            case -1: break;
            case  0: 
               VG_(am_show_nsegments) (0, "gdbserver v.info memory aspacemgr");
               break;
            default: vg_assert (0);
            }
         }

         ret = 1;
         break;
      case  5: /* scheduler */
         VG_(show_sched_status) (True,  // host_stacktrace
                                 True,  // stack_usage
                                 True); // exited_threads
         ret = 1;
         break;
      case  6: /* stats */
         VG_(print_all_stats)(False, /* Memory stats */
                              True   /* Tool stats */);
         ret = 1;
         break;
      case  7: /* open_fds */
         if (VG_(clo_track_fds))
            VG_(show_open_fds) ("");
         else
            VG_(gdb_printf)
               ("Valgrind must be started with --track-fds=yes"
                " to show open fds\n");
         ret = 1;
         break;
      case  8: /* exectxt */
         VG_(print_ExeContext_stats) (True /* with_stacktraces */);
         ret = 1;
         break;
      case  9: { /* location */
         /* Note: we prefer 'v.info location' and not 'v.info address' as
            v.info address is inconsistent with the GDB (native) 
            command 'info address' which gives the address for a symbol.
            GDB equivalent command of 'v.info location' is 'info symbol'. */
         Addr address;
         SizeT dummy_sz = 0x1234;
         if (VG_(strtok_get_address_and_size) (&address, 
                                               &dummy_sz, &ssaveptr)) {
            // If tool provides location information, use that.
            if (VG_(needs).info_location) {
               VG_TDICT_CALL(tool_info_location, address);
            } 
            // If tool does not provide location info, use the common one.
            // Also use the common to compare with tool when debug log is set.
            if (!VG_(needs).info_location || VG_(debugLog_getLevel)() > 0 ) {
               AddrInfo ai;
               ai.tag = Addr_Undescribed;
               VG_(describe_addr) (address, &ai);
               VG_(pp_addrinfo) (address, &ai);
               VG_(clear_addrinfo) (&ai);
            }
         }
         ret = 1;
         break;
      }
      case 10: { /* unwind */
         Addr address;
         SizeT sz = 1;
         if (VG_(strtok_get_address_and_size) (&address, 
                                               &sz, &ssaveptr)) {
            VG_(ppUnwindInfo) (address, address + sz - 1);
         }
         ret = 1;
         break;
      }

      default:
         vg_assert(0);
      }
      break;
   }
   case  3: /* v.wait */
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      if (wcmd != NULL) {
         int_value = strtol (wcmd, NULL, 10);
         VG_(printf) ("gdbserver: continuing in %d ms ...\n", int_value);
         VG_(poll)(NULL, 0, int_value);
      }
      VG_(printf) ("gdbserver: continuing after wait ...\n");
      ret = 1;
      break;
   case  4: /* v.kill */
      kill_request ("monitor command request to kill this process\n");
      break;
   case  5: { /* v.translate */
      Addr address;
      SizeT verbosity = 0x20;
      
      ret = 1;

      if (VG_(strtok_get_address_and_size) (&address, &verbosity, &ssaveptr)) {
         /* we need to force the output to log for the translation trace,
            as low level VEX tracing cannot be redirected to gdb. */
         int saved_command_output_to_log = command_output_to_log;
         int saved_fd = VG_(log_output_sink).fd;
         Bool single_stepping_on_entry = valgrind_single_stepping();
         int vex_verbosity = verbosity & 0xff;
         VG_(log_output_sink).fd = initial_valgrind_sink.fd;
         if ((verbosity & 0x100) && !single_stepping_on_entry) {
            valgrind_set_single_stepping(True); 
            // to force gdbserver instrumentation.
         }
#        if defined(VGA_arm)
         // on arm, we need to (potentially) convert this address
         // to the thumb form.
         address = thumb_pc (address);
#        endif

         VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
                          address,
                          /*debugging*/True, 
                          (Int) vex_verbosity,
                          /*bbs_done*/0,
                          /*allow redir?*/True);
         if ((verbosity & 0x100) && !single_stepping_on_entry) {
            valgrind_set_single_stepping(False);
            // reset single stepping.
         }
         command_output_to_log = saved_command_output_to_log;
         VG_(log_output_sink).fd = saved_fd;
      }
      break;
   }

   case  6: /* v.do */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (VG_(keyword_id) ("expensive_sanity_check_general",
                               wcmd, kwd_report_all)) {
         case -2:
         case -1: break;
         case  0: { /* expensive_sanity_check_general */
            // Temporarily bump up sanity level to check e.g. the malloc arenas.
            const Int save_clo_sanity_level = VG_(clo_sanity_level);
            if (VG_(clo_sanity_level) < 4) VG_(clo_sanity_level) = 4;
            VG_(sanity_check_general) (/* force_expensive */ True);
            VG_(clo_sanity_level) = save_clo_sanity_level;
            break;
         }
         default: vg_assert (0);
      }
      break;

   default:
      vg_assert (0);
   }
   return ret;
}
Exemplo n.º 3
0
/* handle_gdb_valgrind_command handles the provided mon string command.
   If command is recognised, return 1 else return 0.
   Note that in case of ambiguous command, 1 is returned.

   *sink_wanted_at_return is modified if one of the commands 
   'v.set *_output' is handled.
*/
static
int handle_gdb_valgrind_command (char* mon, OutputSink* sink_wanted_at_return)
{
   UWord ret = 0;
   char s[strlen(mon)+1]; /* copy for strtok_r */
   char* wcmd;
   HChar* ssaveptr;
   const char* endptr;
   int   kwdid;
   int int_value;

   vg_assert (initial_valgrind_sink_saved);

   strcpy (s, mon);
   wcmd = strtok_r (s, " ", &ssaveptr);
   /* NB: if possible, avoid introducing a new command below which
      starts with the same 3 first letters as an already existing
      command. This ensures a shorter abbreviation for the user. */
   switch (VG_(keyword_id) ("help v.set v.info v.wait v.kill v.translate"
                            " v.do",
                            wcmd, kwd_report_duplicated_matches)) {
   case -2:
      ret = 1;
      break;
   case -1: 
      break;
   case  0: /* help */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      if (wcmd == NULL) {
         int_value = 0;
      } else {
         switch (VG_(keyword_id) ("debug", wcmd, kwd_report_all)) {
         case -2: int_value = 0; break;
         case -1: int_value = 0; break;
         case  0: int_value = 1; break;
         default: tl_assert (0);
         }
      }

      VG_(gdb_printf) (
"general valgrind monitor commands:\n"
"  help [debug]            : monitor command help. With debug: + debugging commands\n"
"  v.wait [<ms>]           : sleep <ms> (default 0) then continue\n"
"  v.info all_errors       : show all errors found so far\n"
"  v.info last_error       : show last error found\n"
"  v.info n_errs_found     : show the nr of errors found so far\n"
"  v.info open_fds         : show open file descriptors (only if --track-fds=yes)\n"
"  v.kill                  : kill the Valgrind process\n"
"  v.set gdb_output        : set valgrind output to gdb\n"
"  v.set log_output        : set valgrind output to log\n"
"  v.set mixed_output      : set valgrind output to log, interactive output to gdb\n"
"  v.set merge-recursive-frames <num> : merge recursive calls in max <num> frames\n"
"  v.set vgdb-error <errornr> : debug me at error >= <errornr> \n");
      if (int_value) { VG_(gdb_printf) (
"debugging valgrind internals monitor commands:\n"
"  v.do   expensive_sanity_check_general : do an expensive sanity check now\n"
"  v.info gdbserver_status : show gdbserver status\n"
"  v.info memory [aspacemgr] : show valgrind heap memory stats\n"
"     (with aspacemgr arg, also shows valgrind segments on log ouput)\n"
"  v.info exectxt          : show stacktraces and stats of all execontexts\n"
"  v.info scheduler        : show valgrind thread state and stacktrace\n"
"  v.set debuglog <level>  : set valgrind debug log level to <level>\n"
"  v.translate <addr> [<traceflags>]  : debug translation of <addr> with <traceflags>\n"
"    (default traceflags 0b00100000 : show after instrumentation)\n"
"   An additional flag  0b100000000 allows to show gdbserver instrumentation\n");
      }
      break;
   case  1: /* v.set */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (kwdid = VG_(keyword_id) 
              ("vgdb-error debuglog merge-recursive-frames"
               " gdb_output log_output mixed_output",
               wcmd, kwd_report_all)) {
      case -2:
      case -1: 
         break;
      case 0: /* vgdb-error */
      case 1: /* debuglog */
      case 2: /* merge-recursive-frames */
         wcmd = strtok_r (NULL, " ", &ssaveptr);
         if (wcmd == NULL) {
            int_value = 0;
            endptr = "empty"; /* to report an error below */
         } else {
            HChar *the_end;
            int_value = strtol (wcmd, &the_end, 10);
            endptr = the_end;
         }
         if (*endptr != '\0') {
            VG_(gdb_printf) ("missing or malformed integer value\n");
         } else if (kwdid == 0) {
            VG_(gdb_printf) ("vgdb-error value changed from %d to %d\n",
                             VG_(dyn_vgdb_error), int_value);
            VG_(dyn_vgdb_error) = int_value;
         } else if (kwdid == 1) {
            VG_(gdb_printf) ("debuglog value changed from %d to %d\n",
                             VG_(debugLog_getLevel)(), int_value);
            VG_(debugLog_startup) (int_value, "gdbsrv");
         } else if (kwdid == 2) {
            VG_(gdb_printf)
               ("merge-recursive-frames value changed from %d to %d\n",
                VG_(clo_merge_recursive_frames), int_value);
            VG_(clo_merge_recursive_frames) = int_value;
         } else {
            vg_assert (0);
         }
         break;
      case 3: /* gdb_output */
         (*sink_wanted_at_return).fd = -2;
         command_output_to_log = False;
         VG_(gdb_printf) ("valgrind output will go to gdb\n");
         break;
      case 4: /* log_output */
         (*sink_wanted_at_return).fd = initial_valgrind_sink.fd;
         command_output_to_log = True;
         VG_(gdb_printf) ("valgrind output will go to log\n");
         break;
      case 5: /* mixed output */
         (*sink_wanted_at_return).fd = initial_valgrind_sink.fd;
         command_output_to_log = False;
         VG_(gdb_printf)
            ("valgrind output will go to log, interactive output will go to gdb\n");
         break;
      default:
         vg_assert (0);
      }
      break;
   case  2: /* v.info */ {
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (kwdid = VG_(keyword_id) 
              ("all_errors n_errs_found last_error gdbserver_status memory"
               " scheduler open_fds exectxt",
               wcmd, kwd_report_all)) {
      case -2:
      case -1: 
         break;
      case 0: // all_errors
         // A verbosity of minimum 2 is needed to show the errors.
         VG_(show_all_errors)(/* verbosity */ 2, /* xml */ False);
         break;
      case  1: // n_errs_found
         VG_(gdb_printf) ("n_errs_found %d n_errs_shown %d (vgdb-error %d)\n", 
                          VG_(get_n_errs_found) (),
                          VG_(get_n_errs_shown) (),
                          VG_(dyn_vgdb_error));
         break;
      case 2: // last_error
         VG_(show_last_error)();
         break;
      case  3: // gdbserver_status
         VG_(gdbserver_status_output)();
         break;
      case  4: /* memory */
         VG_(print_all_arena_stats) ();
         if (VG_(clo_profile_heap))
            VG_(print_arena_cc_analysis) ();
         wcmd = strtok_r (NULL, " ", &ssaveptr);
         if (wcmd != NULL) {
            switch (VG_(keyword_id) ("aspacemgr", wcmd, kwd_report_all)) {
            case -2:
            case -1: break;
            case  0: 
               VG_(am_show_nsegments) (0, "gdbserver v.info memory aspacemgr");
               break;
            default: tl_assert (0);
            }
         }

         ret = 1;
         break;
      case  5: /* scheduler */
         VG_(show_sched_status) ();
         ret = 1;
         break;
      case  6: /* open_fds */
         if (VG_(clo_track_fds))
            VG_(show_open_fds) ("");
         else
            VG_(gdb_printf)
               ("Valgrind must be started with --track-fds=yes"
                " to show open fds\n");
         ret = 1;
         break;
      case  7: /* exectxt */
         VG_(print_ExeContext_stats) (True /* with_stacktraces */);
         ret = 1;
         break;
      default:
         vg_assert(0);
      }
      break;
   }
   case  3: /* v.wait */
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      if (wcmd != NULL) {
         int_value = strtol (wcmd, NULL, 10);
         VG_(gdb_printf) ("gdbserver: continuing in %d ms ...\n", int_value);
         VG_(poll)(NULL, 0, int_value);
      }
      VG_(gdb_printf) ("gdbserver: continuing after wait ...\n");
      ret = 1;
      break;
   case  4: /* v.kill */
      kill_request ("monitor command request to kill this process\n");
      break;
   case  5: { /* v.translate */
      Addr address;
      SizeT verbosity = 0x20;
      
      ret = 1;

      VG_(strtok_get_address_and_size) (&address, &verbosity, &ssaveptr);
      if (address != (Addr) 0 || verbosity != 0) {
         /* we need to force the output to log for the translation trace,
            as low level VEX tracing cannot be redirected to gdb. */
         int saved_command_output_to_log = command_output_to_log;
         int saved_fd = VG_(log_output_sink).fd;
         Bool single_stepping_on_entry = valgrind_single_stepping();
         int vex_verbosity = verbosity & 0xff;
         VG_(log_output_sink).fd = initial_valgrind_sink.fd;
         if ((verbosity & 0x100) && !single_stepping_on_entry) {
            valgrind_set_single_stepping(True); 
            // to force gdbserver instrumentation.
         }
#        if defined(VGA_arm)
         // on arm, we need to (potentially) convert this address
         // to the thumb form.
         address = thumb_pc (address);
#        endif

         VG_(translate) ( 0 /* dummy ThreadId; irrelevant due to debugging*/,
                          address,
                          /*debugging*/True, 
                          (Int) vex_verbosity,
                          /*bbs_done*/0,
                          /*allow redir?*/True);
         if ((verbosity & 0x100) && !single_stepping_on_entry) {
            valgrind_set_single_stepping(False);
            // reset single stepping.
         }
         command_output_to_log = saved_command_output_to_log;
         VG_(log_output_sink).fd = saved_fd;
      }
      break;
   }

   case  6: /* v.do */
      ret = 1;
      wcmd = strtok_r (NULL, " ", &ssaveptr);
      switch (VG_(keyword_id) ("expensive_sanity_check_general",
                               wcmd, kwd_report_all)) {
         case -2:
         case -1: break;
         case  0: { /* expensive_sanity_check_general */
            // Temporarily bump up sanity level to check e.g. the malloc arenas.
            const Int save_clo_sanity_level = VG_(clo_sanity_level);
            if (VG_(clo_sanity_level) < 4) VG_(clo_sanity_level) = 4;
            VG_(sanity_check_general) (/* force_expensive */ True);
            VG_(clo_sanity_level) = save_clo_sanity_level;
            break;
         }
         default: tl_assert (0);
      }
      break;

   default:
      vg_assert (0);
   }
   return ret;
}
Exemplo n.º 4
0
/* store registers in the guest state (gdbserver_to_valgrind)
   or fetch register from the guest state (valgrind_to_gdbserver). */
static
void transfer_register (ThreadId tid, int abs_regno, void * buf,
                        transfer_direction dir, int size, Bool *mod)
{
    ThreadState* tst = VG_(get_ThreadState)(tid);
    int set = abs_regno / num_regs;
    int regno = abs_regno % num_regs;
    *mod = False;

    VexGuestARMState* arm = (VexGuestARMState*) get_arch (set, tst);

    switch (regno) {
    // numbers here have to match the order of regs above
    // Attention: gdb order does not match valgrind order.
    case 0:
        VG_(transfer) (&arm->guest_R0,   buf, dir, size, mod);
        break;
    case 1:
        VG_(transfer) (&arm->guest_R1,   buf, dir, size, mod);
        break;
    case 2:
        VG_(transfer) (&arm->guest_R2,   buf, dir, size, mod);
        break;
    case 3:
        VG_(transfer) (&arm->guest_R3,   buf, dir, size, mod);
        break;
    case 4:
        VG_(transfer) (&arm->guest_R4,   buf, dir, size, mod);
        break;
    case 5:
        VG_(transfer) (&arm->guest_R5,   buf, dir, size, mod);
        break;
    case 6:
        VG_(transfer) (&arm->guest_R6,   buf, dir, size, mod);
        break;
    case 7:
        VG_(transfer) (&arm->guest_R7,   buf, dir, size, mod);
        break;
    case 8:
        VG_(transfer) (&arm->guest_R8,   buf, dir, size, mod);
        break;
    case 9:
        VG_(transfer) (&arm->guest_R9,   buf, dir, size, mod);
        break;
    case 10:
        VG_(transfer) (&arm->guest_R10,  buf, dir, size, mod);
        break;
    case 11:
        VG_(transfer) (&arm->guest_R11,  buf, dir, size, mod);
        break;
    case 12:
        VG_(transfer) (&arm->guest_R12,  buf, dir, size, mod);
        break;
    case 13:
        VG_(transfer) (&arm->guest_R13,  buf, dir, size, mod);
        break;
    case 14:
        VG_(transfer) (&arm->guest_R14,  buf, dir, size, mod);
        break;
    case 15: {
        VG_(transfer) (&arm->guest_R15T, buf, dir, size, mod);
        if (dir == gdbserver_to_valgrind && *mod) {
            // If gdb is changing the PC, we have to set the thumb bit
            // if needed.
            arm->guest_R15T = thumb_pc(arm->guest_R15T);
        }
        break;
    }
    case 16:
    case 17:
    case 18:
    case 19:
    case 20: /* 9 "empty registers". See struct reg regs above. */
    case 21:
    case 22:
    case 23:
    case 24:
        *mod = False;
        break;
    case 25: {
        UInt cpsr = LibVEX_GuestARM_get_cpsr (arm);
        if (dir == valgrind_to_gdbserver) {
            VG_(transfer) (&cpsr, buf, dir, size, mod);
        } else {
#      if 0
            UInt newcpsr;
            VG_(transfer) (&newcpsr, buf, dir, size, mod);
            *mod = newcpsr != cpsr;
            // GDBTD ???? see FIXME in guest_arm_helpers.c
            LibVEX_GuestARM_put_flags (newcpsr, arm);
#      else
            *mod = False;
#      endif
        }
        break;
    }
    case 26:
        VG_(transfer) (&arm->guest_D0,  buf, dir, size, mod);
        break;
    case 27:
        VG_(transfer) (&arm->guest_D1,  buf, dir, size, mod);
        break;
    case 28:
        VG_(transfer) (&arm->guest_D2,  buf, dir, size, mod);
        break;
    case 29:
        VG_(transfer) (&arm->guest_D3,  buf, dir, size, mod);
        break;
    case 30:
        VG_(transfer) (&arm->guest_D4,  buf, dir, size, mod);
        break;
    case 31:
        VG_(transfer) (&arm->guest_D5,  buf, dir, size, mod);
        break;
    case 32:
        VG_(transfer) (&arm->guest_D6,  buf, dir, size, mod);
        break;
    case 33:
        VG_(transfer) (&arm->guest_D7,  buf, dir, size, mod);
        break;
    case 34:
        VG_(transfer) (&arm->guest_D8,  buf, dir, size, mod);
        break;
    case 35:
        VG_(transfer) (&arm->guest_D9,  buf, dir, size, mod);
        break;
    case 36:
        VG_(transfer) (&arm->guest_D10, buf, dir, size, mod);
        break;
    case 37:
        VG_(transfer) (&arm->guest_D11, buf, dir, size, mod);
        break;
    case 38:
        VG_(transfer) (&arm->guest_D12, buf, dir, size, mod);
        break;
    case 39:
        VG_(transfer) (&arm->guest_D13, buf, dir, size, mod);
        break;
    case 40:
        VG_(transfer) (&arm->guest_D14, buf, dir, size, mod);
        break;
    case 41:
        VG_(transfer) (&arm->guest_D15, buf, dir, size, mod);
        break;
    case 42:
        VG_(transfer) (&arm->guest_D16, buf, dir, size, mod);
        break;
    case 43:
        VG_(transfer) (&arm->guest_D17, buf, dir, size, mod);
        break;
    case 44:
        VG_(transfer) (&arm->guest_D18, buf, dir, size, mod);
        break;
    case 45:
        VG_(transfer) (&arm->guest_D19, buf, dir, size, mod);
        break;
    case 46:
        VG_(transfer) (&arm->guest_D20, buf, dir, size, mod);
        break;
    case 47:
        VG_(transfer) (&arm->guest_D21, buf, dir, size, mod);
        break;
    case 48:
        VG_(transfer) (&arm->guest_D22, buf, dir, size, mod);
        break;
    case 49:
        VG_(transfer) (&arm->guest_D23, buf, dir, size, mod);
        break;
    case 50:
        VG_(transfer) (&arm->guest_D24, buf, dir, size, mod);
        break;
    case 51:
        VG_(transfer) (&arm->guest_D25, buf, dir, size, mod);
        break;
    case 52:
        VG_(transfer) (&arm->guest_D26, buf, dir, size, mod);
        break;
    case 53:
        VG_(transfer) (&arm->guest_D27, buf, dir, size, mod);
        break;
    case 54:
        VG_(transfer) (&arm->guest_D28, buf, dir, size, mod);
        break;
    case 55:
        VG_(transfer) (&arm->guest_D29, buf, dir, size, mod);
        break;
    case 56:
        VG_(transfer) (&arm->guest_D30, buf, dir, size, mod);
        break;
    case 57:
        VG_(transfer) (&arm->guest_D31, buf, dir, size, mod);
        break;
    case 58:
        VG_(transfer) (&arm->guest_FPSCR, buf, dir, size, mod);
        break;
    default:
        vg_assert(0);
    }
}