1 |
578 |
markom |
INSIGHT PLUG-INS HOW-TO
|
2 |
|
|
=======================
|
3 |
|
|
|
4 |
|
|
This text describes the technical aspects of adding a plug-in window
|
5 |
|
|
to Insight, the graphical front-end to the GNU debugger GDB.
|
6 |
|
|
|
7 |
|
|
|
8 |
|
|
1) INTRODUCTION
|
9 |
|
|
|
10 |
|
|
The plug-in facility allows for the addition of custom windows to
|
11 |
|
|
Insight. These windows are not to become part of the Insight
|
12 |
|
|
distribution, but rather to be distributed separately. They can be
|
13 |
|
|
downloaded from the authors web site, may accompany some development
|
14 |
|
|
board or embedded OS or come with anything else that can benefit from
|
15 |
|
|
a custom window being added to the standard Insight. As the plug-ins
|
16 |
|
|
will be loaded into Insight/GDB for execution, the terms of the GPL
|
17 |
|
|
also apply to the plug-in code. Also, Red Hat provides this facility
|
18 |
|
|
as-is and accepts no responsibility from its use. Please refer to the
|
19 |
|
|
text of the GPL for more details.
|
20 |
|
|
|
21 |
|
|
The facilities described here provide support for custom
|
22 |
|
|
visualizations (custom windows for displaying information retrieved
|
23 |
|
|
from the target). By writing a plug-in, it is possible to visualize
|
24 |
|
|
target specific data that is not shown in the standard Insight
|
25 |
|
|
windows.
|
26 |
|
|
|
27 |
|
|
The plug-in facility cannot be used to control target execution. The
|
28 |
|
|
current implementation of Insight assumes that only the Source Window
|
29 |
|
|
issues commands related to target execution control. There is no
|
30 |
|
|
mechanism to prevent one to call the commands that control execution,
|
31 |
|
|
but its use may result in inconsistent GUI states. This restriction
|
32 |
|
|
may be lifted in future versions of Insight.
|
33 |
|
|
|
34 |
|
|
The facility works as follows: A "plugins" subdirectory is added under
|
35 |
|
|
the gdbtcl directory where Insight Tcl code is installed. The custom
|
36 |
|
|
plug-in code will be installed in a subdirectory of this "plugins"
|
37 |
|
|
directory. The plug-in window will be written as a [incr Tcl/Tk]
|
38 |
|
|
class which inherits from the provided PluginWindow class and
|
39 |
|
|
implements the methods necessary to display the desired custom
|
40 |
|
|
data. GDB will read plug-in files on start-up and add a menu item to
|
41 |
|
|
the PlugIn menu of the Insight Source Window. When the menu item is
|
42 |
|
|
chosen, GDB instantiates the custom plug-in class.
|
43 |
|
|
|
44 |
|
|
The PluginWindow base class constructor creates a toplevel window (an
|
45 |
|
|
Insight ManagedWin) which contains a "childsite". In this case, the
|
46 |
|
|
"childsite" is a frame in which the derived class (the custom plug-in)
|
47 |
|
|
can draw. The PluginWindow class also provides facilities to add a
|
48 |
|
|
menu and a toolbar. Among the methods provided by this class, the
|
49 |
|
|
"running" method is called every time the debugger starts the target
|
50 |
|
|
and the "stopped" method is called every time the target stops. In the
|
51 |
|
|
"stopped" method, information can be gathered from the target and
|
52 |
|
|
displayed. The "running" method indicates that GDB is busy running
|
53 |
|
|
the target. No activities should be initiated by any GUI component
|
54 |
|
|
while in this state (except for the STOP button in the Source Window).
|
55 |
|
|
|
56 |
|
|
The remainder of this document describes how to install a custom
|
57 |
|
|
plug-in and some details of the PluginWindow class. Writing Tcl
|
58 |
|
|
Extensions (technically is what plug-ins are) is beyond the scope of
|
59 |
|
|
this document, but a simple example is given and some documentation
|
60 |
|
|
references are provided.
|
61 |
|
|
|
62 |
|
|
Please see the file CONTRIBUTE in this directory for some
|
63 |
|
|
administrative details before you start developing your plug-in.
|
64 |
|
|
|
65 |
|
|
|
66 |
|
|
2) HOW TO ADD A PLUG-IN WINDOW TO INSIGHT
|
67 |
|
|
|
68 |
|
|
Once you have your plug-in class ready, here is how to make it show up
|
69 |
|
|
in the Insight Source Window "PlugIn" menu. You may perform these
|
70 |
|
|
steps manually, but if you are distributing your plug-in, it may be
|
71 |
|
|
convenient to provide with it an installation script that automate
|
72 |
|
|
this steps.
|
73 |
|
|
|
74 |
|
|
The examples in this section refer to the sample plug-in code provided
|
75 |
|
|
with the Insight sources, located in the
|
76 |
|
|
$(SOURCE)/gdb/gdbtk/library/plugins and
|
77 |
|
|
$(SOURCE)/gdb/gdbtk/library/plugins/rhabout directories.
|
78 |
|
|
|
79 |
|
|
Custom plug-ins are provided as "packages" (see [Welch 2000] and
|
80 |
|
|
[Smith 2000]). The following setup will cause your plug-in package to
|
81 |
|
|
be loaded.
|
82 |
|
|
|
83 |
|
|
i) First, locate the $(INSTALL)/share/gdbtcl directory. This is the
|
84 |
|
|
directory which contains the Tcl/Tk code used by Insight. Create a
|
85 |
|
|
"plugins" subdirectory if it does not exist yet (i.e., if your plug-in
|
86 |
|
|
is the first to be installed). Now you must have a directory:
|
87 |
|
|
$(INSTALL)/share/gdbtcl/plugins
|
88 |
|
|
in your installation tree.
|
89 |
|
|
|
90 |
|
|
ii) Create a subdirectory for your plug-in code (named in accordance to
|
91 |
|
|
the conventions set forth in the CONTRIBUTE file). Add all your code
|
92 |
|
|
to that directory. Make sure you have a tclIndex file or use
|
93 |
|
|
auto_mkindex to create it. For instance, in the sample case we would
|
94 |
|
|
have:
|
95 |
|
|
$(INSTALL)/share/gdbtcl/plugins/rhabout
|
96 |
|
|
and it would contain:
|
97 |
|
|
rhabout.itcl rhabout.so tclIndex
|
98 |
|
|
|
99 |
|
|
iii) In the "plugins" directory create a file that will actually load your
|
100 |
|
|
plug-in package (named accordingly to the CONTRIBUTE conventions). In
|
101 |
|
|
the provided sample, this file is "rhabout.tcl" and would contain the
|
102 |
|
|
following lines:
|
103 |
|
|
|
104 |
|
|
package provide RHABOUT 1.0
|
105 |
|
|
set dirname [file dirname [info script]]
|
106 |
|
|
lappend auto_path [file join $dirname rhabout]
|
107 |
|
|
load [file join $dirname rhabout rhabout.so] RHABOUT
|
108 |
|
|
|
109 |
|
|
The first line states what package the sample plug-in code is
|
110 |
|
|
providing. Note that the subdirectory "rhabout" which contains the
|
111 |
|
|
sample plug-in is added to the auto_path in the third line and there
|
112 |
|
|
is a tclIndex file in that directory (that is how plug-in classes and
|
113 |
|
|
methods are found).
|
114 |
|
|
|
115 |
|
|
The last line is only necessary if your plug-in contains Tcl command
|
116 |
|
|
procedures written in C. Loading Tcl libraries is described in [Welch
|
117 |
|
|
2000] and the [incr Tcl/Tk] bits can be found in [Smith 2000]. It is
|
118 |
|
|
recommended that the reader also refer to the "load" Tcl man page if
|
119 |
|
|
these dynamic libraries are to be loaded.
|
120 |
|
|
|
121 |
|
|
iv) In the "plugins" directory, add an entry to the pkgIndex.tcl file,
|
122 |
|
|
if it exists, with a "package ifneeded" command to source the file
|
123 |
|
|
created in step (iii). If the file does not exist, create it. For
|
124 |
|
|
the sample plug-in, this entry is:
|
125 |
|
|
|
126 |
|
|
package ifneeded RHABOUT 1.0 [list source [file join $dir rhabout.tcl]]
|
127 |
|
|
|
128 |
|
|
This roughly corresponds to what would be created by a pkg_mkIndex
|
129 |
|
|
command with the "-direct" option.
|
130 |
|
|
|
131 |
|
|
If you are writing a install script, make sure to append to this file,
|
132 |
|
|
not overwrite it. If there are other plug-ins already installed you
|
133 |
|
|
don't want to remove their "package ifneeded" commands (e.g., use ">>"
|
134 |
|
|
in a c-shell script). Be considerate.
|
135 |
|
|
|
136 |
|
|
v) Create the file "plugins.tcl" in the "plugins" directory if it does
|
137 |
|
|
not yet exist. Again, this is a file shared by all plug-ins so make
|
138 |
|
|
sure your install script does not overwrite, but append to it.
|
139 |
|
|
|
140 |
|
|
This is a Tcl code fragment that will be sourced by the Insight Source
|
141 |
|
|
Window constructor to add menu entries to the "PlugIn" menu that will
|
142 |
|
|
instantiate the plug-in classes. If there is any error in this few
|
143 |
|
|
lines of code Insight will not start and a Tcl stack trace will be
|
144 |
|
|
shown. So test it in your build directory before installing in a
|
145 |
|
|
system shared by others.
|
146 |
|
|
|
147 |
|
|
For the sample plug-in, this lines would be:
|
148 |
|
|
|
149 |
|
|
# Add your window to the PlugIn menu here
|
150 |
|
|
# Don't forget to add your packet as well
|
151 |
|
|
|
152 |
|
|
if {1} { #test here if your target is configured
|
153 |
|
|
#package require LIBGDB 1.0
|
154 |
|
|
package require RHABOUT 1.0
|
155 |
|
|
$Menu add command Other "About Red Hat" \
|
156 |
|
|
{ManagedWin::open RHAbout} \
|
157 |
|
|
-underline 0
|
158 |
|
|
set plugins_available 1
|
159 |
|
|
}
|
160 |
|
|
|
161 |
|
|
You can ignore the LIBGDB "package require" command for now. LIBGDB
|
162 |
|
|
is under construction and not yet available. But do not forget to
|
163 |
|
|
add a "package require" command for your plug-in package. Otherwise,
|
164 |
|
|
when someone choses your plug-in menu entry a stack trace will be
|
165 |
|
|
produced.
|
166 |
|
|
|
167 |
|
|
The Tcl command starting with "$Menu" is similar to the ones provided
|
168 |
|
|
by the "menubar" component of the PluginWindow class (described later
|
169 |
|
|
in this document), but all one needs to do is to copy the above
|
170 |
|
|
replacing the menu entry text "About Red Hat", the plug-in class name
|
171 |
|
|
"RHAbout" and the underline index with the appropriate values.
|
172 |
|
|
|
173 |
|
|
The "set plugins_available 1" command is important. If the variable
|
174 |
|
|
"plugins_available" is not set to 1 by any of the plug-in code
|
175 |
|
|
fragments, the Source Window will not have a "PlugIn" menu.
|
176 |
|
|
|
177 |
|
|
This brings us to the "if" statement in the first line. The sample
|
178 |
|
|
plug-in is generic, it works with any target. However, a custom
|
179 |
|
|
plug-in may be written for a specific target and be of no generic
|
180 |
|
|
use. Furthermore, a target specific plug-in may not even work with
|
181 |
|
|
other host and target configurations different from the one it was
|
182 |
|
|
designed for.
|
183 |
|
|
|
184 |
|
|
The Tcl code used by Insight is shared by all configurations (thus the
|
185 |
|
|
subdirectory name "shared") and adding a plug-in in the wrong
|
186 |
|
|
configuration could render Insight unusable. To avoid this, a test
|
187 |
|
|
for the right configuration must be made so that the plug-in menu
|
188 |
|
|
entry is only added in the configurations that support it (the
|
189 |
|
|
"package require" must also be protected).
|
190 |
|
|
|
191 |
|
|
Insight has a global variable which contains configuration
|
192 |
|
|
information. The array "GDBStartup" has the elements:
|
193 |
|
|
host_name - host configuration triplet
|
194 |
|
|
target_name - target configuration triplet
|
195 |
|
|
|
196 |
|
|
Use these values, $GDBStartup(host_name) and $GDBStartup(target_name),
|
197 |
|
|
to verify that your plug-in code is supported. Don't forget to add
|
198 |
|
|
"global GDBStartup" before you refer to this array.
|
199 |
|
|
|
200 |
|
|
For instance, if the sample code could only be used with Linux hosts,
|
201 |
|
|
the sample code above would look like this:
|
202 |
|
|
|
203 |
|
|
# Add your window to the PlugIn menu here
|
204 |
|
|
# Don't forget to add your packet as well
|
205 |
|
|
|
206 |
|
|
global GDBStartup
|
207 |
|
|
if {[string first "linux" $GDBStartup(host_name)] != -1} {
|
208 |
|
|
#package require LIBGDB 1.0
|
209 |
|
|
package require RHABOUT 1.0
|
210 |
|
|
$Menu add command Other "About Red Hat" \
|
211 |
|
|
{ManagedWin::open RHAbout} \
|
212 |
|
|
-underline 0
|
213 |
|
|
set plugins_available 1
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
|
217 |
|
|
3) DEVELOPING AN INSIGHT PLUG-IN
|
218 |
|
|
|
219 |
|
|
Only itcl based windows will work. They must also be derived (i.e.,
|
220 |
|
|
inherit) from the PluginWindow class described in the next section.
|
221 |
|
|
You must also follow the name conventions described in the CONTRIBUTE
|
222 |
|
|
file to avoid class name clashes.
|
223 |
|
|
|
224 |
|
|
The PluginWindow base class has facilities for adding a menu and a
|
225 |
|
|
toolbar. It already provides the code to deactivate buttons and menu
|
226 |
|
|
entries when GDB is busy (running the target) and reactivate them when
|
227 |
|
|
the target stops. Your job usually consists of calling a method to
|
228 |
|
|
redraw your window with updated information when the target stops.
|
229 |
|
|
You can do this simply by adding a call to this method inside the
|
230 |
|
|
"stopped" method provided.
|
231 |
|
|
|
232 |
|
|
The Insight Tcl source file gdb/gdbtk/library/interface.tcl and the C
|
233 |
|
|
file gdb/gdbtk/generic/gdbtk-cmds.c contain a (quite volatile) set of
|
234 |
|
|
Tcl commands that can be used to retrieve information from and about
|
235 |
|
|
the target. Examples of the use of such commands exist all around the
|
236 |
|
|
Insight source code and details are usually given near the procedure
|
237 |
|
|
or function definitions. Please refrain from using commands that
|
238 |
|
|
control the target execution or change the GDB state in any way, they
|
239 |
|
|
are reserved for use by the Source Window only. Remember, plug-ins are
|
240 |
|
|
a visualization facility only.
|
241 |
|
|
|
242 |
|
|
A special remark is necessary about the gdb_cmd and gdb_immediate
|
243 |
|
|
commands. These are deprecated and will disappear (stop working) soon.
|
244 |
|
|
The GDB maintainers have asked the Insight maintainers to stop using
|
245 |
|
|
the hooks in GDB code that make them possible. Conversion is already
|
246 |
|
|
under way. You can use them for prototyping (for now), but be
|
247 |
|
|
prepared to write Tcl command procedures instead of parsing console text
|
248 |
|
|
output.
|
249 |
|
|
|
250 |
|
|
If you need to issue target-dependent commands to retrieve information
|
251 |
|
|
from your target (that cannot be retrieved with the standard register
|
252 |
|
|
and memory access operations), you can write Tcl command procedures
|
253 |
|
|
and add them to your target dependent file enclosed in
|
254 |
|
|
#ifdef GDBTK
|
255 |
|
|
#endif
|
256 |
|
|
The target dependent Tcl code will move to a subdirectory of gdbtk in
|
257 |
|
|
the future, but for now, just add it to your existent target-dependent
|
258 |
|
|
file.
|
259 |
|
|
|
260 |
|
|
If you must access gdb functions that are not yet available in
|
261 |
|
|
gdbtk-cmds.c (or in any of the spun-offs that will soon exist in the
|
262 |
|
|
gdb/gdbtk/generic directory), consider writing to the Insight
|
263 |
|
|
maintainers. They will be able to tell you what command should be
|
264 |
|
|
implemented and, if they have the time, add it to Insight. As they
|
265 |
|
|
may be busy, consider offering to write the code yourself and
|
266 |
|
|
submitting it for approval (see CONTRIBUTE). You can see how these
|
267 |
|
|
Tcl command procedures in C are written by looking at what it is done
|
268 |
|
|
in the gdbtk-cmds.c file and others in the gdb/gdbtk/generic
|
269 |
|
|
subdirectory. Again, you can use the gdb_cmd and gdb_immediate
|
270 |
|
|
commands to invoke a GDB command line interface command, but they will
|
271 |
|
|
not be available for long.
|
272 |
|
|
|
273 |
|
|
Please refer to the sample source code located in the files:
|
274 |
|
|
gdb/gdbtk/library/plugins/rhabout/rhabout.itcl
|
275 |
|
|
gdb/gdbtk/library/plugins/rhabout/rhabout.c
|
276 |
|
|
|
277 |
|
|
The comments in these files provide a basic framework for a Insight
|
278 |
|
|
plug-in.
|
279 |
|
|
|
280 |
|
|
|
281 |
|
|
4) THE "PluginWindow" BASE CLASS
|
282 |
|
|
|
283 |
|
|
The PluginWindow base class provides the following methods:
|
284 |
|
|
|
285 |
|
|
childsite - returns the path of the frame component that can be used
|
286 |
|
|
by the plug-in code to pack its custom display components.
|
287 |
|
|
|
288 |
|
|
stopped - called when the target stops. It should be overloaded and
|
289 |
|
|
call the plug-in procedure that updates the display. The child
|
290 |
|
|
version must call the base class method implementation if it wants
|
291 |
|
|
menu items and/or buttons to be automatically controlled.
|
292 |
|
|
|
293 |
|
|
running - called when GDB becomes busy by running the target. No
|
294 |
|
|
commands shall be issued by a plug-in while GDB is busy. The child
|
295 |
|
|
version must call the base class method implementation if it wants
|
296 |
|
|
menu items and/or buttons to be automatically controlled.
|
297 |
|
|
|
298 |
|
|
no_inferior - called when GDB disconnects from the target. The
|
299 |
|
|
plug-in may want to forget some context information in this case,
|
300 |
|
|
depending on the specifics of its implementation. The child
|
301 |
|
|
version must call the base class method implementation if it wants
|
302 |
|
|
menu items and/or buttons to be automatically controlled.
|
303 |
|
|
|
304 |
|
|
|
305 |
|
|
The PluginWindow base class contains two components which can be
|
306 |
|
|
optionally used:
|
307 |
|
|
|
308 |
|
|
menubar - allows a menu to be added to the plug-in window. This
|
309 |
|
|
facility is implemented by the GDBMenuBar class (gdbmenubar.itcl).
|
310 |
|
|
|
311 |
|
|
toolbar - allows a toolbar to be added to the plug-in window. This
|
312 |
|
|
facility is implemented by the GDBToolBar class (gdbtoolbar.itcl).
|
313 |
|
|
|
314 |
|
|
|
315 |
|
|
Both buttons and menu entries have "class" attributes. Button classes
|
316 |
|
|
and Menu entry classes are specified when they are created and are
|
317 |
|
|
used for the automatic control of button and menu entry states.
|
318 |
|
|
If the class is specified as "None", the menu entry or button will
|
319 |
|
|
remain always active. The classes "Control" and "Other" follow the
|
320 |
|
|
following convention:
|
321 |
|
|
|
322 |
|
|
Control Other State
|
323 |
|
|
off off gdb is busy
|
324 |
|
|
on on gdb has inferior, and is idle
|
325 |
|
|
off on gdb has no inferior, and is idle
|
326 |
|
|
|
327 |
|
|
|
328 |
|
|
The "menubutton" component offers the following supported commands:
|
329 |
|
|
|
330 |
|
|
add menubutton - add a menu button to the window menu bar.
|
331 |
|
|
add command - add an entry to the last menu created.
|
332 |
|
|
add separator - add a separator to the last menu created.
|
333 |
|
|
show - attach the created menu to the window.
|
334 |
|
|
|
335 |
|
|
If the show command is not issued, the plug-in window will have no
|
336 |
|
|
menu bar. There are other methods and commands defined in the
|
337 |
|
|
GDBMenuBar class. They are for Insight internal use only and should
|
338 |
|
|
not be used by plug-in windows.
|
339 |
|
|
|
340 |
|
|
A menu named "help" will automatically be aligned to the right.
|
341 |
|
|
|
342 |
|
|
The sample plug-in code creates a simple menu with the following commands:
|
343 |
|
|
|
344 |
|
|
$menubar add menubutton file "File" 0
|
345 |
|
|
$menubar add command None "Close" \
|
346 |
|
|
[code $this destroy_toplevel] \
|
347 |
|
|
-underline 1
|
348 |
|
|
$menubar add menubutton help "Help" 0
|
349 |
|
|
$menubar add command Other "Help Topics" \
|
350 |
|
|
{HtmlViewer::open_help index.html} \
|
351 |
|
|
-underline 0
|
352 |
|
|
$menubar add separator
|
353 |
|
|
$menubar add command Other "About GDB..." \
|
354 |
|
|
{ManagedWin::open About -transient} \
|
355 |
|
|
-underline 0
|
356 |
|
|
|
357 |
|
|
# The menu only shows up if you do this:
|
358 |
|
|
$menubar show
|
359 |
|
|
|
360 |
|
|
|
361 |
|
|
The "toolbar" component offers the following supported commands:
|
362 |
|
|
|
363 |
|
|
add button - add a button to the window tool bar.
|
364 |
|
|
add label - add an label widget to the tool bar.
|
365 |
|
|
add separator - add a separator to the tool bar.
|
366 |
|
|
itemconfigure - configure a tool bar element.
|
367 |
|
|
show - make the toolbar visible.
|
368 |
|
|
|
369 |
|
|
If the show command is not issued, the plug-in window will have no
|
370 |
|
|
tool bar. There are other methods and commands defined in the
|
371 |
|
|
GDBToolBar class. They are for Insight internal use only and should
|
372 |
|
|
not be used by plug-in windows.
|
373 |
|
|
|
374 |
|
|
Use the "itemconfigure" command to fill the label elements with the
|
375 |
|
|
current data as necessary.
|
376 |
|
|
|
377 |
|
|
The sample plug-in code creates a single button with the following commands:
|
378 |
|
|
|
379 |
|
|
$toolbar add button con Other {ManagedWin::open Console} \
|
380 |
|
|
"Console (Ctrl+N)" -image console_img
|
381 |
|
|
|
382 |
|
|
# The toolbar will only show up if you do this:
|
383 |
|
|
$toolbar show
|
384 |
|
|
|
385 |
|
|
|
386 |
|
|
The complete Tcl code of the sample plug-in can be found in the file
|
387 |
|
|
gdb/gdbtk/library/plugins/rhabout/rhabout.itcl
|
388 |
|
|
and the PluginWindow class definition and implementation is in the file
|
389 |
|
|
gdb/gdbtk/library/pluginwin.itcl
|
390 |
|
|
|
391 |
|
|
Please refer to the files
|
392 |
|
|
gdb/gdbtk/library/gdbmenubar.itcl
|
393 |
|
|
and
|
394 |
|
|
gdb/gdbtk/library/gdbtoolbar.itcl
|
395 |
|
|
for the current arguments accepted by the menubar and toolbar commands
|
396 |
|
|
respectively.
|
397 |
|
|
|
398 |
|
|
|
399 |
|
|
REFERENCES
|
400 |
|
|
|
401 |
|
|
[Smith 2000] Chad Smith, "[incr Tcl/Tk] from the Ground Up".
|
402 |
|
|
Chapters 9 and 10. Osborne/McGraw-Hill, 2000.
|
403 |
|
|
|
404 |
|
|
[Welch 2000] Brent B. Welch, "Practical Programming in Tcl and Tk",
|
405 |
|
|
3/e. Chapters 12, 14, 44, 45, 46 and 47. Prentice Hall PTR, 2000.
|