Commit | Line | Data |
---|---|---|
e725d5e5 | 1 | static char *sccsid = "@(#)gmon.c 4.7 (Berkeley) %G%"; |
50084e08 | 2 | |
bb9c5045 | 3 | #ifdef DEBUG |
50084e08 | 4 | #include <stdio.h> |
bb9c5045 | 5 | #endif DEBUG |
50084e08 | 6 | |
ee56ba6f | 7 | #include "gmon.h" |
387d0540 PK |
8 | |
9 | /* | |
10 | * froms is actually a bunch of unsigned shorts indexing tos | |
11 | */ | |
50084e08 PK |
12 | static unsigned short *froms; |
13 | static struct tostruct *tos = 0; | |
14 | static unsigned short tolimit = 0; | |
15 | static char *s_lowpc = 0; | |
16 | static char *s_highpc = 0; | |
3a2b18f4 | 17 | static unsigned long s_textsize = 0; |
63238688 | 18 | static char *minsbrk = 0; |
50084e08 | 19 | |
387d0540 PK |
20 | static int ssiz; |
21 | static int *sbuf; | |
50084e08 | 22 | |
50084e08 PK |
23 | #define MSG "No space for monitor buffer(s)\n" |
24 | ||
ee56ba6f | 25 | monstartup(lowpc, highpc) |
387d0540 PK |
26 | char *lowpc; |
27 | char *highpc; | |
50084e08 | 28 | { |
3a2b18f4 PK |
29 | int monsize; |
30 | char *buffer; | |
31 | char *sbrk(); | |
32 | unsigned long limit; | |
50084e08 | 33 | |
387d0540 PK |
34 | s_lowpc = lowpc; |
35 | s_highpc = highpc; | |
3a2b18f4 | 36 | s_textsize = highpc - lowpc; |
e725d5e5 | 37 | monsize = (s_textsize + 1) / 2 + sizeof(struct phdr); |
387d0540 PK |
38 | buffer = sbrk( monsize ); |
39 | if ( buffer == (char *) -1 ) { | |
40 | write( 2 , MSG , sizeof(MSG) ); | |
41 | return; | |
42 | } | |
3a2b18f4 | 43 | froms = (unsigned short *) sbrk( s_textsize ); |
387d0540 PK |
44 | if ( froms == (unsigned short *) -1 ) { |
45 | write( 2 , MSG , sizeof(MSG) ); | |
46 | froms = 0; | |
47 | return; | |
48 | } | |
4dff44be KM |
49 | limit = s_textsize * DENSITY / 100; |
50 | if ( limit < MINCNT ) { | |
51 | limit = MINCNT; | |
52 | } else if ( limit > 65534 ) { | |
53 | limit = 65534; | |
54 | } | |
55 | tos = (struct tostruct *) sbrk( limit * sizeof( struct tostruct ) ); | |
387d0540 PK |
56 | if ( tos == (struct tostruct *) -1 ) { |
57 | write( 2 , MSG , sizeof(MSG) ); | |
58 | froms = 0; | |
59 | tos = 0; | |
60 | return; | |
61 | } | |
387d0540 | 62 | tos[0].link = 0; |
3a2b18f4 PK |
63 | /* |
64 | * tolimit is what mcount checks to see if | |
65 | * all the data structures are ready!!! | |
66 | * make sure it won't overflow. | |
67 | */ | |
4dff44be | 68 | tolimit = limit; |
ee56ba6f | 69 | monitor( lowpc , highpc , buffer , monsize , tolimit ); |
50084e08 PK |
70 | } |
71 | ||
72 | _mcleanup() | |
73 | { | |
bb9c5045 KM |
74 | int fd; |
75 | int fromindex; | |
76 | char *frompc; | |
77 | int toindex; | |
78 | struct rawarc rawarc; | |
50084e08 | 79 | |
bb9c5045 KM |
80 | fd = creat( "gmon.out" , 0666 ); |
81 | if ( fd < 0 ) { | |
387d0540 | 82 | perror( "mcount: gmon.out" ); |
50084e08 PK |
83 | return; |
84 | } | |
387d0540 PK |
85 | # ifdef DEBUG |
86 | fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz ); | |
87 | # endif DEBUG | |
bb9c5045 | 88 | write( fd , sbuf , ssiz ); |
3a2b18f4 | 89 | for ( fromindex = 0 ; fromindex < s_textsize>>1 ; fromindex++ ) { |
50084e08 PK |
90 | if ( froms[fromindex] == 0 ) { |
91 | continue; | |
92 | } | |
93 | frompc = s_lowpc + (fromindex<<1); | |
94 | for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) { | |
95 | # ifdef DEBUG | |
22f3ec41 PK |
96 | fprintf( stderr , |
97 | "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" , | |
50084e08 PK |
98 | frompc , tos[toindex].selfpc , tos[toindex].count ); |
99 | # endif DEBUG | |
bb9c5045 KM |
100 | rawarc.raw_frompc = (unsigned long) frompc; |
101 | rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc; | |
102 | rawarc.raw_count = tos[toindex].count; | |
103 | write( fd , &rawarc , sizeof rawarc ); | |
50084e08 PK |
104 | } |
105 | } | |
bb9c5045 | 106 | close( fd ); |
50084e08 PK |
107 | } |
108 | ||
387d0540 PK |
109 | /* |
110 | * This routine is massaged so that it may be jsb'ed to | |
111 | */ | |
50084e08 PK |
112 | asm("#define _mcount mcount"); |
113 | mcount() | |
114 | { | |
115 | register char *selfpc; /* r11 */ | |
116 | register unsigned short *frompcindex; /* r10 */ | |
117 | register struct tostruct *top; /* r9 */ | |
785a53a1 | 118 | static int profiling = 0; |
50084e08 | 119 | |
bb9c5045 | 120 | asm( " forgot to run ex script on gcrt0.s" ); |
50084e08 PK |
121 | asm( "#define r11 r5" ); |
122 | asm( "#define r10 r4" ); | |
123 | asm( "#define r9 r3" ); | |
124 | #ifdef lint | |
125 | selfpc = (char *) 0; | |
126 | frompcindex = 0; | |
127 | #else not lint | |
128 | /* | |
785a53a1 PK |
129 | * find the return address for mcount, |
130 | * and the return address for mcount's caller. | |
50084e08 PK |
131 | */ |
132 | asm(" movl (sp), r11"); /* selfpc = ... (jsb frame) */ | |
133 | asm(" movl 16(fp), r10"); /* frompcindex = (calls frame) */ | |
134 | #endif not lint | |
785a53a1 PK |
135 | /* |
136 | * check that we are profiling | |
387d0540 | 137 | * and that we aren't recursively invoked. |
785a53a1 | 138 | */ |
3a2b18f4 | 139 | if ( tolimit == 0 ) { |
387d0540 PK |
140 | goto out; |
141 | } | |
142 | if ( profiling ) { | |
50084e08 PK |
143 | goto out; |
144 | } | |
785a53a1 PK |
145 | profiling = 1; |
146 | /* | |
147 | * check that frompcindex is a reasonable pc value. | |
148 | * for example: signal catchers get called from the stack, | |
149 | * not from text space. too bad. | |
150 | */ | |
3a2b18f4 PK |
151 | frompcindex = (unsigned short *) ( (long) frompcindex - (long) s_lowpc ); |
152 | if ( (unsigned long) frompcindex > s_textsize ) { | |
785a53a1 PK |
153 | goto done; |
154 | } | |
3a2b18f4 | 155 | frompcindex = &froms[ ( (long) frompcindex ) >> 1 ]; |
50084e08 PK |
156 | if ( *frompcindex == 0 ) { |
157 | *frompcindex = ++tos[0].link; | |
158 | if ( *frompcindex >= tolimit ) { | |
159 | goto overflow; | |
160 | } | |
161 | top = &tos[ *frompcindex ]; | |
162 | top->selfpc = selfpc; | |
163 | top->count = 0; | |
164 | top->link = 0; | |
165 | } else { | |
166 | top = &tos[ *frompcindex ]; | |
167 | } | |
785a53a1 | 168 | for ( ; /* goto done */ ; top = &tos[ top -> link ] ) { |
50084e08 PK |
169 | if ( top -> selfpc == selfpc ) { |
170 | top -> count++; | |
785a53a1 | 171 | goto done; |
50084e08 PK |
172 | } |
173 | if ( top -> link == 0 ) { | |
174 | top -> link = ++tos[0].link; | |
175 | if ( top -> link >= tolimit ) | |
176 | goto overflow; | |
177 | top = &tos[ top -> link ]; | |
178 | top -> selfpc = selfpc; | |
179 | top -> count = 1; | |
180 | top -> link = 0; | |
785a53a1 | 181 | goto done; |
50084e08 PK |
182 | } |
183 | } | |
785a53a1 PK |
184 | done: |
185 | profiling = 0; | |
186 | /* and fall through */ | |
50084e08 PK |
187 | out: |
188 | asm( " rsb" ); | |
189 | asm( "#undef r11" ); | |
190 | asm( "#undef r10" ); | |
191 | asm( "#undef r9" ); | |
192 | asm( "#undef _mcount"); | |
193 | ||
194 | overflow: | |
3a2b18f4 | 195 | tolimit = 0; |
50084e08 PK |
196 | # define TOLIMIT "mcount: tos overflow\n" |
197 | write( 2 , TOLIMIT , sizeof( TOLIMIT ) ); | |
50084e08 PK |
198 | goto out; |
199 | } | |
200 | ||
ee56ba6f KM |
201 | /*VARARGS1*/ |
202 | monitor( lowpc , highpc , buf , bufsiz , nfunc ) | |
387d0540 | 203 | char *lowpc; |
387d0540 PK |
204 | char *highpc; |
205 | int *buf, bufsiz; | |
ee56ba6f | 206 | int nfunc; /* not used, available for compatability only */ |
50084e08 | 207 | { |
387d0540 | 208 | register o; |
50084e08 | 209 | |
387d0540 PK |
210 | if ( lowpc == 0 ) { |
211 | profil( (char *) 0 , 0 , 0 , 0 ); | |
ee56ba6f | 212 | _mcleanup(); |
387d0540 PK |
213 | return; |
214 | } | |
215 | sbuf = buf; | |
216 | ssiz = bufsiz; | |
217 | ( (struct phdr *) buf ) -> lpc = lowpc; | |
218 | ( (struct phdr *) buf ) -> hpc = highpc; | |
219 | ( (struct phdr *) buf ) -> ncnt = ssiz; | |
220 | o = sizeof(struct phdr); | |
221 | buf = (int *) ( ( (int) buf ) + o ); | |
222 | bufsiz -= o; | |
223 | if ( bufsiz <= 0 ) | |
224 | return; | |
ef7f2ecf | 225 | o = ( ( (char *) highpc - (char *) lowpc) ); |
387d0540 | 226 | if( bufsiz < o ) |
ef7f2ecf | 227 | o = ( (float) bufsiz / o ) * 65536; |
387d0540 | 228 | else |
ef7f2ecf | 229 | o = 65536; |
387d0540 | 230 | profil( buf , bufsiz , lowpc , o ); |
50084e08 | 231 | } |
0bbf4774 KM |
232 | |
233 | /* | |
234 | * This is a stub for the "brk" system call, which we want to | |
63238688 KM |
235 | * catch so that it will not deallocate our data space. |
236 | * (of which the program is not aware) | |
0bbf4774 | 237 | */ |
63238688 KM |
238 | asm("#define _curbrk curbrk"); |
239 | extern char *curbrk; | |
240 | ||
0bbf4774 | 241 | brk(addr) |
63238688 | 242 | char *addr; |
0bbf4774 | 243 | { |
63238688 KM |
244 | |
245 | if (addr < minsbrk) | |
246 | addr = minsbrk; | |
247 | asm(" chmk $17"); | |
ee56ba6f KM |
248 | asm(" jcc 1f"); |
249 | asm(" jmp cerror"); | |
250 | asm("1:"); | |
63238688 KM |
251 | curbrk = addr; |
252 | return (0); | |
0bbf4774 | 253 | } |