For most classic Amiga developers Michael Sinz’ Enforcer is a valuable tool for debugging. Especially the contained tools SegTracker and FindHit are very helpful when analyzing bugs in your compiled code: SegTracker patches AmigaDOS’ functions for loading and unloading binary files and then tracks where the (code/data/bss) segments of each binary are located in memory. If a crash occurs then you can locate which binary caused it. To get more detailed information then FindHit comes into play: If the segment associated with a crash location is identified then FindHit loads the debugging info stored in an executable and then can match these infos to your location and gives you the source code file and line that was used to generate the faulty code…
I do most of my Amiga development now in a cross-dev environment on my Mac and then the FS-UAE emulator is the runtime environment to test and debug code. While it is possible to use the same Enforcer setup inside FS-UAE I really like the built-in debugger of the emulator: It allows to freeze the whole Amiga and inspect the full state. Furthermore, memory watchpoints and breakpoints are available, too. The only thing that was missing: a SegTracker feature that tells me where my application/driver code is loaded and a FindHit feature to get detailed infos on the associated source.
Thanks to open source of both FS-UAE and Enforcer I was able to add both features without too many effort: In the following I present you an extended FS-UAE that adds SegTracker and FindHit right inside the built-in debugger!
1. Build the extended FS-UAE
Currently, the SegTracker extension is only available on my own FS-UAE branch chris-devel on my GitHub Repository. Just clone the source from there and build a fresh FS-UAE. See the build docs of FS-UAE for more details. I tested the extension both on Mac OS X and Linux. I haven’t tried Windows and I suppose the code might need some adjustments before it runs there… Patches are always welcome here 🙂
2. Run FS-UAE
You’ll need the built-in debugger to use the new features. Therefore, you have to ensure that the debugger is enabled in your .fs-uae configuration file. My Host.fs-uae optimized for development looks like this:
[config] fullscreen = 0 # I want an emulator window floppy_drive_volume = 0 # No click sounds joystick_port_1 = nothing # Don't block cursor keys # give me a backslash key on my MacBook Pro: # use Fn+Return keyboard_key_kp_enter = action_key_backslash automatic_input_grab = 0 # keep the mouse free uae_cachesize = 8192 # use JIT console_debugger = 1 # <--- enable the debugger parallel_port = raw:/tmp/vpar # setup a virtual parallel port serial_port = /tmp/vser # setup a virtual serial port
Note the console_debugger entry!
Make sure to run FS-UAE from a console otherwise you won’t see the debugger 🙂 On Mac OS X you use Terminal.app and launch FS-UAE like this:
> fs-uae-2.3.0b1-macosx/FS-UAE.app/Contents/MacOS/fs-uae cfgs/os31cwb.fs-uae
The last argument gives the configuration file to use.
On Linux it works similarly: Use a terminal to launch the fs-uae binary.
If you press F11+D now in the FS-UAE window then the debugger is launched in the console:
D0 00000001 D1 0000F90A D2 00000000 D3 0000003F D4 00005000 D5 0000000B D6 000006EF D7 00000006 A0 07B12B91 A1 07B14239 A2 07B14235 A3 07B14924 A4 079D1428 A5 07B0F6E4 A6 07B13E62 A7 07B02A8E USP 07B02A8E ISP 07802270 SFC 00000001 DFC 00000001 CACR 80008000 TC 00008000 ITT0 00000000 ITT1 00000000 DTT0 00000000 DTT1 00000000 VBR 07825C3C MSP 00000000 MMUS 00000003 URP 07820A00 SRP 07820A00 T=00 S=0 M=0 X=0 N=0 Z=0 V=0 C=0 IMASK=0 STP=0 FP0: 0 FP1: 0 FP2: 0 FP3: 0 FP4: 0 FP5: 0 FP6: 0 FP7: 0 FPSR: 0000 FPCR: 00000000 FPIAR: 00f81622 N=0 Z=0 I=0 NAN=0 079D6BF0 6a0c BPL.B #$0000000c == $079D6BFE (T) Next PC: 079d6bf2 >
Enter x + Return to leave the debugger and this reanimates your Amiga emulation in the FS-UAE Window. While the debugger is active the Amiga is frozen therefore nothing happens there…
3. Enable SegTracker
The SegTracker extension is not enabled by default. You have to enable it if you want to use it.
Start FS-UAE with the WB/Kickstart of your choice (but note that SegTracker will not work on KS 1.x!) and enter the debugger. With the ? command you get a list of available commands and in the patched FS-UAE you will see lots of new Z* commands:
... Z print SegmentTracker status. Ze [<0-1>] enable/disable/toggle SegmentTracker Zl show seglists tracked by SegmentTracker. Za <addr> find segment that contains given address. Zs 'name' search seglist with given name. Zf 'hostfile' load debug info from given executable file. Zy 'symbol' find symbol address. Zc 'file' <line> find source code line address. ...
We use Ze to enable the SegTracker:
>Ze SegmentTracker is enabled
Now it is important to reboot your virtual Amiga because the SegTracker is only installed during start up:
> x # leave debugger F11+R # Reset Amiga # wait a bit for reboot F11+D # re-enter debugger
If everything went well then you can already see the seglists that were loaded during startup: Use the Zl command to see a complete list:
> Zl ... 'LIBS:render.library' @079f58d4 #00 [079f58d8,0000cb84,07a0245c] 'Scalos:Plugins/OOP/title_clock.plugin' @07a0ec3c #00 [07a0ec40,00000850,07a0f490] #01 [079df7d0,00000010,079df7e0] #02 [07a0f498,00000190,07a0f628] 'Scalos:Plugins/OOP/volumegauge.plugin' @07b0396c #00 [07b03970,00000fc8,07b04938] #01 [07b04940,000001fc,07b04b3c] #02 [07b04b48,00000094,07b04bdc] 'Mount' @07b082b4 #00 [07b082b8,000018ac,07b09b64] #01 [079415c0,00000198,07941758] found 151 seglists. > x
This is an OS 3.1 startup with Classic Workbench installed.
For each loaded binary you see all loaded segments and for each segment the start address, size, and end address.
4. Load your Code
Its time to debug your own code: I use the plipbbox.device SANA-II device driver of my plipbox project here as an example.
I launch my driver by first copying it into the DEVS:Networks directory and then the TCP/IP Stack is started with this driver. I use Roadshow here as it has a very nice command line interface for handling things (and developers _love_ cli :):
CLI> addnetinterface plipbox
Now lets have a look in the FS-UAE’s debugger if my binary is already tracked. You can use either the Zl command to see the whole list or use the Zs command to search seglists by name:
> Zl 'plip' Searching seglists matching 'plip' 'DEVS:Networks/plipbox.device' @07b41efc #00 [07b41f00,00001fd8,07b43ed8] #01 [07b185e0,00000124,07b18704] found 1 seglists.
Ah, here is my code! This information is already very helpful if you want to start disassembling or setting breakpoints. But the info is still a bit coarse and therefore I added support for debug infos:
5. Add Debug Info
Now lets add debugging info to this seglist. For this you’ll need the exact same binary you use in your Amiga emulation somewhere located on your host file system. As I use cross-builds its usually the other way round and no big issue: I create the binary on my host and transfer it (via shared folder) to the Amiga. Furthermore, you’ll have to compile your binary with debugging information included (on SAS/C compiler its the DEBUG=LINE switch).
Use the Zf command to load and attach debug infos from the binary file to the tracked seglist found in the current system:
> Zf 'plipbox.device' Loading debug info for seglist 'DEVS:Networks/plipbox.device' from hunk file 'plipbox.device' file 'plipbox.device': 2 segments segment #00: CODE [00001fd8] 14 symbols, 3 src files 000000f4 _DevInit 00000234 _DevOpen 00000428 _DevClose 000004a2 _DevExpunge 0000059c _DevTermIO 000005c8 _DevBeginIO 00000974 _DevAbortIO 0000178e _ServerTask 00001962 _addtracktype 000019d2 _remtracktype 00001a28 _dotracktype 00001a8a _gettrackrec 00001ada _freetracktypes 00001f30 _NewList base:src/device.c: #289 base:src/server.c: #404 base:src/track.c: #58 segment #01: DATA  0 symbols, 0 src files
The given name is first searched to find a seglist in the system with the given name. Then the name is used to load a hunk executable directly from the current directory in the host file system (i.e. my Mac here).
Currently, the location of the binary in the host file system is a limitation, but that may be removed in further releases without too much work…
The segments of the file are loaded and the debug information is extracted. If the segment layout (size and number) of the loaded seglist matches the one found on the emulated Amiga then the debug info is attached otherwise an error is given.
Use the Zl or Zs command again to see the attached debug info:
> Zs 'plip' Searching seglists matching 'plip' 'DEVS:Networks/plipbox.device' @07b41efc #00 [07b41f00,00001fd8,07b43ed8] 14 symbols, 3 src files 07b41ff4 _DevInit 07b42134 _DevOpen 07b42328 _DevClose 07b423a2 _DevExpunge 07b4249c _DevTermIO 07b424c8 _DevBeginIO 07b42874 _DevAbortIO 07b4368e _ServerTask 07b43862 _addtracktype 07b438d2 _remtracktype 07b43928 _dotracktype 07b4398a _gettrackrec 07b439da _freetracktypes 07b43e30 _NewList #01 [07b185e0,00000124,07b18704] 0 symbols, 0 src files found 1 seglists.
Ok, now everything is in place for debugging.
Note that the Zs command already maps the symbols to the loaded locations. Therefore, you can directly set breakpoints on the corresponding addresses.
6. Use Debug Infos
The Za command is the main tool during debugging: It allows you to map an arbitrary address to seglist and debug info if its available:
> Za 0 00000000: not found in any segments. > Za 7b41ff4 07b41ff4: 'DEVS:Networks/plipbox.device' #00 [07b41f00,00001fd8,07b43ed8] +000000f4 07b41ff4 +00000000 _DevInit 07b41ff4 +00000000 base:src/device.c:159 > Za 7b42000 07b42000: 'DEVS:Networks/plipbox.device' #00 [07b41f00,00001fd8,07b43ed8] +00000100 07b41ff4 +0000000c _DevInit 07b41ff4 +0000000c base:src/device.c:159
Note the offset in the second column of the debug info (+0/+c): Its the distant of the current address to the debug information.
You can also perform look ups the other way round: Give a symbol name or part of it and you will see the matching memory locations:
> Zy 'dev' Searching symbols matching 'dev' 'DEVS:Networks/plipbox.device' #00 07b41ff4: _DevInit 07b42134: _DevOpen 07b42328: _DevClose 07b423a2: _DevExpunge 07b4249c: _DevTermIO 07b424c8: _DevBeginIO 07b42874: _DevAbortIO
Or you give a source file name and a line number and you’ll get the address of the generated code:
> Zc 'dev' 159 Searching code line matching dev:159 'DEVS:Networks/plipbox.device' #00 07b41ff4: base:src/device.c:159
With these new tools the built-in debugger in FS-UAE is now a very poweful tool for application and driver debugging on the Amiga. While the current feature set is still basic it is quite useful. I’ll keep adding new features if I need them during debugging 🙂 E.g. adding the debug info to the disassemble command might be a nice extension…
Have Fun and I hope you find these tools useful for your own projects, too!