Debugging in Composite:
-----------------------

In this file I'll go over the 3 main techniques for debugging in
Composite: 1) print statements -- classical and still just as useful,
2) assert statements -- for defensive programming, 3) how to track
down the cause of faults.

Print Statements in Composite:
------------------------------

In any component, you can

#include <llprint.h>

You can, at any point in your code, use

printc(...);

which has a format exactly like printf(...); (see "man 3 printf").

Do not use printf in Composite.

Assert Statements in Composite:
-------------------------------

Assert statements are a way for you to check pre- and post-conditions
within your code.  You can, for instance, say:

assert(array_len < MAX_LEN);

if you know that the length of your array should always be less than
MAX_LEN.  This can be used to catch errors defensively in your code.
You should use many assert statements.

You must satisfy the same dependencies, and

#include <cos_debug.h>

as for using printc above.  Asserts don't slow down code much, so
don't let performance be a concern.  The implementation of asserts
optimizes branch prediction so that there is little slowdown when the
assert isn't triggered.

If an assert statement is triggered, it will cause the system to
segmentation fault after printing the file and line number of the
assert that triggered to the kernel log.

When the system segmentation faults, you should look through the last
hundred or so lines of it to see if there is a line saying

assert error in @ file:#

The error was triggered in "file" at line number "#".

Assessing Segmentation Faults:
-----------------------------

Sometimes you will write code that faults.  This will be reported as a
segmentation fault, like so:

General registers-> EAX: 0, EBX: 0, ECX: 0, EDX: 0
Segment registers-> CS: 1b, DS: 23, ES: 23, FS: 23, GS: 33, SS: 23
Index registers-> ESI: 0, EDI: 0, EIP: 0x47800037, ESP: 40810ed8, EBP: 40810f10
Indicator-> EFLAGS: 3202
(Exception Error Code-> ORIG_AX: 6)
FAULT: Page Fault in thd 2 (not-present write-fault user-mode  ) @ 0x0, ip 0x47800037

This says that the fault happened while executing in thread number 2. The
registers of that thread when the fault occurred are printed as eis
through ebp.  eip is the instruction pointer.

Let's say this fault was in the cpu component. We wish to figure out which line
of code in the cpu.o component caused the fault.  For this we use "objdump", a
program that allows you to decompile a component, and look at its assembly
source. If the
C code was compiled with debugging symbols (which we do by default for
Composite), then it will also show C lines.  In the root directory,
execute the following:

objdump -Srhtl cpu.o

You'll see the contents of the object file.  We know that the fault
happened at instruction address 0x47800037 from the fault report.
Here we ignore the top bits of the address, and do a search through
the object file for the instruction addressed "37".  We find the
code:

void cos_init(void *arg)
{
  20:   55                      push   %ebp
  21:   89 e5                   mov    %esp,%ebp
  23:   83 ec 08                sub    $0x8,%esp
/home/gparmer/research/composite/src/components/implementation/other/cpu/spin.c:18
        assert(0);
  26:   c7 04 24 00 00 00 00    movl   $0x0,(%esp)
                        29: R_386_32    .rodata
  2d:   e8 20 00 00 00          call   52 <prints>
  32:   b8 00 00 00 00          mov    $0x0,%eax
  37:   c7 00 00 00 00 00       movl   $0x0,(%eax)
/home/gparmer/research/composite/src/components/implementation/other/cpu/spin.c:20
//      spin_var = *(int*)NULL;
        while (1) if (spin_var) other = 1;
  3d:   a1 00 00 00 00          mov    0x0,%eax

We can see that instruction 37 dereferenced a null pointer.  More
importantly, if you look up in the code, we see that that code
corresponds to line 18 in
src/components/implementation/other/cpu/spin.c and that corresponds to

assert(0);

That line is within the cos_init function.  Because we compiled our
components with debugging symbols, we can see the C code.  So we can
see that the assert function caused this error.  Now you see the
usefulness of assertion statements.  Instead of going through this
whole process with objdump, you could have simply looked up in the log
and found the following line:

assert error in @ spin.c:18.

Much easier than disassembling objects.  However, when a fault is
caused by an error that didn't trigger an assert, you must use the
above techniques to track down the error.

Stack traces:
-------------

Composite currently lacks stack trace support.
