diff options
author | Eric Andersen <andersen@codepoet.org> | 2004-08-21 21:19:29 +0000 |
---|---|---|
committer | Eric Andersen <andersen@codepoet.org> | 2004-08-21 21:19:29 +0000 |
commit | 6e112da93a731085ff9b07f0804395bb3866925a (patch) | |
tree | 63320d9f5200bb3892ccfbcc55be84a5da535023 /libc | |
parent | e50f6d1c15483fc17323ecdd427f4a84c018f3af (diff) |
Kill off all support for 'gcc -pg' / 'gprof' style profiling. There is both a
size and performance penalty to profiling applications this way, as well as
Heisenberg effects, where the act of measuring changes what is measured.
There are better tools for doing profiling, such as OProfile, that do not
require gcc to instrument the application code.
-Erik
Diffstat (limited to 'libc')
33 files changed, 11 insertions, 1476 deletions
diff --git a/libc/sysdeps/linux/alpha/__longjmp.S b/libc/sysdeps/linux/alpha/__longjmp.S index 2db4e22e9..b78489f53 100644 --- a/libc/sysdeps/linux/alpha/__longjmp.S +++ b/libc/sysdeps/linux/alpha/__longjmp.S @@ -29,16 +29,7 @@ __longjmp: .frame $30 , 0, $26 -#ifdef PROF - ldgp gp, 0(pv) - .set noat - lda AT, _mcount - jsr AT, (AT), _mcount - .set at - .prologue 1 -#else .prologue 0 -#endif mov $17, $0 ldq $9, JB_S0*8(a0) diff --git a/libc/sysdeps/linux/alpha/bits/machine-gmon.h b/libc/sysdeps/linux/alpha/bits/machine-gmon.h deleted file mode 100644 index 5f5522c0b..000000000 --- a/libc/sysdeps/linux/alpha/bits/machine-gmon.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Machine-specific calling sequence for `mcount' profiling function. alpha - Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#define _MCOUNT_DECL(from, self) \ - void __mcount (u_long from, u_long self) - -/* Call __mcount with our the return PC for our caller, and the return - PC our caller will return to. Empty since we use an assembly stub - instead. */ -#define MCOUNT diff --git a/libc/sysdeps/linux/alpha/brk.S b/libc/sysdeps/linux/alpha/brk.S index 8c70a0ce5..4e15518d2 100644 --- a/libc/sysdeps/linux/alpha/brk.S +++ b/libc/sysdeps/linux/alpha/brk.S @@ -46,12 +46,6 @@ __brk: .frame $30 , 8 , $26 ldgp $29, 0($27) subq $30, 8, $30 -#ifdef PROF - .set noat - lda AT, _mcount - jsr AT, (AT), _mcount - .set at -#endif .prologue 1 /* Save the requested brk across the system call. */ diff --git a/libc/sysdeps/linux/alpha/clone.S b/libc/sysdeps/linux/alpha/clone.S index b17a5ec68..396816184 100644 --- a/libc/sysdeps/linux/alpha/clone.S +++ b/libc/sysdeps/linux/alpha/clone.S @@ -44,16 +44,7 @@ __clone: .frame $30 , 0, $26 -#ifdef PROF - ldgp gp,0(pv) - .set noat - lda AT, _mcount - jsr AT, (AT), _mcount - .set at - .prologue 1 -#else .prologue 0 -#endif /* Sanity check arguments. */ ldiq v0,EINVAL @@ -78,10 +69,8 @@ __clone: /* Something bad happened -- no child created */ $error: -#ifndef PROF br gp,1f 1: ldgp gp,0(gp) -#endif jmp zero,__syscall_error .end __clone diff --git a/libc/sysdeps/linux/alpha/divrem.h b/libc/sysdeps/linux/alpha/divrem.h index d22759e40..ca3db4b49 100644 --- a/libc/sysdeps/linux/alpha/divrem.h +++ b/libc/sysdeps/linux/alpha/divrem.h @@ -130,22 +130,6 @@ UFUNC_NAME: lda sp, -STACK(sp) .frame sp, STACK, retaddr, 0 -#ifdef PROF - stq ra, 0(sp) - stq pv, 8(sp) - stq gp, 16(sp) - - br AT, 1f -1: ldgp gp, 0(AT) - - mov retaddr, ra - lda AT, _mcount - jsr AT, (AT), _mcount - - ldq ra, 0(sp) - ldq pv, 8(sp) - ldq gp, 16(sp) -#endif .prologue 0 $udiv: @@ -216,21 +200,6 @@ $divbyzero: SFUNC_NAME: lda sp, -STACK(sp) .frame sp, STACK, retaddr, 0 -#ifdef PROF - stq ra, 0(sp) - stq pv, 8(sp) - stq gp, 16(sp) - - br AT, 1f -1: ldgp gp, 0(AT) - - mov retaddr, ra - jsr AT, _mcount - - ldq ra, 0(sp) - ldq pv, 8(sp) - ldq gp, 16(sp) -#endif .prologue 0 or arg1, arg2, AT diff --git a/libc/sysdeps/linux/alpha/setjmp.S b/libc/sysdeps/linux/alpha/setjmp.S index 69649eeab..105cc8292 100644 --- a/libc/sysdeps/linux/alpha/setjmp.S +++ b/libc/sysdeps/linux/alpha/setjmp.S @@ -34,12 +34,6 @@ $sigsetjmp_local: .frame $26, 16, $26, 0 stq $26, 0($30) .mask 0x04000000, -16 -#ifdef PROF - .set noat - lda AT, _mcount - jsr AT, (AT), _mcount - .set at -#endif .prologue 1 stq $9, JB_S0*8(a0) diff --git a/libc/sysdeps/linux/arm/Makefile b/libc/sysdeps/linux/arm/Makefile index f2582e1a8..6a80686a7 100644 --- a/libc/sysdeps/linux/arm/Makefile +++ b/libc/sysdeps/linux/arm/Makefile @@ -21,7 +21,7 @@ include $(TOPDIR)Rules.mak ASFLAGS=$(CFLAGS) CRT0_SRC = crt0.S -CRT0_OBJ = crt0.o crt1.o gcrt1.o +CRT0_OBJ = crt0.o crt1.o CRT0_DEPS=gmon-start.S CTOR_TARGETS=$(TOPDIR)lib/crti.o $(TOPDIR)lib/crtn.o @@ -54,12 +54,6 @@ $(COBJS): %.o : %.c $(CC) $(CFLAGS) -c $< -o $@ $(STRIPTOOL) -x -R .note -R .comment $*.o -ifeq ($(strip $(UCLIBC_PROFILING)),y) -gmon-start.S: ../common/gmon-start.c - $(CC) $(CFLAGS) -c $< -S -o $*.S -gcrt1.o: $(CRT0_DEPS) -endif - ifeq ($(strip $(UCLIBC_CTOR_DTOR)),y) crti.o: crti.S $(CC) $(CFLAGS) -c crti.S -o crti.o diff --git a/libc/sysdeps/linux/arm/bits/machine-gmon.h b/libc/sysdeps/linux/arm/bits/machine-gmon.h deleted file mode 100644 index 039dfd951..000000000 --- a/libc/sysdeps/linux/arm/bits/machine-gmon.h +++ /dev/null @@ -1,67 +0,0 @@ -/* Machine-dependent definitions for profiling support. ARM version. - Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* GCC for the ARM cannot compile __builtin_return_address(N) for N != 0, - so we must use an assembly stub. */ - -#include <sysdep.h> -#ifndef NO_UNDERSCORES -/* The asm symbols for C functions are `_function'. - The canonical name for the counter function is `mcount', no _. */ -void _mcount (void) asm ("mcount"); -#else -/* The canonical name for the function is `_mcount' in both C and asm, - but some old asm code might assume it's `mcount'. */ -void _mcount (void); -weak_alias (_mcount, mcount) -#endif - -static void mcount_internal (u_long frompc, u_long selfpc); - -#define _MCOUNT_DECL(frompc, selfpc) \ -static void mcount_internal (u_long frompc, u_long selfpc) - -/* This macro/func MUST save r0, r1 because the compiler inserts - blind calls to _mount(), ignoring the fact that _mcount may - clobber registers; therefore, _mcount may NOT clobber registers */ -/* if (this_fp!=0) { - r0 = this_fp - r1 = this_lr - r1 = [r1-4] which is caller's lr - if (r1!=0) - r1 = caller's lr - call mcount_internal(this_lr, caller's_lr) - } -*/ - -#define MCOUNT \ -void _mcount (void) \ -{ \ - __asm__("stmdb sp!, {r0, r1, r2, r3};" \ - "movs fp, fp;" \ - "moveq r1, #0;" \ - "ldrne r1, [fp, $-4];" \ - "ldrne r0, [fp, $-12];" \ - "movnes r0, r0;" \ - "ldrne r0, [r0, $-4];" \ - "movs r0, r0;" \ - "blne mcount_internal;" \ - "ldmia sp!, {r0, r1, r2, r3}"); \ -} - diff --git a/libc/sysdeps/linux/arm/crt0.S b/libc/sysdeps/linux/arm/crt0.S index 6704a81e2..455d35d2d 100644 --- a/libc/sysdeps/linux/arm/crt0.S +++ b/libc/sysdeps/linux/arm/crt0.S @@ -92,7 +92,7 @@ _start: ldr r2,[sp, #8] #endif -#if (defined L_crt1 || defined L_gcrt1 ) && defined __UCLIBC_CTOR_DTOR__ +#if (defined L_crt1 ) && defined __UCLIBC_CTOR_DTOR__ /* Store the address of _init in r3 as an argument to main() */ ldr r3, =_init @@ -123,11 +123,6 @@ _start: .long 2,0,0 3: .align 4 -#if defined L_gcrt1 && defined __UCLIBC_PROFILING__ -# include "./gmon-start.S" -#endif - - /* Define a symbol for the first piece of initialized data. */ .data .globl __data_start diff --git a/libc/sysdeps/linux/common/Makefile b/libc/sysdeps/linux/common/Makefile index 1256e2376..1930351fb 100644 --- a/libc/sysdeps/linux/common/Makefile +++ b/libc/sysdeps/linux/common/Makefile @@ -57,9 +57,6 @@ CSRC= __rt_sigtimedwait.c __socketcall.c __syscall_fcntl.c \ ifneq ($(strip $(EXCLUDE_BRK)),y) CSRC+=sbrk.c endif -ifeq ($(strip $(UCLIBC_PROFILING)),y) -CSRC+=gmon.c -endif ifeq ($(strip $(UCLIBC_PROPOLICE)),y) CSRC+=ssp.c endif diff --git a/libc/sysdeps/linux/common/bits/dlfcn.h b/libc/sysdeps/linux/common/bits/dlfcn.h index e96b5c17a..75122a98a 100644 --- a/libc/sysdeps/linux/common/bits/dlfcn.h +++ b/libc/sysdeps/linux/common/bits/dlfcn.h @@ -40,25 +40,3 @@ /* Do not delete object when closed. */ #define RTLD_NODELETE 0x01000 -#ifdef __USE_GNU -/* To support profiling of shared objects it is a good idea to call - the function found using `dlsym' using the following macro since - these calls do not use the PLT. But this would mean the dynamic - loader has no chance to find out when the function is called. The - macro applies the necessary magic so that profiling is possible. - Rewrite - foo = (*fctp) (arg1, arg2); - into - foo = DL_CALL_FCT (fctp, (arg1, arg2)); -*/ -# define DL_CALL_FCT(fctp, args) \ - (_dl_mcount_wrapper_check ((void *) (fctp)), (*(fctp)) args) - -__BEGIN_DECLS - -/* This function calls the profiling functions. */ -extern void _dl_mcount_wrapper_check (void *__selfpc) __THROW; - -__END_DECLS - -#endif diff --git a/libc/sysdeps/linux/common/bits/machine-gmon.h b/libc/sysdeps/linux/common/bits/machine-gmon.h deleted file mode 100644 index 7dd36308b..000000000 --- a/libc/sysdeps/linux/common/bits/machine-gmon.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Machine-dependent definitions for profiling support. Generic GCC 2 version. - Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -/* GCC version 2 gives us a perfect magical function to get - just the information we need: - void *__builtin_return_address (unsigned int N) - returns the return address of the frame N frames up. */ - -/* Be warned that GCC cannot usefully compile __builtin_return_address(N) - for N != 0 on all machines. In this case, you may have to write - your own version of _mcount(). */ - -#if __GNUC__ < 2 - #error "This file uses __builtin_return_address, a GCC 2 extension." -#endif - -#include <sysdep.h> -#ifndef NO_UNDERSCORES -/* The asm symbols for C functions are `_function'. - The canonical name for the counter function is `mcount', no _. */ -void _mcount (void) asm ("mcount"); -#else -/* The canonical name for the function is `_mcount' in both C and asm, - but some old asm code might assume it's `mcount'. */ -void _mcount (void); -weak_alias (_mcount, mcount) -#endif - -static void mcount_internal (u_long frompc, u_long selfpc); - -#define _MCOUNT_DECL(frompc, selfpc) \ -static inline void mcount_internal (u_long frompc, u_long selfpc) - -#ifndef RETURN_ADDRESS -#define RETURN_ADDRESS(n) __builtin_return_address(n) -#endif - -#define MCOUNT \ -void _mcount (void) \ -{ \ - mcount_internal ((u_long) RETURN_ADDRESS (1), (u_long) RETURN_ADDRESS (0)); \ -} diff --git a/libc/sysdeps/linux/common/gmon-start.c b/libc/sysdeps/linux/common/gmon-start.c deleted file mode 100644 index 6878a7a71..000000000 --- a/libc/sysdeps/linux/common/gmon-start.c +++ /dev/null @@ -1,58 +0,0 @@ -/* Code to enable profiling at program startup. - Copyright (C) 1995,1996,1997,2000,2001,2002 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include <features.h> -#include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/gmon.h> - -#ifdef __UCLIBC_PROFILING__ - -/* Beginning and end of our code segment. We cannot declare them - as the external functions since we want the addresses of those - labels. Taking the address of a function may have different - meanings on different platforms. */ - -extern void _start; -extern void etext; - - -void __gmon_start__ (void) -{ -#ifdef __UCLIBC_CTOR_DTOR__ - /* Protect from being called more than once. Since crti.o is linked - into every shared library, each of their init functions will call us. */ - static int called; - - if (called) - return; - - called = 1; -#endif - - /* Start keeping profiling records. */ - monstartup ((u_long) &_start, (u_long) &etext); - - /* Call _mcleanup before exiting; it will write out gmon.out from the - collected data. */ - atexit (&_mcleanup); -} -#endif - diff --git a/libc/sysdeps/linux/common/gmon.c b/libc/sysdeps/linux/common/gmon.c deleted file mode 100644 index a3444a28e..000000000 --- a/libc/sysdeps/linux/common/gmon.c +++ /dev/null @@ -1,640 +0,0 @@ -/*- - * Copyright (c) 1983, 1992, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include <features.h> -#include <sys/param.h> -#include <sys/time.h> -#include <sys/gmon.h> -#include <sys/gmon_out.h> -#include <sys/uio.h> - -#include <errno.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/types.h> - -#ifdef __UCLIBC_PROFILING__ - -/* Head of basic-block list or NULL. */ -struct __bb *__bb_head; - -struct gmonparam _gmonparam = { state: GMON_PROF_OFF }; - -/* - * See profil(2) where this is described: - */ -static int s_scale; -#define SCALE_1_TO_1 0x10000L - -#define ERR(s) write (STDERR_FILENO, s, sizeof (s) - 1) - -void moncontrol __P ((int mode)); -static void write_hist __P ((int fd)); -static void write_call_graph __P ((int fd)); -static void write_bb_counts __P ((int fd)); - -/* - * Control profiling - * profiling is what mcount checks to see if - * all the data structures are ready. - */ -void moncontrol (int mode) -{ - struct gmonparam *p = &_gmonparam; - - /* Don't change the state if we ran into an error. */ - if (p->state == GMON_PROF_ERROR) - return; - - if (mode) - { - /* start */ - profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale); - p->state = GMON_PROF_ON; - } - else - { - /* stop */ - profil(NULL, 0, 0, 0); - p->state = GMON_PROF_OFF; - } -} - - -void monstartup (u_long lowpc, u_long highpc) -{ - register int o; - char *cp; - struct gmonparam *p = &_gmonparam; - - /* - * round lowpc and highpc to multiples of the density we're using - * so the rest of the scaling (here and in gprof) stays in ints. - */ - p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER)); - p->textsize = p->highpc - p->lowpc; - p->kcountsize = p->textsize / HISTFRACTION; - p->hashfraction = HASHFRACTION; - p->log_hashfraction = -1; - /* The following test must be kept in sync with the corresponding - test in mcount.c. */ - if ((HASHFRACTION & (HASHFRACTION - 1)) == 0) { - /* if HASHFRACTION is a power of two, mcount can use shifting - instead of integer division. Precompute shift amount. */ - p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1; - } - p->fromssize = p->textsize / HASHFRACTION; - p->tolimit = p->textsize * ARCDENSITY / 100; - if (p->tolimit < MINARCS) - p->tolimit = MINARCS; - else if (p->tolimit > MAXARCS) - p->tolimit = MAXARCS; - p->tossize = p->tolimit * sizeof(struct tostruct); - - cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1); - if (! cp) - { - ERR("monstartup: out of memory\n"); - p->tos = NULL; - p->state = GMON_PROF_ERROR; - return; - } - p->tos = (struct tostruct *)cp; - cp += p->tossize; - p->kcount = (HISTCOUNTER *)cp; - cp += p->kcountsize; - p->froms = (ARCINDEX *)cp; - - p->tos[0].link = 0; - - o = p->highpc - p->lowpc; - if (p->kcountsize < (u_long) o) - { -#ifndef hp300 - s_scale = ((float)p->kcountsize / o ) * SCALE_1_TO_1; -#else - /* avoid floating point operations */ - int quot = o / p->kcountsize; - - if (quot >= 0x10000) - s_scale = 1; - else if (quot >= 0x100) - s_scale = 0x10000 / quot; - else if (o >= 0x800000) - s_scale = 0x1000000 / (o / (p->kcountsize >> 8)); - else - s_scale = 0x1000000 / ((o << 8) / p->kcountsize); -#endif - } else - s_scale = SCALE_1_TO_1; - - moncontrol(1); -} - - -/* Return frequency of ticks reported by profil. */ -static int profile_frequency (void) -{ - /* - * Discover the tick frequency of the machine if something goes wrong, - * we return 0, an impossible hertz. - */ - struct itimerval tim; - - tim.it_interval.tv_sec = 0; - tim.it_interval.tv_usec = 1; - tim.it_value.tv_sec = 0; - tim.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &tim, 0); - setitimer(ITIMER_REAL, 0, &tim); - if (tim.it_interval.tv_usec < 2) - return 0; - return (1000000 / tim.it_interval.tv_usec); -} - - -static void write_hist (int fd) -{ - u_char tag = GMON_TAG_TIME_HIST; - struct gmon_hist_hdr thdr __attribute__ ((aligned (__alignof__ (char *)))); - - if (_gmonparam.kcountsize > 0) - { - struct iovec iov[3] = - { - { &tag, sizeof (tag) }, - { &thdr, sizeof (struct gmon_hist_hdr) }, - { _gmonparam.kcount, _gmonparam.kcountsize } - }; - - *(char **) thdr.low_pc = (char *) _gmonparam.lowpc; - *(char **) thdr.high_pc = (char *) _gmonparam.highpc; - *(int32_t *) thdr.hist_size = (_gmonparam.kcountsize - / sizeof (HISTCOUNTER)); - *(int32_t *) thdr.prof_rate = profile_frequency (); - strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen)); - thdr.dimen_abbrev = 's'; - - writev (fd, iov, 3); - } -} - - -static void write_call_graph (int fd) -{ -#define NARCS_PER_WRITEV 32 - u_char tag = GMON_TAG_CG_ARC; - struct gmon_cg_arc_record raw_arc[NARCS_PER_WRITEV] - __attribute__ ((aligned (__alignof__ (char*)))); - ARCINDEX from_index, to_index, from_len; - u_long frompc; - struct iovec iov[2 * NARCS_PER_WRITEV]; - int nfilled; - - for (nfilled = 0; nfilled < NARCS_PER_WRITEV; ++nfilled) - { - iov[2 * nfilled].iov_base = &tag; - iov[2 * nfilled].iov_len = sizeof (tag); - - iov[2 * nfilled + 1].iov_base = &raw_arc[nfilled]; - iov[2 * nfilled + 1].iov_len = sizeof (struct gmon_cg_arc_record); - } - - nfilled = 0; - from_len = _gmonparam.fromssize / sizeof (*_gmonparam.froms); - for (from_index = 0; from_index < from_len; ++from_index) - { - if (_gmonparam.froms[from_index] == 0) - continue; - - frompc = _gmonparam.lowpc; - frompc += (from_index * _gmonparam.hashfraction - * sizeof (*_gmonparam.froms)); - for (to_index = _gmonparam.froms[from_index]; - to_index != 0; - to_index = _gmonparam.tos[to_index].link) - { - struct arc - { - char *frompc; - char *selfpc; - int32_t count; - } - arc; - - arc.frompc = (char *) frompc; - arc.selfpc = (char *) _gmonparam.tos[to_index].selfpc; - arc.count = _gmonparam.tos[to_index].count; - memcpy (raw_arc + nfilled, &arc, sizeof (raw_arc [0])); - - if (++nfilled == NARCS_PER_WRITEV) - { - writev (fd, iov, 2 * nfilled); - nfilled = 0; - } - } - } - if (nfilled > 0) - writev (fd, iov, 2 * nfilled); -} - - -static void write_bb_counts (int fd) -{ - struct __bb *grp; - u_char tag = GMON_TAG_BB_COUNT; - size_t ncounts; - size_t i; - - struct iovec bbhead[2] = - { - { &tag, sizeof (tag) }, - { &ncounts, sizeof (ncounts) } - }; - struct iovec bbbody[8]; - size_t nfilled; - - for (i = 0; i < (sizeof (bbbody) / sizeof (bbbody[0])); i += 2) - { - bbbody[i].iov_len = sizeof (grp->addresses[0]); - bbbody[i + 1].iov_len = sizeof (grp->counts[0]); - } - - /* Write each group of basic-block info (all basic-blocks in a - compilation unit form a single group). */ - - for (grp = __bb_head; grp; grp = grp->next) - { - ncounts = grp->ncounts; - writev (fd, bbhead, 2); - for (nfilled = i = 0; i < ncounts; ++i) - { - if (nfilled > (sizeof (bbbody) / sizeof (bbbody[0])) - 2) - { - writev (fd, bbbody, nfilled); - nfilled = 0; - } - - bbbody[nfilled++].iov_base = (char *) &grp->addresses[i]; - bbbody[nfilled++].iov_base = &grp->counts[i]; - } - if (nfilled > 0) - writev (fd, bbbody, nfilled); - } -} - - -static void write_gmon (void) -{ |