.title trace Profile support entry module (with trace) for ast's .ident "V2.1" ;+ ; ; Index Profile support module (with trace) for ast's ; ; Usage ; ; #include ; extern FILE *$$flow; ; ; $$flow = fopen("trace.out", "w"); ; ; /* or $$flow = stderr; to trace to the console */ ; ... ; $$flow = NULL; /* Turn off flow trace */ ; ; Internal ; ; jsr r5,pcsv$ ; .word name ; Pointer to name ; ; Where name has the structure: ; ; name: .word 0 ; Counter ; .asciz /name/ ; function name ; ; Description ; ; This module is called whenever a function that was compiled ; with the profile option is executed. It checks that the ; stack will remain above 600 octal when the function executes ; and optionally prints a flow-trace. It is a modified version ; of the pcsv() function in the DECUS C library which saves R0 ; so that C routines may be used as RSX-11 AST service routines. ; ; For more information on C AST service routines, see the astset() ; documentation and the AST usage information in the CX library ; manual. ; ; If $$flow is set to a file descriptor, the function name, ; location the function is called from, and the calling environment, ; are printed on each call to a function compiled with the profile ; option. ; ; The output format is: ; ; function_namecallerenvironment ; ; Where function_name is the name of the function being called, ; caller is the address of the calling program (actually, ; the return address), and environment is the R5 argument ; pointer (for local addressing within the routine being called). ; The information will be written to $$flow with a newline before ; and after. ; ; If profiling has been enabled and the program exits via ; error() or via an operating-system trap (such as an illegal ; memory reference), a register dump and subroutine trace ; will be written to stderr. ; ; See the description of calltrace() for details. ; ; Internal ; ; See acsv$ for details of the calling environment. ; ; When this routine is entered for the first time, it sets ; up to intercept synchronous system traps, and loads the ; error exit address and profile pointer. The trap service ; routines are in the "traps" module. See the description there ; for more information. ; ; Bugs ; ; [end] ;- ; ; Edit history ; V2.0 19-Oct-82 RBD Re-baseline for new C kit release. ; V2.1 19-Jan-87 JMC Change .psect for I/D space. ; .enabl gbl,lc .psect C$DATA,D ;2.1 $$flow:: ; set FILE *$$flow for tracing .word 0 format: .byte 12 .ascii "%s" .byte 11 .ascii "%06o" .byte 11 .ascii "%06o" .byte 12,0 die: .byte 15,12 .asciz /-IO-TRACE-stack below 600 octal at/ onesht: .byte 1 ;set to zero when one-shot done .even .psect C$CODE ; ; Set up SST intercept first time through. ; pcsv$:: asrb onesht ;Setup code executed? bcc 8$ ;Yes, skip setup code .mcall SVTK$S ;One shot deserves $S form. SVTK$S #$$sstt,#10 ;Table is in "traps" module ; Set up special profile and exit pointers mov #$$prof,$$pptr ;Profile pointer mov #$$ctra,$$errx ;Error exit ; ; Warning, this code must match the standard C save sequence. ; 8$: sub #10,sp mov r5,(sp) mov sp,r5 tst (r5)+ mov r2,(r5)+ mov r3,(r5)+ mov r4,(r5)+ mov (sp),r4 ;r4 -> profile word inc @(r4)+ ;bump profile count mov r1,-(sp) ;save the rest mov r0,-(sp) ;of the registers ; ; Trace the call ; mov $$flow,r1 ;Get flow file pointer beq 10$ ;None, just check stack overflow mov r5,-(sp) ;frame pointer mov 2(r5),-(sp) ;caller mov -(r0),-(sp) ;(sp) -> pcsv buffer add #2,(sp) ;(sp) -> function name mov #format,-(sp) ;format mov r1,-(sp) ;$$flow jsr pc,fprintf ;print it add #<5.*2>,sp ;drop arguments ; 10$: mov sp,r0 ;new stack pointer cmp (r4),(pc)+ ;Is first subroutine instruction sub (pc)+,sp ;get auto memory? bne 20$ ;no, just check current frame pointer sub 2(r4),r0 ;yes, do the subtract bcs 30$ ;Death if it underflowed 20$: cmp r0,#600 ;Got enough room? blo 30$ ;br if not mov (sp)+,r0 ;restore registers mov (sp)+,r1 ;both of them jsr pc,(r4) ;tst -(sp); jmp (r4) -- Ok exit ; 30$: mov #die,-(sp) ;Sorry about that jsr pc,msg ;Inform the user mov -(r4),(sp) ;Function name add #2,(sp) ;onto stack jsr pc,msg ;Print it jmp $$exit ;Can't do more ; .end