cvsuser     03/02/23 22:58:39

  Modified:    .        MANIFEST jit_debug.c
               docs     running.pod
  Added:       docs     debug.pod
  Log:
  Improve debugging support and documentation:
   - added new document describing various debugging tricks
   - added the PMC registers to the stabs type info
  
  Revision  Changes    Path
  1.318     +1 -0      parrot/MANIFEST
  
  Index: MANIFEST
  ===================================================================
  RCS file: /cvs/public/parrot/MANIFEST,v
  retrieving revision 1.317
  retrieving revision 1.318
  diff -u -w -r1.317 -r1.318
  --- MANIFEST  18 Feb 2003 20:36:59 -0000      1.317
  +++ MANIFEST  24 Feb 2003 06:58:37 -0000      1.318
  @@ -123,6 +123,7 @@
   debug.ops
   disassemble.c
   disassemble.pl
  +docs/debug.pod
   docs/debugger.pod
   docs/dev/byteorder.dev
   docs/dev/dod.dev
  
  
  
  1.9       +120 -25   parrot/jit_debug.c
  
  Index: jit_debug.c
  ===================================================================
  RCS file: /cvs/public/parrot/jit_debug.c,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -w -r1.8 -r1.9
  --- jit_debug.c       16 Feb 2003 22:41:30 -0000      1.8
  +++ jit_debug.c       24 Feb 2003 06:58:37 -0000      1.9
  @@ -1,7 +1,7 @@
   /*
    * jit_debug.c
    *
  - * $Id: jit_debug.c,v 1.8 2003/02/16 22:41:30 scog Exp $
  + * $Id: jit_debug.c,v 1.9 2003/02/24 06:58:37 sfink Exp $
    *
    * write stabs file for jit code
    * when debugging jit code with gdb, do:
  @@ -13,9 +13,59 @@
   #include <parrot/parrot.h>
   #include "parrot/jit.h"
   
  +#define N_GSYM "32"     /* global variable */
  +#define N_FNAME "34"
  +#define N_FUN "36"
  +#define N_STSYM "38"    /* variable in data section */
  +#define N_LCSYM "40"    /* bss section */
  +#define N_MAIN "42"
  +#define N_ROSYM "44"
  +#define N_PC "48"
  +#define N_NSYMS "50"
  +#define N_NOMAP "52"
  +#define N_OBJ "56"
  +#define N_OPT "60"
  +#define N_RSYM "64"     /* register variable */
  +#define N_M2C "66"
  +#define N_SLINE "68"
  +#define N_DSLINE "70"
  +#define N_BSLINE "72"
  +#define N_BROWS "72"
  +#define N_DEFD "74"
  +#define N_FLINE "76"
  +#define N_EHDECL "80"
  +#define N_MOD2 "80"
  +#define N_CATCH "84"
  +#define N_SSYM "96"
  +#define N_ENDM "98"
  +#define N_SO "100"     /* filename */
  +#define N_LSYM "128"   /* stack variable */
  +#define N_BINCL "130"
  +#define N_SOL "132"
  +#define N_PSYM "160"   /* parameter */
  +#define N_EINCL "162"
  +#define N_ENTRY "164"
  +#define N_LBRAC "192"
  +#define N_EXCL "194"
  +#define N_SCOPE "196"
  +#define N_RBRAC "224"
  +#define N_BCOMM "226"
  +#define N_ECOMM "228"
  +#define N_ECOML "232"
  +#define N_WITH "234"
  +#define N_NBTEXT "240"
  +#define N_NBDATA "242"
  +#define N_NBBSS "244"
  +#define N_NBSTS "246"
  +#define N_NBLCS "248"
  +
   #ifdef __GNUC__
   void Parrot_jit_debug(struct Parrot_Interp* interpreter);
   
  +#define BIT_SIZE(t) ((int)(sizeof(t)*8))
  +#define BYTE_SIZE(t) ((int)sizeof(t))
  +#define BIT_OFFSET(str, field) ((int)(offsetof(str, field) * 8))
  +
   typedef struct {
        const char *name;
        const char *spec;
  @@ -23,7 +73,7 @@
   static void
   write_types(FILE *stabs)
   {
  -    int i;
  +    int i, j;
       /* borrowed from mono */
       static BaseTypes base_types[] = {
               {"Void", "(0,1)"},
  @@ -61,11 +111,10 @@
           } else {
               fprintf (stabs, "%s\"", base_types[i].spec);
           }
  -        fprintf (stabs, ",128,0,0,0\n");
  +        fprintf (stabs, "," N_LSYM ",0,0,0\n");
       }
       fprintf(stabs, ".stabs \"STRING:t(0,%d)=*(0,%d)\""
  -                ",128,0,0,0\n", i, i+1);
  -    i++;
  +                "," N_LSYM ",0,0,0\n", i, i+1);
       fprintf(stabs, ".stabs \"Parrot_String:T(0,%d)=s%d"
                   "bufstart:(0,14),%d,%d;"
                   "buflen:(0,6),%d,%d;"   /* XXX type */
  @@ -73,18 +122,60 @@
                   "bufused:(0,12),%d,%d;"
                   "strstart:(0,15),%d,%d;"        /* fake a char* */
                   ";\""
  -                ",128,0,0,0\n", i++, (int) sizeof(STRING),
  -                (int)(offsetof(STRING, bufstart) * 8),
  -                (int)(sizeof(void *)* 8),
  -                (int)(offsetof(STRING, buflen) * 8), 
  -                (int)(sizeof(size_t) * 8),
  -                (int)(offsetof(STRING, obj.flags) * 8), 
  -                (int)(sizeof(UINTVAL) * 8),
  -                (int)(offsetof(STRING, bufused) * 8), 
  -                (int)(sizeof(UINTVAL) * 8),
  -                (int)(offsetof(STRING, strstart) * 8), 
  -                (int)(sizeof(void *) * 8)
  +                "," N_LSYM ",0,0,0\n", i++, BYTE_SIZE(STRING),
  +                BIT_OFFSET(STRING, bufstart), BIT_SIZE(void*),
  +                BIT_OFFSET(STRING, buflen), BIT_SIZE(size_t),
  +                BIT_OFFSET(STRING, obj.flags), BIT_SIZE(UINTVAL),
  +                BIT_OFFSET(STRING, bufused), BIT_SIZE(UINTVAL),
  +                BIT_OFFSET(STRING, strstart), BIT_SIZE(void*)
  +                );
  +
  +    fprintf(stabs, ".stabs \"PMCType:T(0,%d)=e", i++);
  +    for (j = 0; j < enum_class_max; ++j) {
  +        if (Parrot_base_vtables[j].name) {
  +            STRING* name = (*Parrot_base_vtables[j].name)(NULL, NULL);
  +            fwrite(name->strstart, name->strlen, 1, stabs);
  +            fprintf(stabs, ":%d,", j);
  +        }
  +    }
  +    fprintf(stabs, ";\"," N_LSYM ",0,0,0\n");
  +
  +    /* PMC type */
  +    fprintf(stabs, ".stabs \"PMC:T(0,%d)=s%d", i, BYTE_SIZE(PMC));
  +    fprintf(stabs, "obj:(0,%d),%d,%d;",
  +            i + 1, BIT_OFFSET(PMC, obj), BIT_SIZE(pobj_t));
  +    fprintf(stabs, "vtable:*(0,%d),%d,%d;",
  +            i + 3, BIT_OFFSET(PMC, vtable), BIT_SIZE(void*));
  +    fprintf(stabs, "data:(0,14),%d,%d;",
  +            BIT_OFFSET(PMC, data), BIT_SIZE(void*));
  +    fprintf(stabs, "metadata:*(0,%d),%d,%d;",
  +            i, BIT_OFFSET(PMC, metadata), BIT_SIZE(void*));
  +    fprintf(stabs, ";\"");
  +    fprintf(stabs, "," N_LSYM ",0,0,0\n");
  +
  +    fprintf(stabs, ".stabs \"pobj_t:T(0,%d)=s%d"
  +                "u:(0,%d),%d,%d;"
  +                "flags:(0,12),%d,%d;"
  +                ";\""
  +                "," N_LSYM ",0,0,0\n", i + 1, (int)(sizeof(pobj_t)),
  +                i + 2, BIT_OFFSET(pobj_t, u), BIT_SIZE(UnionVal),
  +                BIT_OFFSET(pobj_t, flags), BIT_SIZE(Parrot_UInt)
  +                );
  +    fprintf(stabs, ".stabs \"UnionVal:T(0,%d)=u%d"
  +                "int_val:(0,12),%d,%d;"
  +                "pmc_val:*(0,%d),%d,%d;"
  +                ";\""
  +                "," N_LSYM ",0,0,0\n", i + 2, BYTE_SIZE(UnionVal),
  +                BIT_OFFSET(UnionVal, int_val), BIT_SIZE(INTVAL),
  +                i, BIT_OFFSET(UnionVal, pmc_val), BIT_SIZE(void*)
  +                );
  +    fprintf(stabs, ".stabs \"VTABLE:T(0,%d)=s%d"
  +                "base_type:(0,%d),%d,%d;"
  +                ";\""
  +                "," N_LSYM ",0,0,0\n", i + 3, BYTE_SIZE(UnionVal),
  +                i - 1, BIT_OFFSET(VTABLE, base_type), BIT_SIZE(INTVAL)
                   );
  +    i += 4;
   
   }
   
  @@ -94,12 +185,14 @@
       int i;
       /* fake static var stabs */
       for (i = 0; i < NUM_REGISTERS; i++) {
  -        fprintf(stabs, ".stabs \"I%d:S(0,12)\",38,0,0,%p\n", i,
  +        fprintf(stabs, ".stabs \"I%d:S(0,12)\"," N_STSYM ",0,0,%p\n", i,
                   (char*)&interpreter->ctx.int_reg.registers[i]);
  -        fprintf(stabs, ".stabs \"N%d:S(0,13)\",38,0,0,%p\n", i,
  +        fprintf(stabs, ".stabs \"N%d:S(0,13)\"," N_STSYM ",0,0,%p\n", i,
                   (char*)&interpreter->ctx.num_reg.registers[i]);
  -        fprintf(stabs, ".stabs \"S%d:S(0,16)\",38,0,0,%p\n", i,
  +        fprintf(stabs, ".stabs \"S%d:S(0,16)\"," N_STSYM ",0,0,%p\n", i,
                   (char*)&interpreter->ctx.string_reg.registers[i]);
  +        fprintf(stabs, ".stabs \"P%d:S*(0,18)\"," N_STSYM ",0,0,%p\n", i,
  +                (char*)&interpreter->ctx.pmc_reg.registers[i]);
       }
   }
   
  @@ -156,10 +249,10 @@
           return;
   
       /* filename info */
  -    fprintf(stabs, ".stabs \"%s\",100,0,0,0\n",
  +    fprintf(stabs, ".stabs \"%s\"," N_SO ",0,0,0\n",
               string_to_cstring(interpreter, pasmfile));
       /* jit_func start addr */
  -    fprintf(stabs, ".stabs \"jit_func:F(0,1)\",36,0,1,%p\n",
  +    fprintf(stabs, ".stabs \"jit_func:F(0,1)\"," N_FUN ",0,1,%p\n",
               jit_info->arena.start);
   
       write_types(stabs);
  @@ -169,22 +262,24 @@
        */
   
       /* jit_begin */
  -    fprintf(stabs, ".stabn 68,0,1,0\n");
  +    fprintf(stabs, ".stabn " N_SLINE ",0,1,0\n");
       line = 1;
       lc = 0;
       for (i = 0; i < jit_info->arena.map_size; i++) {
           if (jit_info->arena.op_map[i].ptr) {
  +            op_info_t* op = 
&interpreter->op_info_table[interpreter->code->byte_code[i]];
               if (interpreter->code->cur_cs->debug) {
                   line = (int)interpreter->code->cur_cs->debug->base.data[lc++];
               }
  -            fprintf(stabs, ".stabn 68,0,%d,%d\n", line,
  +            fprintf(stabs, ".stabn " N_SLINE ",0,%d,%d /* %s */\n", line,
                       (int)((char *)jit_info->arena.op_map[i].ptr -
  -                          (char *)jit_info->arena.start));
  +                    (char *)jit_info->arena.start),
  +                    op->full_name);
               line++;
           }
       }
       /* eof */
  -    fprintf(stabs, ".stabs \"\",36,0,1,%p\n",
  +    fprintf(stabs, ".stabs \"\"," N_FUN ",0,1,%p\n",
               (char *) jit_info->arena.size);
       fclose(stabs);
       /* run the stabs file through C<as> generating file.o */
  
  
  
  1.12      +1 -1      parrot/docs/running.pod
  
  Index: running.pod
  ===================================================================
  RCS file: /cvs/public/parrot/docs/running.pod,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -w -r1.11 -r1.12
  --- running.pod       21 Oct 2002 08:47:08 -0000      1.11
  +++ running.pod       24 Feb 2003 06:58:39 -0000      1.12
  @@ -65,7 +65,7 @@
   
     make libparrot.a
     gcc -O3 -g -Iinclude -c foo.c -o foo.o
  -  gcc -g -o foo foo.o -L. -lparrot -ldl
  +  gcc -g -o foo foo.o -L. -lparrot -ldl -lm
     ./foo # Runs it
   
   =item B<make test>
  
  
  
  1.1                  parrot/docs/debug.pod
  
  Index: debug.pod
  ===================================================================
  =head1 TITLE
  
  Debugging Parrot
  
  =head1 HISTORY
  
  =over 4
  
  =item Version 1.0
  
  First version by Steve Fink <[EMAIL PROTECTED]>
  
  =back
  
  =head1 ABSTRACT
  
  This document describes ways to debug various parts of Parrot.
  
  =head1 THE PARROT BINARY
  
  First, you'll want to use the --debugging flag with Configure.pl to
  generate debugging symbols for the parrot binary:
  
    shell> perl Configure.pl --debugging
    shell> make
  
  You can then run the parrot binary under gdb.
  
  =head2 MEMORY MANAGEMENT
  
  Some of the more frequent and exasperating parrot bugs are related to
  memory management in general, and garbage collection in particular.
  
  =head3 Infant mortality
  
  See L<dev/infant.dev> for details of one frequent problem: infant
  mortality. Infant mortality is when you create a Parrot object, but
  the garbage collector runs before you put it into a Parrot register or
  in something else that is itself within a Parrot register.
  
  To help in resolving these issues, the parrot binary accepts a
  --gc-debug flag that makes such problems much more likely to occur (it
  makes garbage collection occur as frequently as possible, to maximize
  the probability that any newborn objects will run afoul of the garbage
  collector if they are improperly coded.)
  
  Within the --gc-debug mode, there is another tool to help narrow down
  the problem. If you edit include/parrot/parrot.h and #define the
  C<GC_VERBOSE> flag to 1, then after the garbage collector has traced
  all objects to find which ones are still alive, it will scan through
  all of the dead objects to see if any of them believe they are alive
  (which will happen for infants, since they come into existence marked
  live.) If it finds any, it will print them out. You can then re-run
  the program with a breakpoint set on the routine that allocated the
  object (e.g. C<get_free_object> in C<smallobject.c>). You'll probably
  want to make the breakpoint conditional on the object having the
  version number that was reported, because the same memory location
  will probably hold many different objects over the lifetime of the
  program.
  
  =head1 IMCC AND PASM CODE
  
  Let's say you have written (or generated) a huge .pasm or .imc file.
  It's not working. You'd like some help in figuring out why.
  
  =head2 pdb
  
  One possible tool is C<pdb>, the Parrot Debugger. See L<debugger.pod>
  for details on it.
  
  =head2 stabs
  
  If you are running on a jit-capable machine, you can also try using
  GDB by having the JIT generate C<stabs> metadata and then stepping
  through the code with GDB as if it were any other language.
  
  To use this, you'll want to use C<imcc> to generate your bytecode
  (.pbc file). It is not strictly necessary, but you'll get more
  information into the bytecode this way.
  
  Let's say your file is named C<test.pasm>. (Note: these instructions
  will also work if you use C<test.imc> everywhere C<test.pasm> occurs.)
  
  Step 1: Generate the .pbc file with extra debugging information.
  
    shell> imcc -d -o test.pbc test.pasm
  
  Step 2: Start up parrot under GDB
  
    shell> gdb parrot
  
  or
  
    shell> emacs &
    (in emacs) M-x gdb
    (in emacs) type "parrot" so it says "gdb parrot"
  
  Step 3: Set a breakpoint on runops_jit
  
    gdb> b runops_jit
  
  Step 4: Run your program under GDB with JIT and debugging on
  
    gdb> run -j -d test.pbc
  
  Step 5: GDB will stop at the beginning of runops_jit. Step through the
  lines until just before the JITted code is executed (the line will be
  something like C<(jit_code)(interpreter,pc)>.
  
    gdb> n
    gdb> n
    .
    .
    .
  
  Step 6: load in the debugging information from the symbol file that
  the jit just generated.
  
    gdb> add-symbol-file test.o 0
  
  Step 7: Step into the JITted code
  
    gdb> s
  
  At this point, you can step through the instructions, or print out the
  various Parrot registers. GDB will know about I0-I31, N0-N31, S0-S31,
  and P0-P31.
  
  =head3 WARNING: Stepping too far
  
  One thing to watch out for is that GDB gets confused when attempting
  to step over certain instructions. The only ones that I have noticed
  having problems is keyed operations. With my version of GDB, if I do
  'n' to step over the instruction, GDB will start running and only stop
  when the entire parrot program has finished. To work around this, do
  'si' twice just before executing any keyed op. For some reason, GDB
  can then figure out when it's supposed to stop next. If you know of a
  better technique, please let the mailing list know
  (C<[EMAIL PROTECTED]>).
  
  =head1 IMCC CODE GENERATION
  
  The C<imcc> binary has a bunch of debugging flags for spewing out
  information about various aspects of its processing. See
  L<languages/imcc/docs/running.pod> for a list of flags.
  
  
  

Reply via email to