Hacker's guide: Debugging and patching the kernel

Debugging the Kernel, and building patches for it

I think I found a bug in the kernel. How do I try to fix it?

Assuming you don't have write access to /usr/share/smalltalk/kernel, or don't want to modify those files before having a definitive fix, the answer is to temporarily extend the class of concern.

A slight variation on the procedure described below is to work in the source tree itself - see the section "Developing within the main source tree" below.

Let's take as an example a problem found in CType.st of gst-2.95h, in the issue tracker as issue 148.

Step 0: Develop a test case

This is the most important step. Without a terse test case, it can be very difficult to isolate the fault.

For the chosen example, the following code, placed into testcase.st serves as our test case:

CStruct subclass: #StructB.
(CStruct subclass: #StructC) declaration: #((#b (#ptr #{StructB}))).
StructC new b elementType cObjectType printNl

The test case is run with the command

$ gst testcase.st
Object: Array new: 1 "<0x40318b40>" error: did not understand #binding
Array(Object)>>doesNotUnderstand: #binding
CType class>>cObjectType:

The expected output (as we imagine it, at this point) is simply

$ gst testcase.st 

Step 1: Develop your fix

After some experimentation, CType>>#storeOn: was found to be at fault. In order to experiment with a fix, it's convenient to use class extension to avoid having to touch the installed kernel files or the default image. Place the replacement method in a separate file, proposed-fix.st:

CType extend [
    storeOn: aStream [
        "Store Smalltalk code that compiles to the receiver"

            nextPut: $(;
            print: self class;
            nextPutAll: ' cObjectType: ';
            print: self cObjectType;
            nextPut: $)

Note how the extension overrides the existing CType>>#storeOn: method. Test your fix by loading it before your testcase script:

$ gst proposed-fix.st testcase.st

Success! Now we have a working set of overrides, it's time to format them as a unified diff patch for submission in the issue tracker.

Step 2: Convert your fix into a patch

You will need two separate checkouts of the source code for the system: one untouched version, that you will use as a baseline for running diff against, and one version you will apply your changes to.

$ tar -zxvf smalltalk-2.95h.tar.gz
$ mv smalltalk-2.95h smalltalk-2.95h-orig
$ cp -R smalltalk-2.95h-orig smalltalk-2.95h-modified

Our example proposed fix replaces a method in class CType, which resides in kernel/CType.st. Edit that file in the smalltalk-2.95h-modified directory.

Once you've updated the sources, it's time to make the patch:

$ diff -ru smalltalk-2.95h-orig smalltalk-2.95h-modified > proposed-fix.patch

The proposed-fix.patch now contains a unified diff record of the changes you've made. Review the file, checking that it makes sense, includes all the changes you want, and doesn't include any unintended changes.

Step 3: Test your patch

To test your patch, make sure it applies cleanly to the distribution:

$ tar -zxvf smalltalk-2.95h.tar.gz
$ cd smalltalk-2.95h
$ patch -p1 < ../proposed-fix.patch
patching file kernel/CType.st

Now try compiling and installing the resulting source tree.

Step 4: Submit your patch

You can submit your finished patch either using the issue tracker, or by mailing the mailing list.

Make sure you include a description of the purpose of your patch, including a description of the fault and the rationale for your fix.

Aside: building images including a workaround or fix

How do I apply it to future images I generate (using ~/.st/pre.st or the ~/.st/kernel directory)?


Syndicate content

User login