OpenCores
URL https://opencores.org/ocsvn/openrisc_me/openrisc_me/trunk

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [config/] [i386/] [gmon-sol2.c] - Blame information for rev 327

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 282 jeremybenn
/*-
2
 * Copyright (c) 1991 The Regents of the University of California.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 3. [rescinded 22 July 1999]
14
 * 4. Neither the name of the University nor the names of its contributors
15
 *    may be used to endorse or promote products derived from this software
16
 *    without specific prior written permission.
17
 *
18
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28
 * SUCH DAMAGE.
29
 */
30
 
31
/*
32
 * This is a modified gmon.c by J.W.Hawtin <oolon@ankh.org>,
33
 * 14/8/96 based on the original gmon.c in GCC and the hacked version
34
 * solaris 2 sparc version (config/sparc/gmon-sol.c) by Mark Eichin. To do
35
 * process profiling on solaris 2.X X86
36
 *
37
 * It must be used in conjunction with sol2-gc1.asm, which is used to start
38
 * and stop process monitoring.
39
 *
40
 * Differences.
41
 *
42
 * On Solaris 2 _mcount is called by library functions not mcount, so support
43
 * has been added for both.
44
 *
45
 * Also the prototype for profil() is different
46
 *
47
 * Solaris 2 does not seem to have char *minbrk whcih allows the setting of
48
 * the minimum SBRK region so this code has been removed and lets pray malloc
49
 * does not mess it up.
50
 *
51
 * Notes
52
 *
53
 * This code could easily be integrated with the original gmon.c and perhaps
54
 * should be.
55
 */
56
#include "tconfig.h"
57
#include "tsystem.h"
58
#include <fcntl.h> /* for creat() */
59
 
60
#ifdef DEBUG
61
#include <stdio.h>
62
#endif
63
 
64
static void moncontrol (int);
65
extern void monstartup (char *, char *);
66
extern void _mcleanup (void);
67
extern void internal_mcount (
68
#ifdef __x86_64__
69
                             char *, unsigned short *
70
#else
71
                             void
72
#endif
73
                             );
74
 
75
 
76
struct phdr {
77
                char    *lpc;
78
                char    *hpc;
79
                int     ncnt;
80
};
81
 
82
 
83
#define HISTFRACTION 2
84
#define HISTCOUNTER unsigned short
85
#define HASHFRACTION 1
86
#define ARCDENSITY 2
87
#define MINARCS 50
88
#define BASEADDRESS 0x8000000 /* On Solaris 2 X86 all executables start here
89
                                 and not at 0 */
90
 
91
struct tostruct {
92
  char *selfpc;
93
  long count;
94
  unsigned short link;
95
};
96
 
97
struct rawarc {
98
    unsigned long       raw_frompc;
99
    unsigned long       raw_selfpc;
100
    long                raw_count;
101
};
102
#define ROUNDDOWN(x,y)  (((x)/(y))*(y))
103
#define ROUNDUP(x,y)    ((((x)+(y)-1)/(y))*(y))
104
 
105
/* char *minbrk; */
106
 
107
typedef __SIZE_TYPE__ size_t;
108
typedef __PTRDIFF_TYPE__ intptr_t;
109
 
110
    /*
111
     *  froms is actually a bunch of unsigned shorts indexing tos
112
     */
113
static int              profiling = 3;
114
static unsigned short   *froms;
115
static struct tostruct  *tos = 0;
116
static long             tolimit = 0;
117
static char             *s_lowpc = 0;
118
static char             *s_highpc = 0;
119
static size_t           s_textsize = 0;
120
 
121
static int      ssiz;
122
static char     *sbuf;
123
static int      s_scale;
124
    /* see profil(2) where this is describe (incorrectly) */
125
#define         SCALE_1_TO_1    0x10000L
126
 
127
#define MSG "No space for profiling buffer(s)\n"
128
 
129
extern int errno;
130
 
131
extern void *sbrk (intptr_t);
132
 
133
void
134
monstartup(char *lowpc, char *highpc)
135
{
136
    size_t              monsize;
137
    char                *buffer;
138
    register size_t     o;
139
 
140
        /*
141
         *      round lowpc and highpc to multiples of the density we're using
142
         *      so the rest of the scaling (here and in gprof) stays in ints.
143
         */
144
    lowpc = (char *)
145
            ROUNDDOWN((size_t)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
146
    s_lowpc = lowpc;
147
    highpc = (char *)
148
            ROUNDUP((size_t)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
149
    s_highpc = highpc;
150
    s_textsize = highpc - lowpc;
151
    monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
152
    buffer = (char *) sbrk( monsize );
153
    if ( buffer == (char *) -1 ) {
154
        write( 2 , MSG , sizeof(MSG) );
155
        return;
156
    }
157
    froms = (unsigned short *) sbrk( s_textsize / HASHFRACTION );
158
    if ( froms == (unsigned short *) -1 ) {
159
        write( 2 , MSG , sizeof(MSG) );
160
        froms = 0;
161
        return;
162
    }
163
    tolimit = s_textsize * ARCDENSITY / 100;
164
    if ( tolimit < MINARCS ) {
165
        tolimit = MINARCS;
166
    } else if ( tolimit > 65534 ) {
167
        tolimit = 65534;
168
    }
169
    tos = (struct tostruct *) sbrk( tolimit * sizeof( struct tostruct ) );
170
    if ( tos == (struct tostruct *) -1 ) {
171
        write( 2 , MSG , sizeof(MSG) );
172
        froms = 0;
173
        tos = 0;
174
        return;
175
    }
176
/*    minbrk = (char *) sbrk(0);*/
177
    tos[0].link = 0;
178
    sbuf = buffer;
179
    ssiz = monsize;
180
    ( (struct phdr *) buffer ) -> lpc = lowpc;
181
    ( (struct phdr *) buffer ) -> hpc = highpc;
182
    ( (struct phdr *) buffer ) -> ncnt = ssiz;
183
    monsize -= sizeof(struct phdr);
184
    if ( monsize <= 0 )
185
        return;
186
    o = highpc - lowpc;
187
    if( monsize < o )
188
#ifndef hp300
189
        s_scale = ( (float) monsize / o ) * SCALE_1_TO_1;
190
#else /* avoid floating point */
191
    {
192
        int quot = o / monsize;
193
 
194
        if (quot >= 0x10000)
195
                s_scale = 1;
196
        else if (quot >= 0x100)
197
                s_scale = 0x10000 / quot;
198
        else if (o >= 0x800000)
199
                s_scale = 0x1000000 / (o / (monsize >> 8));
200
        else
201
                s_scale = 0x1000000 / ((o << 8) / monsize);
202
    }
203
#endif
204
    else
205
        s_scale = SCALE_1_TO_1;
206
    moncontrol(1);
207
}
208
 
209
void
210
_mcleanup (void)
211
{
212
    int                 fd;
213
    int                 fromindex;
214
    int                 endfrom;
215
    char                *frompc;
216
    int                 toindex;
217
    struct rawarc       rawarc;
218
 
219
    moncontrol(0);
220
    fd = creat( "gmon.out" , 0666 );
221
    if ( fd < 0 ) {
222
        perror( "mcount: gmon.out" );
223
        return;
224
    }
225
#   ifdef DEBUG
226
        fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
227
#   endif /* DEBUG */
228
 
229
    write( fd , sbuf , ssiz );
230
    endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
231
    for ( fromindex = 0 ; fromindex < endfrom ; fromindex++ ) {
232
        if ( froms[fromindex] == 0 ) {
233
            continue;
234
        }
235
        frompc = s_lowpc + (fromindex * HASHFRACTION * sizeof(*froms));
236
        for (toindex=froms[fromindex]; toindex!=0; toindex=tos[toindex].link) {
237
#           ifdef DEBUG
238
                fprintf( stderr ,
239
                        "[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
240
                        frompc , tos[toindex].selfpc , tos[toindex].count );
241
#           endif /* DEBUG */
242
            rawarc.raw_frompc = (unsigned long) frompc;
243
            rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
244
            rawarc.raw_count = tos[toindex].count;
245
            write( fd , &rawarc , sizeof rawarc );
246
        }
247
    }
248
    close( fd );
249
}
250
 
251
#ifdef __x86_64__
252
/* See GLIBC for additional information about this technique.  */
253
asm(".globl _mcount\n"
254
    "\t.type\t_mcount, @function\n"
255
    "_mcount:\n"
256
    /* The compiler calls _mcount after the prologue, and does not
257
       save any of the registers.  Therefore we must preserve all
258
       seven registers which may contain function arguments.  */
259
    "\tsubq\t$0x38,%rsp\n"
260
    "\tmovq\t%rax,(%rsp)\n"
261
    "\tmovq\t%rcx,0x08(%rsp)\n"
262
    "\tmovq\t%rdx,0x10(%rsp)\n"
263
    "\tmovq\t%rsi,0x18(%rsp)\n"
264
    "\tmovq\t%rdi,0x20(%rsp)\n"
265
    "\tmovq\t%r8,0x28(%rsp)\n"
266
    "\tmovq\t%r9,0x30(%rsp)\n"
267
    /* Get SELFPC (pushed by the call to this function) and
268
       FROMPCINDEX (via the frame pointer.  */
269
    "\tmovq\t0x38(%rsp),%rdi\n"
270
    "\tmovq\t0x8(%rbp),%rsi\n"
271
    "\tcall\tinternal_mcount\n"
272
    /* Restore the saved registers.  */
273
    "\tmovq\t0x30(%rsp),%r9\n"
274
    "\tmovq\t0x28(%rsp),%r8\n"
275
    "\tmovq\t0x20(%rsp),%rdi\n"
276
    "\tmovq\t0x18(%rsp),%rsi\n"
277
    "\tmovq\t0x10(%rsp),%rdx\n"
278
    "\tmovq\t0x08(%rsp),%rcx\n"
279
    "\tmovq\t(%rsp),%rax\n"
280
    "\taddq\t$0x38,%rsp\n"
281
    "\tretq\n"
282
    );
283
#else
284
/* Solaris 2 libraries use _mcount.  */
285
asm(".globl _mcount; _mcount: jmp internal_mcount");
286
/* This is for compatibility with old versions of gcc which used mcount.  */
287
asm(".globl mcount; mcount: jmp internal_mcount");
288
#endif
289
 
290
void
291
internal_mcount (
292
#ifdef __x86_64__
293
                 char *selfpc,
294
                 unsigned short *frompcindex
295
#else
296
                 void
297
#endif
298
                 )
299
{
300
#ifndef __x86_64__
301
        register char                   *selfpc;
302
        register unsigned short         *frompcindex;
303
#endif
304
        register struct tostruct        *top;
305
        register struct tostruct        *prevtop;
306
        register long                   toindex;
307
        static char already_setup;
308
 
309
#ifndef __x86_64__
310
        /*
311
         *      find the return address for mcount,
312
         *      and the return address for mcount's caller.
313
         */
314
 
315
        /* selfpc = pc pushed by mcount call.
316
           This identifies the function that was just entered.  */
317
        selfpc = (void *) __builtin_return_address (0);
318
        /* frompcindex = pc in preceding frame.
319
           This identifies the caller of the function just entered.  */
320
        frompcindex = (void *) __builtin_return_address (1);
321
#endif
322
 
323
        if(!already_setup) {
324
          extern char etext[];
325
          already_setup = 1;
326
#ifdef __x86_64__
327
          monstartup(0, etext);
328
#else
329
          monstartup((char*)0x08040000, etext);
330
#endif
331
#ifdef USE_ONEXIT
332
          on_exit(_mcleanup, 0);
333
#else
334
          atexit(_mcleanup);
335
#endif
336
        }
337
        /*
338
         *      check that we are profiling
339
         *      and that we aren't recursively invoked.
340
         */
341
        if (profiling) {
342
                goto out;
343
        }
344
        profiling++;
345
        /*
346
         *      check that frompcindex is a reasonable pc value.
347
         *      for example:    signal catchers get called from the stack,
348
         *                      not from text space.  too bad.
349
         */
350
        frompcindex = (unsigned short *)((long)frompcindex - (long)s_lowpc);
351
        if ((unsigned long)frompcindex > s_textsize) {
352
                goto done;
353
        }
354
        frompcindex =
355
            &froms[((long)frompcindex) / (HASHFRACTION * sizeof(*froms))];
356
        toindex = *frompcindex;
357
        if (toindex == 0) {
358
                /*
359
                 *      first time traversing this arc
360
                 */
361
                toindex = ++tos[0].link;
362
                if (toindex >= tolimit) {
363
                        goto overflow;
364
                }
365
                *frompcindex = toindex;
366
                top = &tos[toindex];
367
                top->selfpc = selfpc;
368
                top->count = 1;
369
                top->link = 0;
370
                goto done;
371
        }
372
        top = &tos[toindex];
373
        if (top->selfpc == selfpc) {
374
                /*
375
                 *      arc at front of chain; usual case.
376
                 */
377
                top->count++;
378
                goto done;
379
        }
380
        /*
381
         *      have to go looking down chain for it.
382
         *      top points to what we are looking at,
383
         *      prevtop points to previous top.
384
         *      we know it is not at the head of the chain.
385
         */
386
        for (; /* goto done */; ) {
387
                if (top->link == 0) {
388
                        /*
389
                         *      top is end of the chain and none of the chain
390
                         *      had top->selfpc == selfpc.
391
                         *      so we allocate a new tostruct
392
                         *      and link it to the head of the chain.
393
                         */
394
                        toindex = ++tos[0].link;
395
                        if (toindex >= tolimit) {
396
                                goto overflow;
397
                        }
398
                        top = &tos[toindex];
399
                        top->selfpc = selfpc;
400
                        top->count = 1;
401
                        top->link = *frompcindex;
402
                        *frompcindex = toindex;
403
                        goto done;
404
                }
405
                /*
406
                 *      otherwise, check the next arc on the chain.
407
                 */
408
                prevtop = top;
409
                top = &tos[top->link];
410
                if (top->selfpc == selfpc) {
411
                        /*
412
                         *      there it is.
413
                         *      increment its count
414
                         *      move it to the head of the chain.
415
                         */
416
                        top->count++;
417
                        toindex = prevtop->link;
418
                        prevtop->link = top->link;
419
                        top->link = *frompcindex;
420
                        *frompcindex = toindex;
421
                        goto done;
422
                }
423
 
424
        }
425
done:
426
        profiling--;
427
        /* and fall through */
428
out:
429
        return;         /* normal return restores saved registers */
430
 
431
overflow:
432
        profiling++; /* halt further profiling */
433
#   define      TOLIMIT "mcount: tos overflow\n"
434
        write(2, TOLIMIT, sizeof(TOLIMIT));
435
        goto out;
436
}
437
 
438
/*
439
 * Control profiling
440
 *      profiling is what mcount checks to see if
441
 *      all the data structures are ready.
442
 */
443
static void
444
moncontrol(int mode)
445
{
446
    if (mode)
447
    {
448
      /* start */
449
      profil((unsigned short *)(sbuf + sizeof(struct phdr)),
450
             ssiz - sizeof(struct phdr),
451
             (size_t)s_lowpc, s_scale);
452
 
453
      profiling = 0;
454
    } else {
455
      /* stop */
456
      profil((unsigned short *)0, 0, 0, 0);
457
      profiling = 3;
458
    }
459
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.