1 # Breakpoint window for Insight.
2 # Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2008 Red Hat, Inc.
4 # This program is free software; you can redistribute it and/or modify it
5 # under the terms of the GNU General Public License (GPL) as published by
6 # the Free Software Foundation; either version 2 of the License, or (at
7 # your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
15 # ------------------------------------------------------------------
16 # CONSTRUCTOR: create the main breakpoint window
17 # ------------------------------------------------------------------
18 itcl::body BpWin::constructor {args} {
19 window_name "Breakpoints" "BPs"
21 if {[pref getd gdb/bp/menu] != ""} {
24 set show_threads [pref get gdb/bp/show_threads]
25 debug "Ready to build"
27 eval itk_initialize $args
29 # The scrolledframe uses a canvas, which doesn't properly
30 # calculate an initial size, so we must set a default
31 # window size here. ManagedWin could override this still
32 # if there is a user preference for the geometry.
33 wm geometry $_top 350x165
37 # ------------------------------------------------------------------
38 # DESTRUCTOR: destroy the breakpoint window
39 # ------------------------------------------------------------------
40 itcl::body BpWin::destructor {} {}
43 # ------------------------------------------------------------------
44 # METHOD: build_win - build the main breakpoint window
45 # ------------------------------------------------------------------
46 itcl::body BpWin::build_win {} {
47 global _bp_en _bp_disp
53 # FIXME: The iwidgets scrolled frame is pretty useless.
54 # When we get BLT, use its hiertable to do this.
55 itk_component add sframe {
56 iwidgets::scrolledframe $itk_interior.sf \
57 -hscrollmode $hsmode -vscrollmode $vsmode
60 set twin [$itk_component(sframe) childsite]
64 label $twin.num0 -text "Num" -relief raised -bd 2 -anchor center \
67 label $twin.thread0 -text "Thread" -relief raised -bd 2 -anchor center \
69 label $twin.addr0 -text "Address" -relief raised -bd 2 -anchor center \
71 label $twin.file0 -text "File" -relief raised -bd 2 -anchor center \
73 label $twin.line0 -text "Line" -relief raised -bd 2 -anchor center \
75 label $twin.func0 -text "Function" -relief raised -bd 2 -anchor center \
79 label $twin.pass0 -text "PassCount" -relief raised -borderwidth 2 \
80 -anchor center -font global/fixed
81 grid x $twin.num0 $twin.addr0 $twin.file0 $twin.line0 $twin.func0 $twin.pass0 \
85 grid x $twin.thread0 $twin.addr0 $twin.file0 $twin.line0 $twin.func0 -sticky new
86 # Let the File and Function columns expand; no others.
87 grid columnconfigure $twin 3 -weight 1
88 grid columnconfigure $twin 5 -weight 1
90 grid x $twin.addr0 $twin.file0 $twin.line0 $twin.func0 -sticky new
91 # Let the File and Function columns expand; no others.
92 grid columnconfigure $twin 2 -weight 1
93 grid columnconfigure $twin 4 -weight 1
98 # The last row must always suck up all the leftover vertical
101 grid rowconfigure $twin $next_row -weight 1
104 menu $itk_interior.m -tearoff 0
105 [winfo toplevel $itk_interior] configure -menu $itk_interior.m
106 if { $tracepoints == 0 } {
107 $itk_interior.m add cascade -menu $itk_interior.m.bp -label "Breakpoint" -underline 0
109 $itk_interior.m add cascade -menu $itk_interior.m.bp -label "Tracepoint" -underline 0
111 set m [menu $itk_interior.m.bp]
112 if { $tracepoints == 0 } {
113 $m add radio -label "Normal" -variable _bp_disp($selected) \
114 -value donttouch -underline 0 -state disabled
115 $m add radio -label "Temporary" -variable _bp_disp($selected) \
116 -value delete -underline 0 -state disabled
118 $m add command -label "Actions" -underline 0 -state disabled
122 $m add radio -label "Enabled" -variable _bp_en($selected) -value 1 \
123 -underline 0 -state disabled
124 $m add radio -label "Disabled" -variable _bp_en($selected) -value 0 \
125 -underline 0 -state disabled
127 $m add command -label "Remove" -underline 0 -state disabled
128 $itk_interior.m add cascade -menu $itk_interior.m.all -label "Global" \
130 set m [menu $itk_interior.m.all]
131 $m add check -label " Show Threads" \
132 -variable [pref varname gdb/bp/show_threads] \
133 -underline 1 -command "$this toggle_threads"
135 $m add command -label "Disable All" -underline 0 \
136 -command "$this bp_all disable"
137 $m add command -label "Enable All" -underline 0 \
138 -command "$this bp_all enable"
140 $m add command -label "Remove All" -underline 0 \
141 -command "$this bp_all delete"
143 $m add command -label "Store Breakpoints..." -underline 0 \
144 -command [code $this bp_store]
145 $m add command -label "Restore Breakpoints..." -underline 3 \
146 -command [code $this bp_restore]
149 set Menu [menu $itk_interior.pop -tearoff 0]
151 if { $tracepoints == 0 } {
152 $Menu add radio -label "Normal" -variable _bp_disp($selected) \
153 -value donttouch -underline 0
154 $Menu add radio -label "Temporary" -variable _bp_disp($selected) \
155 -value delete -underline 0
157 $Menu add command -label "Actions" -underline 0
160 $Menu add radio -label "Enabled" -variable _bp_en($selected) -value 1 -underline 0
161 $Menu add radio -label "Disabled" -variable _bp_en($selected) -value 0 -underline 0
163 $Menu add command -label "Remove" -underline 0
164 $Menu add cascade -menu $Menu.all -label "Global" -underline 0
165 set m [menu $Menu.all]
166 $m add check -label " Show Threads" -variable [pref varname gdb/bp/show_threads] \
167 -underline 1 -command "$this toggle_threads"
169 $m add command -label "Disable All" -underline 0 -command "$this bp_all disable"
170 $m add command -label "Enable All" -underline 0 -command "$this bp_all enable"
172 $m add command -label "Remove All" -underline 0 -command "$this bp_all delete"
174 if { $tracepoints == 0 } {
175 # insert all breakpoints
176 foreach i [gdb_get_breakpoint_list] {
177 set e [BreakpointEvent \#auto -action create -number $i]
182 # insert all tracepoints
183 foreach i [gdb_get_tracepoint_list] {
184 set e [TracepointEvent \#auto -action create -number $i]
190 pack $itk_component(sframe) -side left -expand true -fill both
193 # ------------------------------------------------------------------
194 # METHOD: bp_add - add a breakpoint entry
195 # ------------------------------------------------------------------
196 itcl::body BpWin::bp_add {bp_event {tracepoint 0}} {
197 global _bp_en _bp_disp gdbtk_platform _files
199 set number [$bp_event get number]
200 set thread [$bp_event get thread]
201 set disposition [$bp_event get disposition]
202 set file [$bp_event get file]
205 set diposition tracepoint
206 set bptype tracepoint
208 set bptype breakpoint
211 debug "bp_add bpnum=$number thread=$thread show=$show_threads"
213 set _bp_en($i) [$bp_event get enabled]
214 set _bp_disp($i) $disposition
216 switch $disposition {
217 donttouch { set color [pref get gdb/src/bp_fg] }
219 set color [pref get gdb/src/temp_bp_fg]
223 set color [pref get gdb/src/trace_fg]
225 default { set color yellow }
228 if {$thread != "-1"} {set color [pref get gdb/src/thread_fg]}
230 if {$gdbtk_platform(platform) == "windows"} {
231 checkbutton $twin.en$i -relief flat -variable _bp_en($i) \
232 -activebackground $bg1 -command "$this bp_able $i" -fg $color
234 checkbutton $twin.en$i -relief flat -variable _bp_en($i) \
235 -command "$this bp_able $i" -activebackground $bg1 \
236 -selectcolor $color -highlightbackground $bg1
240 label $twin.num$i -text "$number " -relief flat -anchor w -font global/fixed
242 label $twin.addr$i -text "[gdb_CA_to_TAS [$bp_event get address]] " -relief flat -anchor w -font global/fixed -bg $bg1
243 if {[info exists _files(short,$file)]} {
244 set file $_files(short,$file)
246 # FIXME. Really need to do better than this.
247 set file [::file tail $file]
250 if {$thread == "-1"} {set thread "ALL"}
251 label $twin.thread$i -text "$thread " -relief flat -anchor w -font global/fixed
253 label $twin.file$i -text "$file " -relief flat -anchor w -font global/fixed
254 label $twin.line$i -text "[$bp_event get line] " -relief flat -anchor w -font global/fixed
255 label $twin.func$i -text "[$bp_event get function] " -relief flat -anchor w -font global/fixed
257 label $twin.pass$i -text "[$bp_event get pass_count] " -relief flat -anchor w -font global/fixed
261 set zz [list addr file func line]
262 if {$tracepoints} {lappend zz num pass}
263 if {$show_threads} {lappend zz thread}
265 bind $twin.${thing}${i} <1> "$this bp_select $i"
266 bind $twin.${thing}${i} <Double-1> "$this goto_bp $i"
267 bind $twin.${thing}${i} <3> [code $this _select_and_popup $i %X %Y]
272 grid $twin.en$i $twin.num$i $twin.addr$i $twin.file$i $twin.line$i \
273 $twin.func$i $twin.pass$i -sticky new -ipadx 4 -ipady 2
276 grid $twin.en$i $twin.thread$i $twin.addr$i $twin.file$i $twin.line$i \
277 $twin.func$i -sticky new -ipadx 4 -ipady 2
279 grid $twin.en$i $twin.addr$i $twin.file$i $twin.line$i \
280 $twin.func$i -sticky new -ipadx 4 -ipady 2
284 # This used to be the last row. Fix it vertically again.
285 grid rowconfigure $twin $i -weight 0
287 set index_to_bpnum($i) $number
288 set Index_to_bptype($i) $bptype
291 grid rowconfigure $twin $i -weight 1
294 # ------------------------------------------------------------------
295 # METHOD: bp_store - stores away the breakpoints in a file of gdb
297 # ------------------------------------------------------------------
298 itcl::body BpWin::bp_store {} {
299 set out_file [tk_getSaveFile]
300 if {$out_file == ""} {
303 if {[catch {::open $out_file w} outH]} {
304 tk_messageBox -message "Could not open $out_file: $outH"
307 foreach breakpoint [gdb_get_breakpoint_list] {
309 foreach {file function line_no address type \
310 enable_p disp ignore cmds cond thread hit_count user_spec} \
311 [gdb_get_breakpoint_info $breakpoint] {
315 if {$user_spec != ""} {
316 set bp_specifier $user_spec
317 } elseif {$file != ""} {
318 set filename [file tail $file]
319 set bp_specifier $filename:$line_no
321 set bp_specifier *$address
324 # FIXME: doesn't handle watchpoints.
325 if {[string compare $disp "delete"] == 0} {
326 puts $outH "tbreak $bp_specifier"
328 puts $outH "break $bp_specifier"
332 puts $outH "disable \$bpnum"
335 puts $outH "ignore \$bpnum $ignore"
341 # ------------------------------------------------------------------
342 # METHOD: bp_restore - restore the breakpoints from a file of gdb
344 # ------------------------------------------------------------------
345 itcl::body BpWin::bp_restore {} {
346 set inH [tk_getOpenFile]
351 if {[catch {gdb_cmd "source $inH"} err]} {
352 tk_messageBox -message "Error sourcing in BP file $inH: \"$err\""
356 # ------------------------------------------------------------------
357 # METHOD: bp_select - select a row in the grid
358 # ------------------------------------------------------------------
359 itcl::body BpWin::bp_select { r } {
360 global _bp_en _bp_disp
362 set zz [list addr file func line]
363 if {$tracepoints} {lappend zz num pass}
364 if {$show_threads} {lappend zz thread}
370 $twin.${thing}${i} configure -fg $::Colors(fg) -bg $bg1
374 # if we click on the same line, unselect it and return
375 if {$selected == $r} {
378 if {$tracepoints == 0} {
379 $itk_interior.m.bp entryconfigure "Normal" -state disabled
380 $itk_interior.m.bp entryconfigure "Temporary" -state disabled
382 $itk_interior.m.bp entryconfigure "Actions" -state disabled
384 $itk_interior.m.bp entryconfigure "Enabled" -state disabled
385 $itk_interior.m.bp entryconfigure "Disabled" -state disabled
386 $itk_interior.m.bp entryconfigure "Remove" -state disabled
392 $twin.${thing}${r} configure -fg $::Colors(sfg) -bg $::Colors(sbg)
395 if {$tracepoints == 0} {
396 $itk_interior.m.bp entryconfigure "Normal" -variable _bp_disp($r) \
397 -command "$this bp_type $r" -state normal
398 $itk_interior.m.bp entryconfigure "Temporary" -variable _bp_disp($r) \
399 -command "$this bp_type $r" -state normal
400 $Menu entryconfigure "Normal" -variable _bp_disp($r) \
401 -command "$this bp_type $r" -state normal
402 $Menu entryconfigure "Temporary" -variable _bp_disp($r) \
403 -command "$this bp_type $r" -state normal
405 $itk_interior.m.bp entryconfigure "Actions" -command "$this get_actions $r" -state normal
406 $Menu entryconfigure "Actions" -command "$this get_actions $r" -state normal
408 $itk_interior.m.bp entryconfigure "Enabled" -variable _bp_en($r) \
409 -command "$this bp_able $r" -state normal
410 $itk_interior.m.bp entryconfigure "Disabled" -variable _bp_en($r) \
411 -command "$this bp_able $r" -state normal
412 $itk_interior.m.bp entryconfigure "Remove" -command "$this bp_remove $r" -state normal
413 $Menu entryconfigure "Enabled" -variable _bp_en($r) \
414 -command "$this bp_able $r" -state normal
415 $Menu entryconfigure "Disabled" -variable _bp_en($r) \
416 -command "$this bp_able $r" -state normal
417 $Menu entryconfigure "Remove" -command "$this bp_remove $r" -state normal
422 # ------------------------------------------------------------------
423 # NAME: private method BpWin::_select_and_popup
424 # DESCRIPTION: Select the given breakpoint and popup the options
425 # menu at the given location.
429 # ------------------------------------------------------------------
430 itcl::body BpWin::_select_and_popup {bp X Y} {
431 if {$selected != $bp} {
437 # ------------------------------------------------------------------
438 # METHOD: bp_modify - modify a breakpoint entry
439 # ------------------------------------------------------------------
440 itcl::body BpWin::bp_modify {bp_event {tracepoint 0}} {
441 global _bp_en _bp_disp gdbtk_platform _files
443 set number [$bp_event get number]
444 set thread [$bp_event get thread]
445 set disposition [$bp_event get disposition]
446 set file [$bp_event get file]
449 set disposition tracepoint
450 set bptype tracepoint
452 set bptype breakpoint
456 for {set i 1} {$i < $next_row} {incr i} {
457 if { $number == $index_to_bpnum($i)
458 && "$Index_to_bptype($i)" == "$bptype"} {
465 debug "ERROR: breakpoint number $number not found!"
469 if {$_bp_en($i) != [$bp_event get enabled]} {
470 set _bp_en($i) [$bp_event get enabled]
473 if {$_bp_disp($i) != $disposition} {
474 set _bp_disp($i) $disposition
477 switch $disposition {
478 donttouch { set color [pref get gdb/src/bp_fg] }
480 set color [pref get gdb/src/temp_bp_fg]
482 tracepoint { set color [pref get gdb/src/trace_fg] }
483 default { set color yellow}
486 if {$thread != "-1"} {set color [pref get gdb/src/thread_fg]}
488 if {$gdbtk_platform(platform) == "windows"} then {
489 $twin.en$i configure -fg $color
491 $twin.en$i configure -selectcolor $color
494 $twin.num$i configure -text "$number "
496 $twin.addr$i configure -text "[gdb_CA_to_TAS [$bp_event get address]] "
497 if {[info exists _files(short,$file)]} {
498 set file $_files(short,$file)
500 # FIXME. Really need to do better than this.
501 set file [::file tail $file]
504 if {$thread == "-1"} {set thread "ALL"}
505 $twin.thread$i configure -text "$thread "
507 $twin.file$i configure -text "$file "
508 $twin.line$i configure -text "[$bp_event get line] "
509 $twin.func$i configure -text "[$bp_event get function] "
511 $twin.pass$i configure -text "[$bp_event get pass_count] "
515 # ------------------------------------------------------------------
516 # METHOD: bp_able - enable/disable a breakpoint
517 # ------------------------------------------------------------------
518 itcl::body BpWin::bp_able { i } {
523 switch $Index_to_bptype($i) {
524 breakpoint {set type {}}
525 tracepoint {set type "tracepoint"}
528 if {$_bp_en($i) == "1"} {
529 set command "enable $type $temp($i) "
531 set command "disable $type "
534 append command "$index_to_bpnum($i)"
538 # ------------------------------------------------------------------
539 # METHOD: bp_remove - remove a breakpoint
540 # ------------------------------------------------------------------
541 itcl::body BpWin::bp_remove { i } {
545 switch $Index_to_bptype($i) {
546 breakpoint { set type {} }
547 tracepoint { set type "tracepoint" }
550 gdb_cmd "delete $type $index_to_bpnum($i)"
553 # ------------------------------------------------------------------
554 # METHOD: bp_type - change the breakpoint type (disposition)
555 # ------------------------------------------------------------------
556 itcl::body BpWin::bp_type { i } {
558 if {$Index_to_bptype($i) != "breakpoint"} {
562 set bpnum $index_to_bpnum($i)
563 #debug "bp_type $i $bpnum"
564 set bpinfo [gdb_get_breakpoint_info $bpnum]
565 lassign $bpinfo file func line pc type enabled disposition \
566 ignore_count commands cond thread hit_count user_spec
568 switch $disposition {
570 gdb_cmd "delete $bpnum"
574 gdb_cmd "delete $bpnum"
575 gdb_cmd "tbreak *$pc"
577 default { debug "Unknown breakpoint disposition: $disposition" }
581 # ------------------------------------------------------------------
582 # METHOD: bp_delete - delete a breakpoint
583 # ------------------------------------------------------------------
584 itcl::body BpWin::bp_delete {bp_event} {
585 set number [$bp_event get number]
586 for {set i 1} {$i < $next_row} {incr i} {
587 if { $number == $index_to_bpnum($i) } {
589 grid forget $twin.en$i $twin.num$i $twin.addr$i $twin.file$i \
590 $twin.line$i $twin.func$i $twin.pass$i
591 destroy $twin.en$i $twin.num$i $twin.addr$i $twin.file$i \
592 $twin.line$i $twin.func$i $twin.pass$i
595 grid forget $twin.thread$i
596 destroy $twin.thread$i
598 grid forget $twin.en$i $twin.addr$i $twin.file$i $twin.line$i $twin.func$i
599 destroy $twin.en$i $twin.addr$i $twin.file$i $twin.line$i $twin.func$i
601 if {$selected == $i} {
609 # ------------------------------------------------------------------
610 # PUBLIC METHOD: breakpoint - Update widget when a breakpoint
611 # event is received from the backend.
612 # ------------------------------------------------------------------
613 itcl::body BpWin::breakpoint {bp_event} {
615 set action [$bp_event get action]
616 #debug "bp update $action [$bp_event get number] [$bp_event get type]"
619 modify { bp_modify $bp_event 0 }
620 create { bp_add $bp_event 0 }
621 delete { bp_delete $bp_event }
622 default { dbug E "Unknown breakpoint action: $action" }
626 # ------------------------------------------------------------------
627 # METHOD: tracepoint - Update widget when a tracepoint event
628 # is received from the backend.
629 # ------------------------------------------------------------------
630 itcl::body BpWin::tracepoint {tp_event} {
632 set action [$tp_event get action]
633 #debug "tp update $action [$tp_event get number]"
636 modify { bp_modify $tp_event 1 }
637 create { bp_add $tp_event 1 }
638 delete { bp_delete $tp_event }
639 default { dbug E "Unknown tracepoint action: $action" }
643 # ------------------------------------------------------------------
644 # METHOD: bp_all - perform a command on all breakpoints
645 # ------------------------------------------------------------------
646 itcl::body BpWin::bp_all { command } {
650 foreach bpnum [gdb_get_breakpoint_list] {
651 if { $command == "enable"} {
652 for {set i 1} {$i < $next_row} {incr i} {
653 if { $bpnum == $index_to_bpnum($i)
654 && "$Index_to_bptype($i)" == "breakpoint"} {
655 gdb_cmd "enable $temp($i) $bpnum"
660 gdb_cmd "$command $bpnum"
665 foreach bpnum [gdb_get_tracepoint_list] {
666 if { $command == "enable"} {
667 for {set i 1} {$i < $next_row} {incr i} {
668 if { $bpnum == $index_to_bpnum($i)
669 && "$Index_to_bptype($i)" == "tracepoint"} {
670 gdb_cmd "enable tracepoint $bpnum"
675 gdb_cmd "$command tracepoint $bpnum"
681 # ------------------------------------------------------------------
682 # METHOD: get_actions - pops up the add trace dialog on a selected
684 # ------------------------------------------------------------------
685 itcl::body BpWin::get_actions {bpnum} {
686 set bpnum $index_to_bpnum($bpnum)
687 set bpinfo [gdb_get_tracepoint_info $bpnum]
688 lassign $bpinfo file func line pc enabled pass_count \
689 step_count thread hit_count actions
691 set filename [::file tail $file]
692 ManagedWin::open TraceDlg -File $filename -Lines $line
695 # ------------------------------------------------------------------
696 # METHOD: toggle_threads - callback when show_threads is toggled
697 # ------------------------------------------------------------------
698 itcl::body BpWin::toggle_threads {} {
699 set show_threads [pref get gdb/bp/show_threads]
703 # ------------------------------------------------------------------
704 # METHOD: reconfig - used when preferences change
705 # ------------------------------------------------------------------
706 itcl::body BpWin::reconfig {} {
707 if {[winfo exists $itk_interior.f]} { destroy $itk_interior.f }
708 if {[winfo exists $itk_interior.m]} { destroy $itk_interior.m }
709 if {[winfo exists $itk_interior.sbox]} { destroy $itk_interior.sbox }
710 if {[winfo exists $itk_interior.sf]} { destroy $itk_interior.sf }
711 if {[winfo exists $itk_interior.pop]} { destroy $itk_interior.pop }
715 # ------------------------------------------------------------------
716 # METHOD: goto_bp - show bp in source window
717 # ------------------------------------------------------------------
718 itcl::body BpWin::goto_bp {r} {
719 set bpnum $index_to_bpnum($r)
721 set bpinfo [gdb_get_tracepoint_info $bpnum]
723 set bpinfo [gdb_get_breakpoint_info $bpnum]
725 set pc [lindex $bpinfo 3]
727 SrcWin::choose_and_display BROWSE_TAG [gdb_loc *$pc]