Copyright (c) Hyperion Entertainment and contributors.

Debug Kernel

From AmigaOS Documentation Wiki
Jump to navigation Jump to search


When you program AmigaOS, sooner or later you will need tools to help you debugging your applications (and not only yours) and find out why a program crashes or runs erratically. For that you have debuggers (GDB and db101), small tools to operate with debug outputs and level of debugging (like KDebug, DumpDebugBuffer, etc.), memory trackers (like MemGuard and MemGuardian) and bunch of other small utilities and tricks which help you to do debugging. One of those tricks, which is little known, is the fact that a debug version of the standard AmigaOS kernel is publicly released ready to use for third party developers (or advanced users willing to help debugging applications).

What is "debug kernel" exactly?

Debug kernel is the same kernel as the standard one, but with added code to help catching some of the most common programming errors. This additional code adds a slightly (yet non negligible) amount of bytes to the kernel size (around half a megabyte) and is slower. Thus it has been removed from the standard kernel for performance and optimization purposes and is generally not useful to the standard average user. Yet this debug kernel can prove itself to be very useful to programmers, especially it provides the following functionality:

  1. Clobbering of succ/pred pointers when a Node is removed from a list.
    One common mistake when dealing with lists is to access successor and/or previous pointers from a removed node. While at first sight it may seems harmless it may reveal itself as a dreadful bug to spot because once a node has been removed from a list nothing guarantees you that the list has not be reworked/copied/reallocated or anything else. This will give you a bug that is very hard to reproduce or even non reproducible at all. As such one should NEVER access Succ/Prev pointers from a removed Node, instead if he needs to, he should access them prior the call to Remove(). To help spotting such errors the debug kernel will modify the ln_Succ/ln_Prev pointer to a given fixed invalid value thus the bug automatically becomes always reproducible. This will also help you spot the fact one is trying to free a Node twice.
  2. "Munge" of memory. With this option the debug kernel will do additional tests on memory pointers. It will help spotting what really happened just by observing the DAR (or DEAR on 440ep and 460ex CPUs) value in the crash log:
    • If the value is 0x00000000 (or thereabouts), then you have accessed a null pointer (and you will see 0xABADCAFE in one or more registers);
    • If the value is 0xDEADBEEF or 0xFEFEBEEF then you have accessed some memory after it has been freed;
    • If the value is 0xABADCAFE then you have accessed uninitialized memory;
    • If the value is 0xCCCCCCCC (or thereabouts), then you have tried to free a Node a second time.

When you want to catch all those problems which you can't catch by just simply running MemGuard on a release kernel then you should use the debug kernel. When developing software, it is recommended that you use the debug kernel.

How to set it up

The kernel.debug file is already placed in the Kickstart directory with all the other kernel modules. By default this directory is "SYS:Kickstart/".

The preferred way to use the debug kernel is to edit your kicklayout file, duplicate the current layout and in this duplicate modify the line pointing to "kernel" so it points to "kernel.debug", do not forget to change the label associated with this new layout by adding 'debug' or something. This way you will be able to choose which configuration you want to boot at any time.

Once you have setup the use of the debug kernel, you must also add some options to the kernel. Basically in order to activate the munge option of the debug kernel you must set the variable "os4_commandline" adds the keyword "munge". This part depends on your platform firmware, please report to your documentation to know how to do it, but you have to do something like "setenv os4_commandline munge" or "setenv os4_commandline=munge" (depends on your firmware), if os4_commandline is already set with another value you can concatenate using space e.g. os4_commandline 'serial munge' to have the debug output to serial port and the munge option activated.

Do not confuse environment variables with command line parameters. You cannot set kernel options via amigaboot.of like "amigaboot.of os4_commandline 'serial'" and the extra parameters will be just ignored. Instead you must set those variables via the "setenv" command in the firmware and then amigaboot.of will parse them.

The following kernel parameters are available:

Outputs all debug via the serial port, instead of using a memory buffer.
baudrate [N]
Sets the serial port baud rate to N.
debuglevel [N]
Sets the debuglevel to level N.
The debug level is the amount of information that should be output by the debug kernel.
Debug levels range between 0 to 20 with 0 being no debug, 5 moderate output (all warnings are 5 or lower), 10 being lots of output, and 15 being an insane amount of output (fault conditions from kernel functions are displayed), and 20 being a ludicrous amount of output (entry and exit to functions will be logged).
Note: higher levels are possible, but will produce too much output to be useful.
Sets the AttnFlags in ExecBase to a 68020 without an FPU.
Munges (fills) freed memory with a recognisable value so that illegal memory accesses can be found more easily when using both the debug and non-debug kernels.
In other words, no valid data will persist past any deallocation function, so if someone reads from memory that has just been freed, they are likely to get a pointer address to a region that will cause an exception when accessed, instead of its previous contents. The munging value written to freed memory is architecture dependant and allocation type dependant, here are some of the values you may encounter: 0xfefecafe, 0xabadcafe, 0xfefeabad, 0xabadabad, 0xfefebeef, 0xdeadbeef.
Note: This argument does nothing on a release kernel.
It is strongly recommended that you do not rename the kernel.debug file.