1 /* -*- D -*- 2 * 3 * Execution flow trace with arguments 4 * 5 * Activate tracing between 6 * ::nsf::configure dtrace on 7 * and 8 * ::nsf::configure dtrace off 9 * 10 * Since this D script accesses the C data structures it is sensitive 11 * to the representation sizes of the data structures (e.g. pointers). 12 * Make sure to call the script with the appropriate architecture flag 13 * on Mac OS X; on SunOS, there is apparently a -32 or -64 flag. 14 * 15 * Example: 16 * 17 * sudo dtrace -arch x86_64 -x bufsize=20m -F -s dtrace/execution-flow-args.d \ 18 * -c "./nxsh dtrace/sample.tcl" 19 * 20 * -gustaf neumann 21 */ 22 23 enum {maxstrlen = 50}; 24 25 /* 26 * Needed data structures to access the content of Tcl_Objs. 27 */ 28 typedef struct Tcl_Obj Tcl_Obj; 29 30 typedef struct Tcl_ObjType { 31 char *name; 32 void *freeIntRepProc; 33 void *dupIntRepProc; 34 void *updateStringProc; 35 void *setFromAnyProc; 36 } Tcl_ObjType; 37 38 struct Tcl_Obj { 39 int refCount; 40 char *bytes; 41 int length; 42 Tcl_ObjType *typePtr; 43 union { 44 long longValue; 45 double doubleValue; 46 void *otherValuePtr; 47 int64_t wideValue; 48 struct { 49 void *ptr1; 50 void *ptr2; 51 } twoPtrValue; 52 struct { 53 void *ptr; 54 unsigned long value; 55 } ptrAndLongRep; 56 } internalRep; 57 }; 58 59 /* 60 * Handling "nsf::configure dtrace on|off". 61 */ 62 nsf*:::configure-probe /!self->tracing && copyinstr(arg0) == "dtrace" / { 63 self->tracing = (arg1 && copyinstr(arg1) == "on") ? 1 : 0; 64 } 65 66 nsf*:::configure-probe /self->tracing && copyinstr(arg0) == "dtrace" / { 67 self->tracing = (arg1 && copyinstr(arg1) == "off") ? 0 : 1; 68 } 69 70 /* 71 * Output object, class, method, number of arguments and first two 72 * arguments upon method invocation. 73 */ 74 nsf*:::method-entry /self->tracing/ { 75 76 this->objv = arg3 ? ((Tcl_Obj**)copyin((user_addr_t)((Tcl_Obj**)arg4), 77 sizeof(Tcl_Obj*) * arg3)) : NULL; 78 79 this->i = 0; 80 this->o = arg3 > this->i && *(this->objv + this->i) ? 81 (Tcl_Obj*)copyin((user_addr_t)*(this->objv + this->i), sizeof(Tcl_Obj)) : NULL; 82 this->s0 = this->o ? (this->o->bytes ? copyinstr((user_addr_t)this->o->bytes, maxstrlen) : 83 lltostr(this->o->internalRep.longValue)) : ""; 84 85 this->i = 1; 86 this->o = arg3 > this->i && *(this->objv + this->i) ? 87 (Tcl_Obj*)copyin((user_addr_t)*(this->objv + this->i), sizeof(Tcl_Obj)) : NULL; 88 this->s1 = this->o ? (this->o->bytes ? copyinstr((user_addr_t)this->o->bytes, maxstrlen) : 89 lltostr(this->o->internalRep.longValue)) : ""; 90 91 printf("%s %s.%s (%d) %s %s", 92 copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3, 93 this->s0, this->s1); 94 } 95 96 /* 97 * Output object, class, method and return code upon method return. 98 */ 99 nsf*:::method-return /self->tracing/ { 100 printf("%s %s.%s -> %d", copyinstr(arg0), copyinstr(arg1), copyinstr(arg2), arg3); 101 } 102