MACH-STACK(3)                                       MACH-STACK(3)

     NAME
          stacktrace, localaddr, unwindframe, windindex, windreglocs -
          stack traces

     SYNOPSIS
          #include <u.h>
          #include <libc.h>
          #include <mach.h>

          int   stacktrace(Map *map, Rgetter rget, Tracer trace)

          int   localaddr(Map *map, Regs *regs, char *fn, char *val,
          ulong *val)

          int   unwindframe(Map *map, Regs *regs, ulong *next, Symbol
          *sym)

          int   windindex(char *regname)

          Loc*  windreglocs(void)

     DESCRIPTION
          Stacktrace provides machine-independent implementations of
          process stack traces.  They must retrieve data and register
          contents from an executing image.  Sometimes the desired
          registers are not the current registers but rather a set of
          saved registers stored elsewhere in memory.  The caller may
          specify an initial register set in the form of an Rgetter
          function, of the form

               ulong rget(Map *map, char *name)

          It returns the contents of a register when given a map and a
          register name.  It is usually sufficient for the register
          function to return meaningful values only for SP and PC, and
          for the link register (usually LR) on CISC machines.

          Given the map and the rgetter, stacktrace unwinds the stack
          starting at the innermost function.  At each level in the
          trace, it calls the tracer function, which has the form

               int trace(Map *map, ulong pc, ulong callerpc,
                     Rgetter rget, Symbol *s)

          The tracer is passed the map, the current program counter,
          the program counter of the caller (zero if the caller is
          unknown), a new rget function, and a symbol (see mach-
          symbol(3)) describing the current function (nil if no symbol
          is known).  The value returned by the tracer controls
          whether the stack trace continues: a zero or negative return

     Page 1                       Plan 9            (printed 11/18/24)

     MACH-STACK(3)                                       MACH-STACK(3)

          value stops the trace, while a positive return value contin-
          ues it.

          The rgetter passed to the tracer is not the rgetter passed
          to stacktrace itself.  Instead, it is a function returning
          the register values at the time of the call, to the extent
          that they can be reconstructed.  The most common use for
          this rgetter is as an argument to lget4, etc., when evaluat-
          ing the locations of local variables.

          Localaddr uses stacktrace to walk up the stack looking for
          the innermost instance of a function named fn ; once it
          finds the function, it looks for the parameter or local
          variable var, storing the address of the variable in val.

          Unwindframe is the low-level function on which stacktrace is
          built.  Given the current memory image in map and the cur-
          rent register set in regs , unwindframe fills in next with
          the values of the register set at the time of the call to
          the function in the current program counter.  Sym should be
          the symbol corresponding to the current function, if avail-
          able.

          The next array holds only the winding registers, typically
          the caller-save registers and the program counter and stack
          pointer.  The order of registers in the array is called the
          winding order. The winding set can be found in the array
          mach->windreg, which has mach->nwindreg entries.  Windindex
          returns the index of the named register in the winding
          order.  Windreglocs returns an array of Loc structures cor-
          responding to the winding registers, in the winding order.

     EXAMPLE
          The following code writes a simple stack trace to standard
          output, stopping after at most 20 stack frames.
               static int
               trace(Map *map, ulong pc, ulong callerpc,
                   Rgetter rget, Symbol *s, int depth)
               {
                   char buf[512];
                   int i, first;
                   u32int v;
                   Symbol s2;

                   if(sym)
                       print("%s+%lx", s->name, pc - loceval(s->loc));
                   else
                       print("%lux", pc);
                   print("(");
                   first = 0;
                   for(i=0; indexlsym(s, &i, &s2)>=0; i++){
                       if(s.class != CPARAM)

     Page 2                       Plan 9            (printed 11/18/24)

     MACH-STACK(3)                                       MACH-STACK(3)

                           continue;
                       if(first++)
                           print(", ");
                       if(lget4(map, rget, s->loc, &v) >= 0)
                           print("%s=%#lux", s->name, (ulong)v);
                       else
                           print("%s=???", s->name);
                   }
                   print(") called from ");
                   symoff(buf, sizeof buf, callerpc, CTEXT);
                   print("%s\n", buf);
                   return depth < 20;
               }

                   if(stacktrace(map, nil, trace) <= 0)
                       print("no stack frame0);

     SOURCE
          /usr/local/plan9/src/libmach

     SEE ALSO
          mach(3)

     BUGS
          Need to talk about Regs

     Page 3                       Plan 9            (printed 11/18/24)