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 MessageNotUnderstood(Exception)>>signal Array(Object)>>doesNotUnderstand: #binding CType class>>cObjectType: StructC>>b UndefinedObject>>executeStatements
The expected output (as we imagine it, at this point) is simply
$ gst testcase.st StructB
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"
aStream
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 StructB
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)?
TODO
