Menu

Directions for debug mode

2018-01-26
2018-02-16
  • Scott Franco

    Scott Franco - 2018-01-26

    Directions for debug mode

    So some quick notes about where the (brand new) debug mode is going.

    Here is the current help list for debug mode:

    Commands:

    li [s[,e|:l] List machine instructions
    d [s[,e|:l] Dump memory
    ds Dump storage parameters
    dd [s] Dump display frames
    bi a Place breakpoint at instruction
    c [a] Clear breakpoint/all breakpoints
    lb List active breakpoints
    si [n] Step instructions
    sis [n] Step instructions silently
    hs Report heap space
    pc a Set pc contents
    sp a Set sp contents
    mp a Set mp contents
    np a Set np contents
    cp a Set cp contents
    ti Turn instruction tracing on
    nti Turn instruction tracing off
    tr Turn system routine tracing on
    ntr Turn system routine tracing off
    ts Turn source line tracing on
    nts Turn source line tracing off
    r Run program from current pc
    ps Print current registers and instruction
    q Quit interpreter

    What debug mode does is behave like a SLD (Source Level Debug) such
    as gdb for programs running on P6. If you look at the code, you'll
    note that the source level statements are mostly stubbed out
    (not implemented) but that will change rapidly.

    SLD depends on two things, one fairly easy and the other harder.
    Gaining access to the source is just a matter of opening the file,
    which P6 does by using its own language extension routines like
    assigntext(), etc. The file gets indexed, so that it can rapidly
    find what source file locations correspond to which line numbers.
    Then listing source, breakpointing in terms of source lines, etc,
    these all flow naturally.

    Harder is to be able to debug in terms of source level symbols.
    This includes things like printing variables in terms of original
    Pascaline source, showing all locals to current procedure/function,
    watching variables, setting variables, etc. The basis
    of this is both sending symbols from the front end (pcom) to the
    back end (pint) via the intermediate file. In addition, it must
    also send a description of the type of each object along with the
    symbol.

    Machine vs. source level debug

    Much as gdb does, the idea is that both source level and machine
    level debug is supported, with a slight preference to source
    level debug, since that is the mode I believe most users will
    want.

    To this end there is regularity in the naming convention. For
    example:

    l - list source lines.
    li - list machine instructions.
    s - step source line.
    si - step machine instructions.
    b - Break at source line.
    bi - Break at machine instruction.

    etc.

    So the idea here is that both source level debuggers and
    machine level debuggers get support, and if you do both modes
    at once (like me), you are also supported. For source level,
    that mode gets the shorter commands.

    Symbolic debugging

    For symbols, the "gold standard" is to be able to print and
    modify the contents of any variable, global or local, using
    expressions and access syntax and semantics that are the same
    or similar as the original language. Secondary to this is
    the ability to place a watch on a variable (print on any
    changes) and to print whole slices of structures, and to print
    all variables in the set of locals.

    To this end, I have established two design principles for the
    symbols annotation in the intermediate:

    1. The type description is a simple ASCII string sequence.

    2. One string completely describes the entire type. IE., it
      does not cross reference other types as the original language
      does (nor indeed have any concept of a named type).

    Another design princple for symbolic referencing is that
    the debug is very lax as to how it treats types. For example,

    s := 1;

    Same as:

    s := one;

    for The type (zero, one, two);

    And:

    c := $41;

    Same as:

    c := 'A';

    IE., it is not the debuggers job to enforce type restrictions.

    In summary

    Debuggers, source and machine level, can be used at both
    interpreter level and target machine level. However, machine
    level debuggers, while ultimately very useful in their own
    right, suffer from the issue that an advanced compiler will
    often modify the result code so that it bears little
    relationship to the original source code. This is a result
    of optimization, which moves or eliminates code blocks.

    Additionally, it is often hard to integrate as many runtime
    checks in a final machine compiler as are in the intermediate.
    This is an important factor in P6 and P5. In fact, I will
    say it again (and again): P5 and P6 are more throughly runtime
    checked than any other Pascal compiler that exists or has
    ever existed, and all of the possible runtime checks are not
    even done yet. Read the PRT specifications. Most of those
    checks are never done in compilers.

    Thus, although both interpreter level and machine level
    debugging are useful, I think interpreter level debug is much
    better and smoother than machine level debug. This also
    means that keeping the interpretive mode in P5/P6 equal to
    the full compiled mode in functionality is very important.

    In short, the debug mode for P6, in terms of a "bang for the
    buck" analysis, is a clear win. I got the initial version
    running in two days of after hours work, and the footprint
    is not great.

    I hope you will find it useful.

    Scott Franco

     

    Last edit: Scott Franco 2018-01-27
  • Scott Franco

    Scott Franco - 2018-02-16

    Almost done with debug mode. I won't bother to go over how it works again. Its really complex (perhaps overly). I'll save it for the documentation.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.