GDB (API)
|
00001 # Interface between GDB and Insight. 00002 # Copyright (C) 1997, 1998, 1999, 2001, 2002, 2004, 2008 Red Hat, Inc. 00003 # 00004 # This program is free software; you can redistribute it and/or modify it 00005 # under the terms of the GNU General Public License (GPL) as published by 00006 # the Free Software Foundation; either version 2 of the License, or (at 00007 # your option) any later version. 00008 # 00009 # This program is distributed in the hope that it will be useful, 00010 # but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 # GNU General Public License for more details. 00013 00014 00015 # This variable is reserved for this module. Ensure it is an array. 00016 global gdbtk_state 00017 set gdbtk_state(busyCount) 0 00018 00019 # *** DEPRECATED: Use GDBEventHandler::breakpoint instead. 00020 # This is run when a breakpoint changes. The arguments are the 00021 # action, the breakpoint number, and the breakpoint info. 00022 #define_hook gdb_breakpoint_change_hook 00023 00024 # *** DEPRECATED: Use GDBEventHandler::set_variable instead. 00025 # This is run when a `set' command successfully completes in gdb. The 00026 # first argument is the gdb variable name (as a Tcl list). The second 00027 # argument is the new value. 00028 #define_hook gdb_set_hook 00029 00030 # ------------------------------------------------------------ 00031 # PROC: gdbtk_tcl_set_variable - A "set" command was issued 00032 # in gdb to change an internal variable. Notify 00033 # gui. 00034 # ------------------------------------------------------------ 00035 proc gdbtk_tcl_set_variable {var val} { 00036 set e [SetVariableEvent \#auto -variable $var -value $val] 00037 GDBEventHandler::dispatch $e 00038 delete object $e 00039 } 00040 00041 #################################################################### 00042 # # 00043 # GUI STATE HOOKS # 00044 # # 00045 #################################################################### 00046 # !!!!! NOTE !!!!! 00047 # For debugging purposes, please put debug statements at the very 00048 # beginning and ends of all GUI state hooks. 00049 00050 # *** DEPRECATED: Use GDBEventHandler::busy instead. 00051 # GDB_BUSY_HOOK 00052 # This hook is used to register a callback when the UI should 00053 # be disabled because the debugger is either busy or talking 00054 # to the target. 00055 # 00056 # All callbacks should disable ALL user input which could cause 00057 # any state changes in either the target or the debugger. 00058 #define_hook gdb_busy_hook 00059 00060 # *** DEPRECATED: Use GDBEventHandler::idle instead. 00061 # GDB_IDLE_HOOK 00062 # This hook is used to register a callback when the UI should 00063 # be enabled because the debugger is no longer busy. 00064 # 00065 # All callbacks should enable user input. These callbacks 00066 # should also be as fast as possible to avoid any significant 00067 # time delays when enabling the UI. 00068 define_hook gdb_idle_hook 00069 00070 # *** DEPRECATED: Use GDBEventHandler::update instead. 00071 # GDB_UPDATE_HOOK 00072 # This hook is used to register a callback to update the widget 00073 # when debugger state has changed. 00074 #define_hook gdb_update_hook 00075 00076 # GDB_NO_INFERIOR_HOOK 00077 # This hook is used to register a callback which should be invoked 00078 # whenever there is no inferior (either at startup time or when 00079 # an inferior is killed). 00080 # 00081 # All callbacks should reset their windows to a known, "startup" 00082 # state. 00083 define_hook gdb_no_inferior_hook 00084 00085 # GDB_DISPLAY_CHANGE_HOOK 00086 # This is run when a display changes. The arguments are the action, 00087 # the breakpoint number, and (optionally) the value. 00088 define_hook gdb_display_change_hook 00089 00090 # GDB_TRACE_FIND_HOOK 00091 # This hook is run by the trace find command. It is used to switch 00092 # from control to browse mode when the user runs tfind commands... 00093 # 00094 define_hook gdb_trace_find_hook 00095 00096 # ------------------------------------------------------------------ 00097 # gdbtk_tcl_preloop - This function is called after gdb is initialized 00098 # but before the mainloop is started. It sets the app name, and 00099 # opens the first source window. 00100 # ------------------------------------------------------------------ 00101 00102 proc gdbtk_tcl_preloop { } { 00103 global gdb_exe_name gdb_current_directory 00104 00105 set_baud 00106 00107 tk appname gdbtk 00108 # If there was an error loading an executible specified on the command line 00109 # then we will have called pre_add_symbol, which would set us to busy, 00110 # but not the corresponding post_add_symbol. Do this here just in case... 00111 after idle gdbtk_idle 00112 ManagedWin::startup 00113 00114 if {$gdb_exe_name != ""} { 00115 # At startup, file_changed_hook is called too late for us, so we 00116 # must notice the initial session by hand. If the arguments exist 00117 # -- if the user used `gdb --args' -- then we want the new 00118 # arguments and pwd to override what is set in the session. 00119 set current_args [gdb_get_inferior_args] 00120 set current_dir $gdb_current_directory 00121 Session::notice_file_change 00122 set_baud 00123 if {[string length $current_args] > 0} { 00124 gdb_set_inferior_args $current_args 00125 gdb_cmd "cd $current_dir" 00126 } 00127 } 00128 00129 gdbtk_update 00130 } 00131 00132 00133 # ------------------------------------------------------------------ 00134 # PROCEDURE: gdbtk_busy - Dispatch a busy event 00135 # 00136 # Use this procedure from within GUI code to indicate that 00137 # the debugger is busy, either running the inferior or 00138 # talking to the target. 00139 # ------------------------------------------------------------------ 00140 proc gdbtk_busy {} { 00141 00142 set e [BusyEvent \#auto] 00143 GDBEventHandler::dispatch $e 00144 delete object $e 00145 00146 # Force the screen to update 00147 update 00148 } 00149 00150 # ------------------------------------------------------------------ 00151 # PROCEDURE: gdbtk_update - run all update hooks 00152 # 00153 # Use this procedure to force all widgets to update 00154 # themselves. This hook is usually run after command 00155 # that could change target state. 00156 # ------------------------------------------------------------------ 00157 proc gdbtk_update {} { 00158 00159 set e [UpdateEvent \#auto] 00160 GDBEventHandler::dispatch $e 00161 delete object $e 00162 00163 # Force the screen to update 00164 update 00165 } 00166 00167 # ------------------------------------------------------------------ 00168 # PROCEDURE: gdbtk_update_safe - run all update hooks in a safe way 00169 # 00170 # Use this procedure to force all widgets to update 00171 # themselves. This hook is usually run after command 00172 # that could change target state. 00173 # Like gdbtk_update but safe to be used in "after idle" 00174 # which is used in update hooks. 00175 # ------------------------------------------------------------------ 00176 proc gdbtk_update_safe {} { 00177 global gdb_running 00178 00179 # Fencepost: Do not update if we are running the target 00180 # We get here because script commands may have changed memory or 00181 # registers and "after idle" events registered as a consequence 00182 # If we try to update while the target is running we are doomed. 00183 if {!$gdb_running} { 00184 gdbtk_update 00185 } 00186 } 00187 00188 # ------------------------------------------------------------------ 00189 # PROCEDURE: gdbtk_idle - dispatch IdleEvent 00190 # 00191 # Use this procedure to free the UI for more user input. 00192 # This should only be run AFTER all communication with 00193 # the target has halted, otherwise the risk of two (or 00194 # more) widgets talking to the target arises. 00195 # ------------------------------------------------------------------ 00196 proc gdbtk_idle {} { 00197 global gdb_running 00198 00199 # Put the unfiltered hook back in place, just in case 00200 # somebody swapped it out, and then died before they 00201 # could replace it. 00202 gdb_restore_fputs 00203 00204 set err [catch {run_hooks gdb_idle_hook}] 00205 if {$err} { 00206 dbug E "Error running gdb_idle_hook: $::errorInfo" 00207 } 00208 00209 set e [IdleEvent \#auto] 00210 GDBEventHandler::dispatch $e 00211 delete object $e 00212 00213 if {!$gdb_running} { 00214 set err [catch {run_hooks gdb_no_inferior_hook} txt] 00215 if {$err} { 00216 dbug E "no_inferior_hook error: $txt" 00217 } 00218 } 00219 00220 # Force the screen to update 00221 update 00222 } 00223 00224 define_hook download_progress_hook 00225 00226 # ------------------------------------------------------------------ 00227 # PROCEDURE: gdbtk_quit_check - Ask if the user really wants to quit. 00228 # ------------------------------------------------------------------ 00229 proc gdbtk_quit_check {} { 00230 global gdb_downloading gdb_running gdb_exe_name 00231 00232 if {$gdb_downloading} { 00233 set msg "Downloading to target,\n really close the debugger?" 00234 if {![gdbtk_tcl_query $msg no]} { 00235 return 0 00236 } 00237 } elseif {$gdb_running} { 00238 # While we are running the inferior, gdb_cmd is fenceposted and 00239 # returns immediately. Therefore, we need to ask here. Do we need 00240 # to stop the target, too? 00241 set msg "A debugging session is active.\n" 00242 append msg "Do you still want to close the debugger?" 00243 if {![gdbtk_tcl_query $msg no]} { 00244 return 0 00245 } 00246 } 00247 00248 return 1 00249 } 00250 00251 # ------------------------------------------------------------------ 00252 # PROCEDURE: gdbtk_quit - Quit the debugger 00253 # Call this procedure anywhere the user can request to quit. 00254 # This procedure will ask all the right questions before 00255 # exiting. 00256 # ------------------------------------------------------------------ 00257 proc gdbtk_quit {} { 00258 if {[gdbtk_quit_check]} { 00259 gdbtk_force_quit 00260 } 00261 } 00262 00263 # ------------------------------------------------------------------ 00264 # PROCEDURE: gdbtk_force_quit - Quit the debugger immediately 00265 # ------------------------------------------------------------------ 00266 proc gdbtk_force_quit {} { 00267 # If we don't delete source windows, GDB hooks will 00268 # try to update them as we exit 00269 foreach win [ManagedWin::find SrcWin] { 00270 delete object $win 00271 } 00272 # Calling gdb_force_quit is probably not necessary here 00273 # because it should have been called when the source window(s) 00274 # were deleted, but just in case... 00275 gdb_force_quit 00276 } 00277 00278 # ------------------------------------------------------------------ 00279 # PROCEDURE: gdbtk_cleanup - called by GDB immediately 00280 # before exiting. Last chance to cleanup! 00281 # ------------------------------------------------------------------ 00282 proc gdbtk_cleanup {} { 00283 global gdb_exe_name 00284 00285 # Save the session 00286 if {$gdb_exe_name != ""} { 00287 Session::save 00288 } 00289 00290 # This is a sign that it is too late to be doing updates, etc... 00291 set ::gdb_shutting_down 1 00292 00293 # Shutdown the window manager and save all preferences 00294 # This way a "quit" in the console window will cause 00295 # preferences to be saved. 00296 ManagedWin::shutdown 00297 pref_save 00298 } 00299 00300 # ------------------------------------------------------------------ 00301 # PROC: gdbtk_tcl_query - 00302 # ------------------------------------------------------------------ 00303 proc gdbtk_tcl_query {message {default yes}} { 00304 global gdb_checking_for_exit gdbtk_state gdbtk_platform 00305 00306 # FIXME We really want a Help button here. But Tk's brain-damaged 00307 # modal dialogs won't really allow it. Should have async dialog 00308 # here. 00309 00310 set title "GDB" 00311 set modal "task" 00312 00313 # If we are checking whether to exit gdb, we want a system modal 00314 # box. Otherwise it may be hidden by some other program, and the 00315 # user will have no idea what is going on. 00316 if {[info exists gdb_checking_for_exit] && $gdb_checking_for_exit} { 00317 set modal "system" 00318 } 00319 00320 if {$gdbtk_platform(platform) == "windows"} { 00321 # On Windows, we want to only ask each question once. 00322 # If we're already asking the question, just wait for the answer 00323 # to come back. 00324 set ans [list answer $message] 00325 set pending [list pending $message] 00326 00327 if {[info exists gdbtk_state($pending)]} { 00328 incr gdbtk_state($pending) 00329 } else { 00330 set gdbtk_state($pending) 1 00331 set gdbtk_state($ans) {} 00332 00333 ide_messageBox [list set gdbtk_state($ans)] -icon warning \ 00334 -default $default -message $message -title $title \ 00335 -type yesno -modal $modal -parent . 00336 } 00337 00338 vwait gdbtk_state($ans) 00339 set r $gdbtk_state($ans) 00340 if {[incr gdbtk_state($pending) -1] == 0} { 00341 # Last call waiting for this answer, so clear it. 00342 unset gdbtk_state($pending) 00343 unset gdbtk_state($ans) 00344 } 00345 } else { 00346 # On Unix, apparently it doesn't matter how many times we ask a 00347 # question. 00348 set r [tk_messageBox -icon warning -default $default \ 00349 -message $message -title $title \ 00350 -type yesno -parent .] 00351 } 00352 00353 update idletasks 00354 return [expr {$r == "yes"}] 00355 } 00356 00357 # ------------------------------------------------------------------ 00358 # PROC: gdbtk_tcl_warning - 00359 # ------------------------------------------------------------------ 00360 proc gdbtk_tcl_warning {message} { 00361 debug "$message" 00362 00363 # ADD a warning message here if the gui must NOT display it 00364 # add the message at the beginning of the switch followed by - 00365 00366 switch -regexp $message { 00367 "Unable to find dynamic linker breakpoint function.*" {return} 00368 "Internal error.*" { gdbtk_tcl_fputs_error $message } 00369 "incomplete CFI.*" { gdbtk_tcl_fputs_error $message } 00370 "RTTI symbol not found for class.*" { gdbtk_tcl_fputs_error $message } 00371 "DW_AT.*" { gdbtk_tcl_fputs_error $message } 00372 "unsupported tag.*" { gdbtk_tcl_fputs_error $message } 00373 default {show_warning $message} 00374 } 00375 } 00376 00377 # ------------------------------------------------------------------ 00378 # PROC: show_warning - 00379 # ------------------------------------------------------------------ 00380 proc show_warning {message} { 00381 global gdbtk_platform 00382 00383 # FIXME We really want a Help button here. But Tk's brain-damaged 00384 # modal dialogs won't really allow it. Should have async dialog 00385 # here. 00386 set title "GDB" 00387 set modal "task" 00388 00389 # On Windows, we use ide_messageBox which runs the Win32 MessageBox function 00390 # in another thread. This permits a program which handles IDE requests from 00391 # other programs to not return from the request until the MessageBox completes. 00392 # This is not possible without using another thread, since the MessageBox 00393 # function call will be running its own event loop, and will be higher on the 00394 # stack than the IDE request. 00395 # 00396 # On Unix tk_messageBox runs in the regular Tk event loop, so 00397 # another thread is not required. 00398 00399 00400 if {$gdbtk_platform(platform) == "windows"} { 00401 ide_messageBox [list set r] -icon warning \ 00402 -default ok -message $message -title $title \ 00403 -type ok -modal $modal -parent . 00404 } else { 00405 set r [tk_messageBox -icon warning -default ok \ 00406 -message $message -title $title \ 00407 -type ok -parent .] 00408 } 00409 } 00410 00411 # ------------------------------------------------------------------ 00412 # PROC: gdbtk_tcl_ignorable_warning - 00413 # ------------------------------------------------------------------ 00414 proc gdbtk_tcl_ignorable_warning {class message} { 00415 catch {ManagedWin::open WarningDlg -center -transient \ 00416 -message [list $message] -ignorable $class} 00417 } 00418 00419 # ------------------------------------------------------------------ 00420 # PROC: gdbtk_tcl_fputs - 00421 # ------------------------------------------------------------------ 00422 proc gdbtk_tcl_fputs {message} { 00423 global gdbtk_state 00424 # Restore the fputs hook, in case anyone forgot to put it back... 00425 gdb_restore_fputs 00426 00427 if {[info exists gdbtk_state(console)] && $gdbtk_state(console) != ""} { 00428 $gdbtk_state(console) insert $message 00429 } 00430 } 00431 00432 # ------------------------------------------------------------------ 00433 # PROC: echo - 00434 # ------------------------------------------------------------------ 00435 proc echo {args} { 00436 gdbtk_tcl_fputs [concat $args]\n 00437 } 00438 00439 # ------------------------------------------------------------------ 00440 # PROC: gdbtk_tcl_fputs_error - write an error message 00441 # ------------------------------------------------------------------ 00442 proc gdbtk_tcl_fputs_error {message} { 00443 if {[info exists ::gdbtk_state(console)] && $::gdbtk_state(console) != ""} { 00444 $::gdbtk_state(console) insert $message err_tag 00445 update 00446 } 00447 } 00448 00449 # ------------------------------------------------------------------ 00450 # PROC: gdbtk_tcl_fputs_log - write a log message 00451 # ------------------------------------------------------------------ 00452 proc gdbtk_tcl_fputs_log {message} { 00453 if {[info exists ::gdbtk_state(console)] && $::gdbtk_state(console) != ""} { 00454 $::gdbtk_state(console) insert $message log_tag 00455 update 00456 } 00457 } 00458 00459 # ------------------------------------------------------------------ 00460 # PROC: gdbtk_tcl_fputs_target - write target output 00461 # ------------------------------------------------------------------ 00462 proc gdbtk_tcl_fputs_target {message} { 00463 if {$::gdbtk_state(console) == ""} { 00464 ManagedWin::open Console -force 00465 } 00466 $::gdbtk_state(console) insert $message target_tag 00467 update 00468 } 00469 00470 00471 # ------------------------------------------------------------------ 00472 # PROC: gdbtk_tcl_fputs_target_err - write target error output 00473 # ------------------------------------------------------------------ 00474 proc gdbtk_tcl_fputs_target_err {message} { 00475 if {$::gdbtk_state(console) == ""} { 00476 ManagedWin::open Console -force 00477 } 00478 $::gdbtk_state(console) insert $message err_tag 00479 } 00480 00481 # ------------------------------------------------------------------ 00482 # PROC: gdbtk_tcl_flush - 00483 # ------------------------------------------------------------------ 00484 proc gdbtk_tcl_flush {} { 00485 debug [info level 0] 00486 } 00487 00488 # ------------------------------------------------------------------ 00489 # PROC: gdbtk_tcl_start_variable_annotation - 00490 # ------------------------------------------------------------------ 00491 proc gdbtk_tcl_start_variable_annotation {valaddr ref_type stor_cl 00492 cum_expr field type_cast} { 00493 debug [info level 0] 00494 } 00495 00496 # ------------------------------------------------------------------ 00497 # PROC: gdbtk_tcl_end_variable_annotation - 00498 # ------------------------------------------------------------------ 00499 proc gdbtk_tcl_end_variable_annotation {} { 00500 debug [info level 0] 00501 } 00502 00503 # ------------------------------------------------------------------ 00504 # PROC: gdbtk_tcl_breakpoint - A breakpoint was changed -- notify 00505 # gui. 00506 # ------------------------------------------------------------------ 00507 proc gdbtk_tcl_breakpoint {action bpnum} { 00508 # debug "BREAKPOINT: $action $bpnum" 00509 set e [BreakpointEvent \#auto -action $action -number $bpnum] 00510 GDBEventHandler::dispatch $e 00511 delete object $e 00512 } 00513 00514 # ------------------------------------------------------------------ 00515 # PROC: gdbtk_tcl_tracepoint - A tracepoint was changed -- notify 00516 # gui. 00517 # ------------------------------------------------------------------ 00518 proc gdbtk_tcl_tracepoint {action tpnum} { 00519 # debug "TRACEPOINT: $action $tpnum" 00520 set e [TracepointEvent \#auto -action $action -number $tpnum] 00521 GDBEventHandler::dispatch $e 00522 delete object $e 00523 } 00524 00525 # ------------------------------------------------------------------ 00526 # PROC: gdbtk_tcl_trace_find_hook - 00527 # ------------------------------------------------------------------ 00528 proc gdbtk_tcl_trace_find_hook {arg from_tty} { 00529 # debug "$arg $from_tty" 00530 run_hooks gdb_trace_find_hook $arg $from_tty 00531 } 00532 00533 ################################################################ 00534 # 00535 # Handle `readline' interface. 00536 # 00537 00538 # Run a command that is known to use the "readline" interface. We set 00539 # up the appropriate buffer, and then run the actual command via 00540 # gdb_cmd. Calls into the "readline" callbacks just return values 00541 # from our list. 00542 00543 # ------------------------------------------------------------------ 00544 # PROC: gdb_run_readline_command - 00545 # ------------------------------------------------------------------ 00546 proc gdb_run_readline_command {command args} { 00547 global gdbtk_state 00548 debug "$command $args" 00549 set gdbtk_state(readlineArgs) $args 00550 set gdbtk_state(readlineShowUser) 1 00551 gdb_cmd $command 00552 } 00553 00554 # ------------------------------------------------------------------ 00555 # PROC: gdb_run_readline_command_no_output 00556 # Run a readline command, but don't show the commands to the user. 00557 # ------------------------------------------------------------------ 00558 proc gdb_run_readline_command_no_output {command args} { 00559 global gdbtk_state 00560 debug "$command $args" 00561 set gdbtk_state(readlineArgs) $args 00562 set gdbtk_state(readlineShowUser) 0 00563 gdb_cmd $command 00564 } 00565 00566 # ------------------------------------------------------------------ 00567 # PROC: gdbtk_tcl_readline_begin - 00568 # ------------------------------------------------------------------ 00569 proc gdbtk_tcl_readline_begin {message} { 00570 global gdbtk_state 00571 # debug 00572 set gdbtk_state(readline) 0 00573 if {$gdbtk_state(console) != "" && $gdbtk_state(readlineShowUser)} { 00574 $gdbtk_state(console) insert $message 00575 } 00576 } 00577 00578 # ------------------------------------------------------------------ 00579 # PROC: gdbtk_tcl_readline - 00580 # ------------------------------------------------------------------ 00581 proc gdbtk_tcl_readline {prompt} { 00582 global gdbtk_state 00583 # debug "prompt=$prompt" 00584 if {[info exists gdbtk_state(readlineArgs)]} { 00585 # Not interactive, so pop the list, and print element. 00586 set cmd [lvarpop gdbtk_state(readlineArgs)] 00587 if {$gdbtk_state(console) != "" && $gdbtk_state(readlineShowUser)} { 00588 $gdbtk_state(console) insert $cmd 00589 } 00590 } else { 00591 # Interactive. 00592 # debug "interactive" 00593 set gdbtk_state(readline) 1 00594 $gdbtk_state(console) activate $prompt 00595 vwait gdbtk_state(readline_response) 00596 set cmd $gdbtk_state(readline_response) 00597 # debug "got response: $cmd" 00598 unset gdbtk_state(readline_response) 00599 set gdbtk_state(readline) 0 00600 } 00601 return $cmd 00602 } 00603 00604 # ------------------------------------------------------------------ 00605 # PROC: gdbtk_tcl_readline_end - 00606 # ------------------------------------------------------------------ 00607 proc gdbtk_tcl_readline_end {} { 00608 global gdbtk_state 00609 # debug 00610 catch {unset gdbtk_state(readlineArgs)} 00611 catch {unset gdbtk_state(readlineActive)} 00612 } 00613 00614 # ------------------------------------------------------------------ 00615 # PROC: gdbtk_tcl_busy - this is called immediately before gdb 00616 # executes a command. 00617 # 00618 # ------------------------------------------------------------------ 00619 proc gdbtk_tcl_busy {} { 00620 global gdbtk_state 00621 if {[incr gdbtk_state(busyCount)] == 1} { 00622 gdbtk_busy 00623 } 00624 } 00625 00626 ################################################################ 00627 # 00628 # 00629 # 00630 00631 # ------------------------------------------------------------------ 00632 # PROC: gdbtk_tcl_idle - this is called immediately after gdb 00633 # executes a command. 00634 # ------------------------------------------------------------------ 00635 proc gdbtk_tcl_idle {} { 00636 global gdbtk_state 00637 if {$gdbtk_state(busyCount) > 0 00638 && [incr gdbtk_state(busyCount) -1] == 0} { 00639 gdbtk_update 00640 gdbtk_idle 00641 } 00642 } 00643 00644 # ------------------------------------------------------------------ 00645 # PROC: gdbtk_tcl_tstart - 00646 # ------------------------------------------------------------------ 00647 proc gdbtk_tcl_tstart {} { 00648 set srcwin [lindex [manage find src] 0] 00649 $srcwin.toolbar do_tstop 0 00650 00651 } 00652 00653 # ------------------------------------------------------------------ 00654 # PROC: gdbtk_tcl_tstop - 00655 # ------------------------------------------------------------------ 00656 proc gdbtk_tcl_tstop {} { 00657 set srcwin [lindex [manage find src] 0] 00658 $srcwin.toolbar do_tstop 0 00659 00660 } 00661 00662 00663 # ------------------------------------------------------------------ 00664 # PROC: gdbtk_tcl_display - 00665 # 00666 # A display changed. ACTION is `enable', `disable', `delete', 00667 # `create', or `update'. VALUE is only meaningful in the `update' 00668 # case. 00669 # ------------------------------------------------------------------ 00670 proc gdbtk_tcl_display {action number {value {}}} { 00671 # Handle create explicitly. 00672 if {$action == "create"} { 00673 manage create_if_never data 00674 } 00675 run_hooks gdb_display_change_hook $action $number $value 00676 } 00677 00678 # ------------------------------------------------------------------ 00679 # PROCEDURE: gdbtk_register_changed 00680 # This hook is called from value_assign to inform us that 00681 # the user has changed the contents of a register. 00682 # ------------------------------------------------------------------ 00683 proc gdbtk_register_changed {} { 00684 after idle gdbtk_update_safe 00685 } 00686 00687 # ------------------------------------------------------------------ 00688 # PROCEDURE: gdbtk_memory_changed 00689 # This hook is called from value_assign to inform us that 00690 # the user has changed the contents of memory (including 00691 # the program's variables). 00692 # ------------------------------------------------------------------ 00693 proc gdbtk_memory_changed {} { 00694 after idle gdbtk_update_safe 00695 } 00696 00697 #################################################################### 00698 # # 00699 # FILE HOOKS # 00700 # # 00701 # There are a number of hooks that are installed in gdb to # 00702 # aid with file-like commands (selecting an exectuable and # 00703 # loading symbols): # 00704 # - exec_file_display_hook # 00705 # Called in exec_file_command. The tcl hook is # 00706 # "gdbtk_tcl_exec_file_display" # 00707 # - file_changed_hook # 00708 # Called in file_command. The tcl hook is # 00709 # "gdbtk_tcl_file_changed" # 00710 # - deprecated_pre_add_symbol_hook # 00711 # Called in symbol_file_add before loading. The tcl # 00712 # hook is "gdbtk_tcl_pre_add_symbol" # 00713 # - deprecated_post_add_symbol_hook # 00714 # Called in symbol_file_add when finished loading # 00715 # a symbol file. The tcl hook is # 00716 # "gdbtk_tcl_post_add_symbol" # 00717 # # 00718 # Together, these hooks should give the gui enough information # 00719 # to cover the two most common uses of file commands: # 00720 # 1. executable with symbols # 00721 # 2. separate executable and symbol file(s) # 00722 # # 00723 #################################################################### 00724 define_hook file_changed_hook 00725 00726 # ------------------------------------------------------------------ 00727 # PROCEDURE: gdbtk_tcl_pre_add_symbol 00728 # This hook is called before any symbol files 00729 # are loaded so that we can inform the user. 00730 # ------------------------------------------------------------------ 00731 proc gdbtk_tcl_pre_add_symbol {file} { 00732 00733 gdbtk_busy 00734 00735 # Display some feedback to the user 00736 set srcs [ManagedWin::find SrcWin] 00737 foreach w $srcs { 00738 $w set_status "Reading symbols from $file..." 00739 } 00740 update idletasks 00741 } 00742 00743 # ------------------------------------------------------------------ 00744 # PROCEDURE: gdbtk_tcl_post_add_symbol 00745 # This hook is called after we finish reading a symbol 00746 # file, so the source windows' combo boxes need filling. 00747 # ------------------------------------------------------------------ 00748 proc gdbtk_tcl_post_add_symbol {} { 00749 00750 set srcs [ManagedWin::find SrcWin] 00751 foreach w $srcs { 00752 $w fillNameCB 00753 } 00754 gdbtk_idle 00755 } 00756 00757 # ------------------------------------------------------------------ 00758 # PROCEDURE: gdbtk_tcl_file_changed 00759 # This hook is called whenever the exec file changes. 00760 # This is called AFTER symbol reading, so it is 00761 # ok to point to main when we get called. 00762 # ------------------------------------------------------------------ 00763 proc gdbtk_tcl_file_changed {filename} { 00764 00765 if {$filename == ""} { 00766 gdb_clear_file 00767 catch {run_hooks gdb_clear_file_hook} 00768 set ::gdb_exe_name "" 00769 set ::gdb_loaded 0 00770 set ::gdb_running 0 00771 gdbtk_update 00772 } else { 00773 SrcWin::point_to_main 00774 run_hooks file_changed_hook 00775 } 00776 } 00777 00778 # ------------------------------------------------------------------ 00779 # PROCEDURE: gdbtk_tcl_exec_file_display 00780 # This hook is called from exec_file_command. It's purpose 00781 # is to setup the gui for a new file. Note that we cannot 00782 # look for main, since this hook is called BEFORE we 00783 # read symbols. If the user used the "file" command, 00784 # gdbtk_tcl_file_changed will set the source window to 00785 # look at main. If the user used "exec-file" and "add-symbol" 00786 # commands, then we cannot look for main. 00787 # ------------------------------------------------------------------ 00788 proc gdbtk_tcl_exec_file_display {filename} { 00789 global gdb_exe_changed 00790 00791 # DO NOT CALL set_exe here! 00792 00793 # Clear out the GUI, don't do it if filename is "" so that 00794 # you avoid distracting flashes in the source window. 00795 00796 if {$filename != ""} { 00797 gdbtk_clear_file 00798 } 00799 00800 # set_exe calls file command with the filename in 00801 # quotes, so we need to strip them here. 00802 # We need to make sure that we turn filename into 00803 # an absolute path or sessions won't work. 00804 if {[file tail $filename] == $filename} { 00805 # want full pathname 00806 set filename [file join $::gdb_current_directory $filename] 00807 } 00808 set_exe_name $filename 00809 set gdb_exe_changed 0 00810 00811 SrcWin::point_to_main 00812 } 00813 00814 # ------------------------------------------------------------------ 00815 # PROCEDURE: gdbtk_locate_main 00816 # This proc tries to locate a suitable main function from 00817 # a list of names defined in the gdb/main_names preference; 00818 # returns the linespec (see below) if found, or a null string 00819 # if not. 00820 # 00821 # The return linespec looks like this: 00822 # 0: basename of the file 00823 # 1: function name 00824 # 2: full filename 00825 # 3: source line number 00826 # 4: address 00827 # 5: current PC - which will often be the same as address, but not when 00828 # we are browsing, or walking the stack. 00829 # 6: shared library name if the pc is in a shared lib 00830 # 00831 # ------------------------------------------------------------------ 00832 proc gdbtk_locate_main {{init ""}} { 00833 global _main_cache gdb_exe_name 00834 debug 00835 00836 if {$init == "" && $_main_cache != ""} { 00837 #debug "returning $_main_cache from cache" 00838 return $_main_cache 00839 } 00840 set _main_cache {} 00841 00842 set main_names [pref get gdb/main_names] 00843 foreach main $main_names { 00844 if {![catch {gdb_loc $main} linespec]} { 00845 set _main_cache $linespec 00846 break 00847 } 00848 } 00849 if {$_main_cache == {} 00850 && ![catch gdb_entry_point entry_point] 00851 && ![catch {gdb_loc "*$entry_point"} linespec]} { 00852 set _main_cache $linespec 00853 } 00854 00855 # need to see if result is valid 00856 lassign $_main_cache file func ffile line addr rest 00857 if {$addr == 0x0 && $func == {}} { set _main_cache {} } 00858 00859 #debug "returning $_main_cache" 00860 return $_main_cache 00861 } 00862 00863 ############################################## 00864 # The rest of this file is an assortment of Tcl wrappers 00865 # for various bits of gdb functionality. 00866 # 00867 ############################################# 00868 00869 # ------------------------------------------------------------------ 00870 # PROC: set_exe_name - Update the executable name 00871 # ------------------------------------------------------------------ 00872 proc set_exe_name {exe} { 00873 global gdb_exe_name gdb_exe_changed 00874 #debug "exe=$exe gdb_exe_name=$gdb_exe_name" 00875 00876 set gdb_exe_name $exe 00877 set gdb_exe_changed 1 00878 } 00879 00880 00881 # ------------------------------------------------------------------ 00882 # PROC: set_exe - 00883 # ------------------------------------------------------------------ 00884 proc set_exe {} { 00885 global gdb_exe_name gdb_exe_changed gdb_target_changed gdb_loaded file_done 00886 # debug "gdb_exe_changed=$gdb_exe_changed gdb_exe_name=$gdb_exe_name" 00887 if {$gdb_exe_changed} { 00888 set gdb_exe_changed 0 00889 if {$gdb_exe_name == ""} { return } 00890 set err [catch {gdb_cmd "file '$gdb_exe_name'" 1} msg] 00891 if {$err} { 00892 dbug E "$msg" 00893 set l [split $msg :] 00894 set errtxt [join [lrange $l 1 end] :] 00895 set msg "Error loading \"$gdb_exe_name\":\n" 00896 append msg $errtxt 00897 tk_messageBox -title "Error" -message $msg -icon error \ 00898 -type ok 00899 set gdb_exe_name {} 00900 set file_done 0 00901 return 00902 } elseif {[string match {*no debugging symbols found*} $msg]} { 00903 tk_messageBox -icon error -default ok \ 00904 -title "GDB" -type ok \ 00905 -message "This executable has no debugging information." 00906 } 00907 00908 # force new target command 00909 set gdb_target_changed 1 00910 set gdb_loaded 0 00911 set file_done 1 00912 } 00913 } 00914 00915 # ------------------------------------------------------------------ 00916 # _open_file - open a file dialog to select a file for debugging. 00917 # If filename is not "", then open this file. 00918 # ------------------------------------------------------------------ 00919 00920 proc _open_file {{file ""}} { 00921 global gdb_running gdb_downloading gdbtk_platform 00922 00923 if {$gdb_running || $gdb_downloading} { 00924 # We are already running/downloading something.. 00925 if {$gdb_running} { 00926 set msg "A debugging session is active.\nAbort session and load new file?" 00927 } else { 00928 set msg "A download is in progress.\nAbort download and load new file?" 00929 } 00930 if {![gdbtk_tcl_query $msg no]} { 00931 return 0 00932 } 00933 } 00934 00935 if {[string compare $file ""] == 0} { 00936 set curFocus [focus] 00937 00938 # Make sure that this is really a modal dialog... 00939 # FIXME: Add a disable_all to ide_grab_support. 00940 00941 ide_grab_support disable_except {} 00942 00943 set file [tk_getOpenFile -parent . -title "Load New Executable"] 00944 00945 ide_grab_support enable_all 00946 00947 # If no one had the focus before, leave it that way (since I 00948 # am not sure how this could happen... Also, the vwait in 00949 # tk_getOpenFile could have allowed the curFocus window to actually 00950 # be destroyed, so make sure it is still around. 00951 00952 if {$curFocus != "" && [winfo exists $curFocus]} { 00953 raise [winfo toplevel $curFocus] 00954 focus $curFocus 00955 } 00956 } elseif {![file exists $file]} { 00957 tk_messageBox -message "File \"$file\" does not exist" 00958 return 0 00959 } 00960 00961 00962 if {$file == ""} { 00963 return 0 00964 } 00965 # Add the base dir for this file to the source search path. 00966 set root [file dirname $file] 00967 if {$gdbtk_platform(os) == "cygwin"} { 00968 set root [ide_cygwin_path to_posix $root] 00969 set file [ide_cygwin_path to_posix $file] 00970 } 00971 00972 catch {gdb_cmd "cd $root"} 00973 00974 # Clear out gdb's internal state, so that it will allow us 00975 # (the gui) to ask the user questions. 00976 gdb_clear_file 00977 00978 # The gui needs to set this... 00979 set_exe_name $file 00980 00981 # set_exe needs to be called anywhere the gui does a file_command... 00982 if {[set_exe] == "cancel"} { 00983 gdbtk_update 00984 gdbtk_idle 00985 return 0 00986 } 00987 00988 return 1 00989 } 00990 00991 # ------------------------------------------------------------------ 00992 # _close_file - close the current executable and prepare for 00993 # another executable. 00994 # ------------------------------------------------------------------ 00995 proc _close_file {} { 00996 00997 # If there is already an inferior, ask him if he wants to close 00998 # the file. If there is already an exec file loaded (and not run) 00999 # also ask, but don't ask twice. 01000 set okay 1 01001 if {[gdb_target_has_execution]} { 01002 set okay [gdbtk_tcl_query "Program is already running.\nClose file anyway?"] 01003 } elseif {$::gdb_exe_name != ""} { 01004 set okay [gdbtk_tcl_query "Program already loaded.\nClose file anyway?"] 01005 } else { 01006 # No exec file yet 01007 return 01008 } 01009 01010 if {$okay} { 01011 Session::save 01012 gdb_clear_file 01013 gdbtk_tcl_file_changed "" 01014 01015 # Print out a little message to all console windows 01016 foreach cw [ManagedWin::find Console] { 01017 $cw insert "No executable file now.\n" 01018 } 01019 } 01020 } 01021 01022 # ------------------------------------------------------------------ 01023 # PROC: set_target_name - Update the target name. 01024 # 01025 # This function will prompt for a new target and update 01026 # all variables. 01027 # 01028 # If $prompt is 0 it will just update gdb_target_cmd from gdb_target. 01029 # 01030 # RETURN: 01031 # 1 if successful, 01032 # 0 if the not (the user canceled the target selection dialog) 01033 # ------------------------------------------------------------------ 01034 proc set_target_name {{prompt 1}} { 01035 global gdb_target_name gdb_target_changed gdb_exe_changed 01036 global gdb_target_cmd gdb_pretty_name 01037 # debug 01038 set cmd_tmp $gdb_target_cmd 01039 set name_tmp $gdb_target_name 01040 01041 # debug "gdb_target_name=$gdb_target_name; name_tmp=$name_tmp" 01042 if {$prompt} { 01043 set win [ManagedWin::open TargetSelection -exportcancel 1 -center \ 01044 -transient] 01045 # need to call update here so the target selection dialog can take over 01046 update idletasks 01047 } 01048 01049 # debug "gdb_target_name=$gdb_target_name" 01050 if {$gdb_target_name == "CANCEL"} { 01051 set gdb_target_cmd $cmd_tmp 01052 set gdb_target_name $name_tmp 01053 return 0 01054 } 01055 set target $gdb_target_name 01056 set targ [TargetSelection::getname $target cmd] 01057 set gdb_target_cmd $cmd_tmp 01058 set gdb_pretty_name [TargetSelection::getname $target pretty-name] 01059 01060 # debug "target=$target pretty_name=$gdb_pretty_name" 01061 set targ_opts "" 01062 switch -regexp -- $gdb_target_name { 01063 sim|ice { 01064 set targ $gdb_target_name 01065 set targ_opts [pref getd gdb/load/${gdb_target_name}-opts] 01066 } 01067 default { 01068 set port [pref getd gdb/load/$target-port] 01069 if {$port == ""} { 01070 set port [pref get gdb/load/default-port] 01071 } 01072 set portnum [pref getd gdb/load/$target-portname] 01073 if {$portnum == ""} { 01074 set portnum [pref get gdb/load/default-portname] 01075 } 01076 set hostname [pref getd gdb/load/$target-hostname] 01077 if {$hostname == ""} { 01078 set hostname [pref getd gdb/load/default-hostname] 01079 } 01080 # replace "com1" with the real port name 01081 set targ [lrep $targ "com1" $port] 01082 # replace "tcpX" with hostname:portnum 01083 set targ [lrep $targ "tcpX" ${hostname}:${portnum}] 01084 # replace "ethX" with hostname 01085 set targ [lrep $targ "ethX" e=${hostname}] 01086 } 01087 } 01088 01089 # debug "targ=$targ gdb_target_cmd=$gdb_target_cmd" 01090 if {$gdb_target_cmd != $targ || $gdb_target_changed} { 01091 set gdb_target_changed 1 01092 set gdb_target_cmd "$targ $targ_opts" 01093 } 01094 return 1 01095 } 01096 01097 # ------------------------------------------------------------------ 01098 # PROC: set_target - Change the target 01099 # ------------------------------------------------------------------ 01100 proc set_target {} { 01101 global gdb_target_cmd gdb_target_changed gdb_pretty_name gdb_target_name 01102 #debug "gdb_target_changed=$gdb_target_changed gdb_target_cmd=\"$gdb_target_cmd\"" 01103 #debug "gdb_target_name=$gdb_target_name" 01104 if {$gdb_target_cmd == "" && ![TargetSelection::native_debugging]} { 01105 if {$gdb_target_name == ""} { 01106 set prompt 1 01107 01108 # get the default 01109 #set gdb_target_name [pref getd gdb/load/target] 01110 } else { 01111 set prompt 0 01112 } 01113 if {![set_target_name $prompt]} { 01114 set gdb_target_name "" 01115 return CANCELED 01116 } 01117 } 01118 01119 if {$gdb_target_changed} { 01120 set srcWin [lindex [ManagedWin::find SrcWin] 0] 01121 01122 $srcWin set_status "Trying to communicate with target $gdb_pretty_name" 1 01123 update 01124 catch {gdb_cmd "detach"} 01125 debug "CONNECTING TO TARGET: $gdb_target_cmd" 01126 gdbtk_busy 01127 set err [catch {gdb_immediate "target $gdb_target_cmd"} msg ] 01128 $srcWin set_status 01129 gdbtk_idle 01130 01131 if {$err} { 01132 if {[string first "Program not killed" $msg] != -1} { 01133 return CANCELED 01134 } 01135 update 01136 set dialog_title "GDB" 01137 set debugger_name "GDB" 01138 tk_messageBox -icon error -title $dialog_title -type ok \ 01139 -message "$msg\n\n$debugger_name cannot connect to the target board\ 01140 using [lindex $gdb_target_cmd 1].\nVerify that the board is securely connected and, if\ 01141 necessary,\nmodify the port setting with the debugger preferences." 01142 return ERROR 01143 } 01144 01145 if {![catch {pref get gdb/load/$gdb_target_name-after_attaching} aa] && $aa != ""} { 01146 if {[catch {gdb_cmd $aa} err]} { 01147 catch {[ManagedWin::find Console] insert $err err_tag} 01148 } 01149 } 01150 set gdb_target_changed 0 01151 return TARGET_CHANGED 01152 } 01153 return TARGET_UNCHANGED 01154 } 01155 01156 # ------------------------------------------------------------------ 01157 # PROC: run_executable - 01158 # 01159 # This procedure is used to run an executable. It is called when the 01160 # run button is used. 01161 # ------------------------------------------------------------------ 01162 proc run_executable { {auto_start 1} } { 01163 global gdb_loaded gdb_downloading gdb_target_name 01164 global gdb_exe_changed gdb_target_changed gdb_program_has_run 01165 global gdb_running gdb_exe_name gdbtk_platform 01166 01167 # debug "auto_start=$auto_start gdb_target_name=$gdb_target_name" 01168 01169 set gdb_running_saved $gdb_running 01170 set gdb_running 0 01171 01172 # No executable was specified. Prompt the user for one. 01173 if {$gdb_exe_name == ""} { 01174 if {[_open_file]} { 01175 run_executable $auto_start 01176 return 01177 } else { 01178 # The user canceled the load of a new executable. 01179 return 01180 } 01181 } 01182 01183 if {$gdb_downloading} { return } 01184 if {[pref get gdb/control_target]} { 01185 # Breakpoint mode 01186 set_exe 01187 01188 # Attach 01189 if {$gdb_target_name == "" || [pref get gdb/src/run_attach]} { 01190 set r [gdbtk_attach_remote] 01191 if {$r == "ATTACH_CANCELED" || $r == "ATTACH_ERROR"} { 01192 return 01193 } 01194 } 01195 01196 # Download 01197 if {[pref get gdb/src/run_load] && $gdb_target_name != "exec"} { 01198 debug "Downloading..." 01199 set gdb_loaded 0 01200 01201 # if the app has not been downloaded or the app has already 01202 # started, we need to redownload before running 01203 if {!$gdb_loaded} { 01204 if {[Download::download_it]} { 01205 # user cancelled the command 01206 # debug "user cancelled the command $gdb_running" 01207 set gdb_loaded 0 01208 gdbtk_update 01209 gdbtk_idle 01210 } 01211 if {!$gdb_loaded} { 01212 # The user cancelled the download after it started 01213 # debug "User cancelled the download after it started $gdb_running" 01214 gdbtk_update 01215 gdbtk_idle 01216 return 01217 } 01218 } 01219 } 01220 01221 # _Now_ set/clear breakpoints 01222 if {[pref get gdb/load/exit] && ![TargetSelection::native_debugging]} { 01223 debug "Setting new BP at exit" 01224 catch {gdb_cmd "clear exit"} 01225 catch {gdb_cmd "break exit"} 01226 } 01227 01228 if {[pref get gdb/load/main]} { 01229 set main "main" 01230 if {[set linespec [gdbtk_locate_main]] != ""} { 01231 set main [lindex $linespec 1] 01232 } 01233 debug "Setting new BP at $main" 01234 catch {gdb_cmd "clear $main"} 01235 catch {gdb_cmd "break $main"} 01236 } 01237 01238 # set BP at user-specified function 01239 if {[pref get gdb/load/bp_at_func]} { 01240 foreach bp [pref get gdb/load/bp_func] { 01241 debug "Setting BP at $bp" 01242 catch {gdb_cmd "clear $bp"} 01243 catch {gdb_cmd "break $bp"} 01244 } 01245 } 01246 01247 # This is a hack. If the target is "sim" the opts are appended 01248 # to the target command. Otherwise they are assumed to be command line 01249 # args. What about simulators that accept command line args? 01250 if {$gdb_target_name != "sim"} { 01251 # set args 01252 set gdb_args [pref getd gdb/load/$gdb_target_name-opts] 01253 if { $gdb_args != ""} { 01254 debug "set args $gdb_args" 01255 gdb_set_inferior_args $gdb_args 01256 } 01257 } 01258 01259 # If the user requested it, start an xterm for use as the 01260 # inferior's tty. 01261 if {$gdbtk_platform(platform) != "windows" 01262 && [pref getd gdb/process/xtermtty] == "yes"} { 01263 tty::create 01264 } 01265 01266 # 01267 # Run 01268 01269 if {$auto_start} { 01270 if {[pref get gdb/src/run_run]} { 01271 debug "Runnning target..." 01272 set run run 01273 } else { 01274 debug "Continuing target..." 01275 set run cont 01276 } 01277 if {$gdb_target_name == "exec"} { 01278 set run run 01279 } 01280 if {[catch {gdb_immediate $run} msg]} { 01281 dbug W "msg=$msg" 01282 gdbtk_idle 01283 if {[string match "*help target*" $msg]} { 01284 set_target_name 01285 run_executable $auto_start 01286 return 01287 } 01288 if {[string match "No executable*" $msg]} { 01289 # No executable was specified. Prompt the user for one. 01290 if {[_open_file]} { 01291 run_executable $auto_start 01292 } else { 01293 debug "CANCELLED" 01294 } 01295 return 01296 } 01297 set gdb_running $gdb_running_saved 01298 } else { 01299 debug RUNNING 01300 set gdb_running 1 01301 } 01302 } else { 01303 SrcWin::point_to_main 01304 } 01305 01306 gdbtk_update 01307 gdbtk_idle 01308 } elseif {[pref get gdb/mode]} { 01309 # tracepoint -- need to tstart 01310 set gdb_running 1 01311 tstart 01312 } 01313 return 01314 } 01315 01316 # ------------------------------------------------------------------ 01317 # PROC: gdbtk_attach_remote - attach to the target 01318 # This proc returns the following status messages: 01319 # 01320 # ATTACH_ERROR: An error occurred connecting to target. 01321 # ATTACH_CANCELED: The attach was canceled. 01322 # ATTACH_TARGET_CHANGED: Successfully attached, target changed. 01323 # ATTACH_TARGET_UNCHANGED: Successfully attached, target unchanged. 01324 # UNKNOWN: An unknown error occurred. 01325 # ------------------------------------------------------------------ 01326 proc gdbtk_attach_remote {} { 01327 global gdb_loaded 01328 01329 debug "Attaching...." 01330 set r UNKNOWN 01331 while {1} { 01332 01333 switch [set_target] { 01334 01335 ERROR { 01336 # target command failed, ask for a new target name 01337 if {![set_target_name]} { 01338 # canceled again 01339 set r ATTACH_ERROR 01340 break 01341 } 01342 } 01343 01344 TARGET_CHANGED { 01345 # success -- target changed 01346 set gdb_loaded 0 01347 set r ATTACH_TARGET_CHANGED 01348 break 01349 } 01350 01351 CANCELED { 01352 # command cancelled by user 01353 set r ATTACH_CANCELED 01354 break 01355 } 01356 01357 TARGET_UNCHANGED { 01358 # success -- target NOT changed (i.e., rerun) 01359 set r ATTACH_TARGET_UNCHANGED 01360 break 01361 } 01362 } 01363 } 01364 01365 # debug "Attach returning: \"$r\"" 01366 return $r 01367 } 01368 01369 # ------------------------------------------------------------------ 01370 # PROC: gdbtk_connect: connect to a remote target 01371 # in asynch mode if async is 1 01372 # ------------------------------------------------------------------ 01373 proc gdbtk_connect {{async 0}} { 01374 global file_done 01375 01376 debug "async=$async" 01377 01378 gdbtk_busy 01379 01380 set result [gdbtk_attach_remote] 01381 switch $result { 01382 ATTACH_ERROR { 01383 set successful 0 01384 } 01385 01386 ATTACH_TARGET_CHANGED { 01387 if {[pref get gdb/load/check] && $file_done} { 01388 set err [catch {gdb_cmd "compare-sections"} errTxt] 01389 if {$err} { 01390 set successful 0 01391 tk_messageBox -title "Error" -message $errTxt \ 01392 -icon error -type ok 01393 break 01394 } 01395 } 01396 01397 tk_messageBox -title "GDB" -message "Successfully connected" \ 01398 -icon info -type ok 01399 set successful 1 01400 } 01401 01402 ATTACH_CANCELED { 01403 tk_messageBox -title "GDB" -message "Connection Canceled" -icon info \ 01404 -type ok 01405 set successful 0 01406 } 01407 01408 ATTACH_TARGET_UNCHANGED { 01409 tk_messageBox -title "GDB" -message "Successfully connected" \ 01410 -icon info -type ok 01411 set successful 1 01412 } 01413 01414 default { 01415 dbug E "Unhandled response from gdbtk_attach_remote: \"$result\"" 01416 set successful 0 01417 } 01418 } 01419 01420 gdbtk_idle 01421 01422 # Whenever we attach, we need to do an update 01423 if {$successful} { 01424 gdbtk_attached 01425 } 01426 return $successful 01427 } 01428 01429 # ------------------------------------------------------------------ 01430 # PROC: gdbtk_step - step the target 01431 # ------------------------------------------------------------------ 01432 proc gdbtk_step {} { 01433 catch {gdb_immediate step} 01434 } 01435 01436 # ------------------------------------------------------------------ 01437 # PROC: gdbtk_next 01438 # ------------------------------------------------------------------ 01439 proc gdbtk_next {} { 01440 catch {gdb_immediate next} 01441 } 01442 01443 # ------------------------------------------------------------------ 01444 # PROC: gdbtk_finish 01445 # ------------------------------------------------------------------ 01446 proc gdbtk_finish {} { 01447 catch {gdb_immediate finish} 01448 } 01449 01450 # ------------------------------------------------------------------ 01451 # PROC: gdbtk_continue 01452 # ------------------------------------------------------------------ 01453 proc gdbtk_continue {} { 01454 catch {gdb_immediate continue} 01455 } 01456 01457 # ------------------------------------------------------------------ 01458 # PROC: gdbtk_stepi 01459 # ------------------------------------------------------------------ 01460 proc gdbtk_stepi {} { 01461 catch {gdb_immediate stepi} 01462 } 01463 01464 # ------------------------------------------------------------------ 01465 # PROC: gdbtk_nexti 01466 # ------------------------------------------------------------------ 01467 proc gdbtk_nexti {} { 01468 catch {gdb_immediate nexti} 01469 } 01470 01471 # ------------------------------------------------------------------ 01472 # PROC: gdbtk_attached 01473 # ------------------------------------------------------------------ 01474 # 01475 # This is called AFTER gdb has successfully done an attach. Use it to 01476 # bring the GUI up to a current state... 01477 proc gdbtk_attached {} { 01478 gdbtk_update 01479 } 01480 01481 # ------------------------------------------------------------------ 01482 # PROC: gdbtk_detached 01483 # ------------------------------------------------------------------ 01484 # 01485 # This is called AFTER gdb has successfully done an detach. Use it to 01486 # bring the GUI up to a current state... 01487 proc gdbtk_detached {} { 01488 if {!$::gdb_shutting_down} { 01489 run_hooks gdb_no_inferior_hook 01490 } 01491 } 01492 01493 # ------------------------------------------------------------------ 01494 # PROC: gdbtk_stop 01495 # ------------------------------------------------------------------ 01496 # 01497 # The stop button is tricky. In order to use the stop button, 01498 # the debugger must be able to keep gui alive while target_wait is 01499 # blocking (so that the user can interrupt or detach from it). 01500 # 01501 # The best solution for this is to capture gdb deep down where it can 01502 # block. For _any_ target board, this will be in either serial or 01503 # socket code. These places call deprecated_ui_loop_hook to keep us 01504 # alive. For native unix, we use an interval timer. Simulators either 01505 # call deprecated_ui_loop_hook directly (older sims, at least) or they 01506 # call gdb's os_poll_quit callback, where we insert a call to 01507 # deprecated_ui_loop_hook. Some targets (like v850ice and windows 01508 # native) require a call to deprecated_ui_loop_hook directly in 01509 # target_wait. See comments before gdb_stop and x_event to find out 01510 # more about how this is accomplished. 01511 # 01512 # The stop button's behavior: 01513 # Pressing the stop button should attempt to stop the target. If, after 01514 # some time (like 3 seconds), gdb fails to fall out of target_wait (i.e., 01515 # the gui's idle hooks are run), then open a dialog asking the user if 01516 # he'd like to detach. 01517 proc gdbtk_stop {} { 01518 global _gdbtk_stop 01519 01520 if {$_gdbtk_stop(timer) == ""} { 01521 add_hook gdb_idle_hook gdbtk_stop_idle_callback 01522 set _gdbtk_stop(timer) [after 15000 gdbtk_detach] 01523 catch {gdb_stop} 01524 } 01525 } 01526 01527 # ------------------------------------------------------------------ 01528 # PROC: gdbtk_stop_idle_callback 01529 # ------------------------------------------------------------------ 01530 # This callback normally does nothing. When the stop button has 01531 # been pressed, though, and gdb has successfully stopped the target, 01532 # this callback will clean up after gdbtk_stop, removing the "Detach" 01533 # dialog (if it's open) and gettingg rid of any outstanding timers 01534 # and hooks. 01535 proc gdbtk_stop_idle_callback {} { 01536 global _gdbtk_stop gdbtk_state 01537 01538 # Check if the dialog asking if user wants to detach is open 01539 # and unpost it if it exists. 01540 if {$_gdbtk_stop(msg) != ""} { 01541 set ans [list answer $_gdbtk_stop(msg)] 01542 set gdbtk_state($ans) no 01543 } 01544 01545 if {$_gdbtk_stop(timer) != ""} { 01546 # Cancel the timer callback 01547 after cancel $_gdbtk_stop(timer) 01548 set _gdbtk_stop(timer) "" 01549 catch {remove_hook gdb_idle_hook gdbtk_stop_idle_callback} 01550 } 01551 } 01552 01553 # ------------------------------------------------------------------ 01554 # PROC: gdbtk_detach 01555 # ------------------------------------------------------------------ 01556 # This proc is installed as a timer event when the stop button 01557 # is pressed. If target_wait doesn't return (we were unable to stop 01558 # the target), then this proc is called. 01559 # 01560 # Open a dialog box asking if the user would like to detach. If so, 01561 # try to detach. If not, do nothing and go away. 01562 proc gdbtk_detach {} { 01563 global _gdbtk_stop 01564 01565 set _gdbtk_stop(msg) "No response from target. Detach from target\n(and stop debugging it)?" 01566 if {[gdbtk_tcl_query $_gdbtk_stop(msg) no]} { 01567 catch {gdb_stop detach} 01568 } 01569 01570 set _gdbtk_stop(timer) "" 01571 set _gdbtk_stop(msg) "" 01572 remove_hook gdb_idle_hook gdbtk_stop_idle_callback 01573 } 01574 01575 # ------------------------------------------------------------------ 01576 # PROC: gdbtk_run 01577 # ------------------------------------------------------------------ 01578 proc gdbtk_run {} { 01579 if {$::gdb_running == 1} { 01580 set msg "A program is currently being debugged.\n" 01581 append msg "Do you want to restart?" 01582 if {![gdbtk_tcl_query $msg no]} { 01583 # NO 01584 return 01585 } 01586 } 01587 run_executable 01588 } 01589 01590 # ------------------------------------------------------------------ 01591 # PROC: gdbtk_attach_native: attach to a running target 01592 # ------------------------------------------------------------------ 01593 proc gdbtk_attach_native {} { 01594 ManagedWin::open_dlg AttachDlg ;#-transient 01595 01596 debug "ManagedWin got [AttachDlg::last_button] [AttachDlg::pid]" 01597 01598 if {[AttachDlg::last_button]} { 01599 set pid [AttachDlg::pid] 01600 set symbol_file [AttachDlg::symbol_file] 01601 if {$symbol_file != "" && ![_open_file $symbol_file]} { 01602 ManagedWin::open WarningDlg -transient \ 01603 -message "Could not load symbols from $symbol_file." 01604 return 01605 } 01606 01607 if {[catch {gdb_cmd "attach $pid"} result]} { 01608 ManagedWin::open WarningDlg -transient \ 01609 -message [list "Could not attach to $pid:\n$result"] 01610 return 01611 } 01612 } 01613 } 01614 01615 # ------------------------------------------------------------------ 01616 # PROC: set_baud - Tell GDB the baud rate. 01617 # ------------------------------------------------------------------ 01618 proc set_baud {} { 01619 global gdb_target_name 01620 #set target [ide_property get target-internal-name] 01621 set baud [pref getd gdb/load/${gdb_target_name}-baud] 01622 if {$baud == ""} { 01623 set baud [pref get gdb/load/baud] 01624 } 01625 # debug "setting baud to $baud" 01626 catch {gdb_cmd "set remotebaud $baud"} 01627 } 01628 01629 # ------------------------------------------------------------------ 01630 # PROC: do_state_hook - 01631 # ------------------------------------------------------------------ 01632 proc do_state_hook {varname ind op} { 01633 run_hooks state_hook $varname 01634 } 01635 01636 # ------------------------------------------------------------------ 01637 # PROC: gdbtk_disconnect - 01638 # ------------------------------------------------------------------ 01639 proc gdbtk_disconnect {{async 0}} { 01640 global gdb_loaded gdb_target_changed 01641 catch {gdb_cmd "detach"} 01642 # force a new target command to do something 01643 set gdb_loaded 0 01644 set gdb_target_changed 1 01645 set gdb_running 0 01646 gdbtk_idle 01647 gdbtk_update 01648 } 01649 01650 # ------------------------------------------------------------------ 01651 # PROC: tstart - 01652 # ------------------------------------------------------------------ 01653 proc tstart {} { 01654 if {[catch {gdb_cmd "tstart"} errTxt]} { 01655 tk_messageBox -title "Error" -message $errTxt -icon error \ 01656 -type ok 01657 gdbtk_idle 01658 return 0 01659 } 01660 return 1 01661 } 01662 01663 # ------------------------------------------------------------------ 01664 # PROC: tstop - 01665 # ------------------------------------------------------------------ 01666 proc tstop {} { 01667 01668 if {[catch {gdb_cmd "tstop"} errTxt]} { 01669 tk_messageBox -title "Error" -message $errTxt -icon error \ 01670 -type ok 01671 gdbtk_idle 01672 return 0 01673 } 01674 return 1 01675 } 01676 01677 # ------------------------------------------------------------------ 01678 # PROC: source_file - 01679 # ------------------------------------------------------------------ 01680 proc source_file {} { 01681 set file_name [tk_getOpenFile -title "Choose GDB Command file"] 01682 if {$file_name != ""} { 01683 gdb_cmd "source $file_name" 01684 } 01685 } 01686 01687 01688 # ----------------------------------------------------------------------------- 01689 # NAME: gdbtk_signal 01690 # 01691 # SYNOPSIS: gdbtk_signal {name longname} 01692 # 01693 # DESC: This procedure is called from GDB when a signal 01694 # is generated, for example, a SIGSEGV. 01695 # 01696 # ARGS: name - The name of the signal, as returned by 01697 # target_signal_to_name(). 01698 # longname - A description of the signal. 01699 # ----------------------------------------------------------------------------- 01700 proc gdbtk_signal {name {longname ""}} { 01701 dbug W "caught signal $name $longname" 01702 set longname 01703 set message "Program received signal $name, $longname" 01704 set srcs [ManagedWin::find SrcWin] 01705 foreach w $srcs { 01706 $w set_status $message 01707 } 01708 gdbtk_tcl_ignorable_warning signal $message 01709 update idletasks 01710 } 01711 01712 # Hook for clearing out executable state. Widgets should register a callback 01713 # for this hook if they have anything that may need cleaning if the user 01714 # requests to re-load an executable. 01715 define_hook gdb_clear_file_hook 01716 01717 # ----------------------------------------------------------------------------- 01718 # NAME: gdbtk_clear_file 01719 # 01720 # SYNOPSIS: gdbtk_clear_file 01721 # 01722 # DESC: This procedure is called when the user requests a new exec 01723 # file load. It runs the gdb_clear_file_hook, which tells 01724 # all widgets to clear state. It CANNOT call gdb_clear_file, 01725 # since this hook runs AFTER we load a new exec file (i.e., 01726 # gdb_clear_file would clear the file name). 01727 # 01728 # ARGS: none 01729 # ----------------------------------------------------------------------------- 01730 proc gdbtk_clear_file {} { 01731 global gdb_target_name 01732 01733 debug 01734 # Give widgets a chance to clean up 01735 catch {run_hooks gdb_clear_file_hook} 01736 01737 # Save the target name in case the user has already selected a 01738 # target. No need to force the user to select it again. 01739 set old_target $gdb_target_name 01740 01741 # Finally, reset our state 01742 initialize_gdbtk 01743 01744 set gdb_target_name $old_target 01745 } 01746 01747 # ------------------------------------------------------------------ 01748 # PROC: intialize_gdbtk - (re)initialize gdbtk's state 01749 # ------------------------------------------------------------------ 01750 proc initialize_gdbtk {} { 01751 global gdb_exe_changed gdb_target_changed gdb_running gdb_downloading \ 01752 gdb_loaded gdb_program_has_run file_done gdb_pretty_name gdb_exec \ 01753 gdb_target_cmd download_dialog gdb_pretty_name gdb_exe_name _gdbtk_stop \ 01754 gdb_target_name gdb_target_changed gdbtk_state gdb_kod_cmd gdb_shutting_down 01755 01756 # initialize state variables 01757 set gdb_exe_changed 0 01758 set gdb_target_changed 0 01759 set gdb_running 0 01760 set gdb_downloading 0 01761 set gdb_loaded 0 01762 set gdb_program_has_run 0 01763 set file_done 0 01764 set gdb_pretty_name {} 01765 set gdb_exec {} 01766 set gdb_target_cmd "" 01767 set gdb_running 0 01768 set gdb_shutting_down 0 01769 01770 set download_dialog "" 01771 01772 # gdb_pretty_name is the name of the GDB target as it should be 01773 # displayed to the user. 01774 set gdb_pretty_name "" 01775 01776 # gdb_exe_name is the name of the executable we are debugging. 01777 set gdb_exe_name "" 01778 01779 # Initialize readline 01780 if {![info exists gdbtk_state(readline)]} { 01781 # Only do this once... 01782 set gdbtk_state(readline) 0 01783 set gdbtk_state(console) "" 01784 set gdbtk_state(readlineShowUser) 1 01785 } 01786 01787 # flush cache for gdbtk_locate_main 01788 gdbtk_locate_main 1 01789 01790 # check for existence of a kod command and get it's name and 01791 # text for menu entry 01792 set gdb_kod_cmd "" 01793 set msg "" 01794 if {![catch {gdb_cmd "show os"} msg] && ($msg != "")} { 01795 set line1 [string range $msg 0 [expr [string first \n $msg] -1]] 01796 if {[regexp -- \"(.*)\" $line1 dummy cmd]} { 01797 set gdb_kod_cmd $cmd 01798 } 01799 } 01800 # debug "kod_cmd=$gdb_kod_cmd" 01801 01802 # setup stop button 01803 set _gdbtk_stop(timer) "" 01804 set _gdbtk_stop(msg) "" 01805 01806 # gdb_target_name is the name of the GDB target; that is, the argument 01807 # to the GDB target command. 01808 set gdb_target_name "" 01809 01810 # By setting gdb_target_changed, we force a target dialog 01811 # to be displayed on the first "run" 01812 set gdb_target_changed 1 01813 } 01814 01815 # The architecture changed. Inform the UI. 01816 proc gdbtk_tcl_architecture_changed {} { 01817 set e [ArchChangedEvent \#auto] 01818 # First perform global actions as a result of the architecture change. 01819 gdb_reg_arch_changed $e 01820 # Now dispatch to all the other event handlers. 01821 GDBEventHandler::dispatch $e 01822 delete object $e 01823 } 01824 01825 proc gdbtk_console_read {} { 01826 if {$::gdbtk_state(console) == ""} { 01827 ManagedWin::open Console -force 01828 } else { 01829 raise [namespace tail $::gdbtk_state(console)] 01830 } 01831 set result [$::gdbtk_state(console) gets] 01832 debug "result=$result" 01833 return $result 01834 } 01835 01836 # This is based on TIP 171 to enable better default behavior 01837 # with the MouseWheel event. I don't know why this is not in 01838 # Tk yet (at least 8.5), but this allows all of our windows to 01839 # scroll without having to do anything. 01840 proc ::tk::MouseWheel {wFired X Y D {shifted 0}} { 01841 # Set event to check based on call 01842 set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>" 01843 # do not double-fire in case the class already has a binding 01844 if {[bind [winfo class $wFired] $evt] ne ""} { return } 01845 # obtain the window the mouse is over 01846 set w [winfo containing $X $Y] 01847 # if we are outside the app, try and scroll the focus widget 01848 if {![winfo exists $w]} { catch {set w [focus]} } 01849 if {[winfo exists $w]} { 01850 if {[bind $w $evt] ne ""} { 01851 # Awkward ... this widget has a MouseWheel binding, but to 01852 # trigger successfully in it, we must give it focus. 01853 catch {focus} old 01854 if {$w ne $old} { focus $w } 01855 event generate $w $evt -rootx $X -rooty $Y -delta $D 01856 if {$w ne $old} { focus $old } 01857 return 01858 } 01859 # aqua and x11/win32 have different delta handling 01860 if {[tk windowingsystem] ne "aqua"} { 01861 set delta [expr {- ($D / 30)}] 01862 } else { 01863 set delta [expr {- ($D)}] 01864 } 01865 # scrollbars have different call conventions 01866 if {[string match "*Scrollbar" [winfo class $w]]} { 01867 catch {tk::ScrollByUnits $w \ 01868 [string index [$w cget -orient] 0] $delta} 01869 } else { 01870 # Walking up to find the proper widget handles cases like 01871 # embedded widgets in a canvas 01872 01873 # 20091008-keiths: This cannot possibly work the way it 01874 # was written in the TIP, so I've rewritten it to work the 01875 # way the comments say it should. 01876 set cmd [list "%W" [expr {$shifted ? "xview" : "yview"}] \ 01877 scroll $delta units] 01878 while {[catch [regsub "%W" $cmd $w]] && [winfo toplevel $w] ne $w} { 01879 set w [winfo parent $w] 01880 } 01881 } 01882 } 01883 } 01884 01885 bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0] 01886 bind all <Shift-MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 1] 01887 if {[tk windowingsystem] eq "x11"} { 01888 # Support for mousewheels on Linux/Unix commonly comes through 01889 # mapping the wheel to the extended buttons. 01890 bind all <4> [list ::tk::MouseWheel %W %X %Y 120] 01891 bind all <5> [list ::tk::MouseWheel %W %X %Y -120] 01892 } 01893 01894 set mw_classes [list Text Listbox Table TreeCtrl] 01895 foreach class $mw_classes { bind $class <MouseWheel> {} } 01896 if {[tk windowingsystem] eq "x11"} { 01897 foreach class $mw_classes { 01898 bind $class <4> {} 01899 bind $class <5> {} 01900 } 01901 } 01902