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); } }
/* 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; }
/* 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; }
/* 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); } }