diff options
Diffstat (limited to 'gmon')
-rw-r--r-- | gmon/Makefile | 93 | ||||
-rw-r--r-- | gmon/bb_exit_func.c | 74 | ||||
-rw-r--r-- | gmon/bb_init_func.c | 53 | ||||
-rw-r--r-- | gmon/gmon.c | 80 | ||||
-rw-r--r-- | gmon/profil.c | 2 | ||||
-rw-r--r-- | gmon/sprofil.c | 2 | ||||
-rw-r--r-- | gmon/sys/gmon.h | 30 | ||||
-rw-r--r-- | gmon/sys/gmon_out.h | 2 | ||||
-rw-r--r-- | gmon/sys/profil.h | 2 | ||||
-rw-r--r-- | gmon/tst-gmon-gprof.sh | 60 | ||||
-rw-r--r-- | gmon/tst-gmon-pie.c | 1 | ||||
-rw-r--r-- | gmon/tst-gmon-static-gprof.sh | 62 | ||||
-rw-r--r-- | gmon/tst-gmon-static-pie.c | 1 | ||||
-rw-r--r-- | gmon/tst-gmon-static.c | 1 | ||||
-rw-r--r-- | gmon/tst-gmon.c | 50 | ||||
-rw-r--r-- | gmon/tst-sprofil.c | 2 |
16 files changed, 333 insertions, 182 deletions
diff --git a/gmon/Makefile b/gmon/Makefile index abb96d70d2..d94593c9d8 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1995-2016 Free Software Foundation, Inc. +# Copyright (C) 1995-2018 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 @@ -23,11 +23,9 @@ subdir := gmon include ../Makeconfig headers := sys/gmon.h sys/gmon_out.h sys/profil.h -routines := gmon mcount profil sprofil bb_init_func bb_exit_func prof-freq +routines := gmon mcount profil sprofil prof-freq -elide-routines.os = bb_init_func bb_exit_func - -tests = tst-sprofil +tests = tst-sprofil tst-gmon ifeq ($(build-profile),yes) tests += tst-profile-static tests-static += tst-profile-static @@ -35,9 +33,54 @@ tests-static += tst-profile-static LDFLAGS-tst-profile-static = -profile endif +tests += tst-gmon-static +tests-static += tst-gmon-static + +ifeq (yesyes,$(have-fpie)$(build-shared)) +tests += tst-gmon-pie +tests-pie += tst-gmon-pie +ifeq (yes,$(enable-static-pie)) +tests += tst-gmon-static-pie +tests-static += tst-gmon-static-pie +endif +endif + # The mcount code won't work without a frame pointer. CFLAGS-mcount.c := -fno-omit-frame-pointer +CFLAGS-tst-gmon.c := -fno-omit-frame-pointer -pg +tst-gmon-no-pie = yes +CRT-tst-gmon := $(csu-objpfx)gcrt1.o +tst-gmon-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-gprof.out +endif + +CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o +tst-gmon-static-no-pie = yes +tst-gmon-static-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-gprof.out +endif + +CFLAGS-tst-gmon-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-pie := $(csu-objpfx)gcrt1.o +tst-gmon-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-pie-gprof.out +endif + +ifeq (yes,$(enable-static-pie)) +CFLAGS-tst-gmon-static-pie.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg +CRT-tst-gmon-static-pie := $(csu-objpfx)grcrt1.o +tst-gmon-static-pie-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon-static-pie.data +ifeq ($(run-built-tests),yes) +tests-special += $(objpfx)tst-gmon-static-pie-gprof.out +endif +endif + + include ../Rules # We cannot compile mcount.c with -pg because that would @@ -45,7 +88,7 @@ include ../Rules # On systems where `profil' is not a system call, the same # problem exists for the internal functions in profil.c. -noprof := mcount +noprof := mcount $(sysdep_noprof) ifeq (,$(filter profil,$(unix-syscalls))) noprof += profil sprofil endif @@ -53,3 +96,41 @@ endif $(noprof:%=$(objpfx)%.op): %.op: %.o rm -f $@ ln $< $@ + +# GMON_OUTPUT_PREFIX only sets the output prefix. The actual file +# name contains the PID as well. +$(objpfx)tst-gmon.out: clean-tst-gmon-data +clean-tst-gmon-data: + rm -f $(objpfx)tst-gmon.data.* + +$(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \ + $(evaluate-test) + +$(objpfx)tst-gmon-static.out: clean-tst-gmon-static-data +clean-tst-gmon-static-data: + rm -f $(objpfx)tst-gmon-static.data.* + +$(objpfx)tst-gmon-static-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static \ + $(objpfx)tst-gmon-static.data.* > $@; \ + $(evaluate-test) + +$(objpfx)tst-gmon-pie.out: clean-tst-gmon-pie-data +clean-tst-gmon-pie-data: + rm -f $(objpfx)tst-gmon-pie.data.* + +$(objpfx)tst-gmon-pie-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-pie $(objpfx)tst-gmon-pie.data.* > $@; \ + $(evaluate-test) + +$(objpfx)tst-gmon-static-pie.out: clean-tst-gmon-static-pie-data +clean-tst-gmon-static-pie-data: + rm -f $(objpfx)tst-gmon-static-pie.data.* + +$(objpfx)tst-gmon-static-pie-gprof.out: tst-gmon-static-gprof.sh \ + $(objpfx)tst-gmon-static-pie.out + $(SHELL) $< $(GPROF) $(objpfx)tst-gmon-static-pie \ + $(objpfx)tst-gmon-static-pie.data.* > $@; \ + $(evaluate-test) diff --git a/gmon/bb_exit_func.c b/gmon/bb_exit_func.c deleted file mode 100644 index d9c91bc282..0000000000 --- a/gmon/bb_exit_func.c +++ /dev/null @@ -1,74 +0,0 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by David Mosberger (davidm@cs.arizona.edu). - - 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, see - <http://www.gnu.org/licenses/>. */ - -/* __bb_exit_func() dumps all the basic-block statistics linked into - the __bb_head chain to .d files. */ - -#include <sys/gmon.h> -#include <sys/gmon_out.h> -#include <sys/types.h> - -#include <stdio.h> -#include <stdio_ext.h> -#include <string.h> - -#define OUT_NAME "gmon.out" - - -extern struct __bb *__bb_head attribute_hidden; - - -void -__bb_exit_func (void) -{ - const int version = GMON_VERSION; - struct gmon_hdr ghdr; - struct __bb *ptr; - FILE *fp; - fp = fopen (OUT_NAME, "wb"); - if (!fp) - { - perror (OUT_NAME); - return; - } - /* No threads use this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - - memcpy (&ghdr.cookie[0], GMON_MAGIC, 4); - memcpy (&ghdr.version, &version, sizeof (version)); - fwrite_unlocked (&ghdr, sizeof (ghdr), 1, fp); - - for (ptr = __bb_head; ptr != 0; ptr = ptr->next) - { - u_int ncounts = ptr->ncounts; - u_char tag; - u_int i; - - tag = GMON_TAG_BB_COUNT; - fwrite_unlocked (&tag, sizeof (tag), 1, fp); - fwrite_unlocked (&ncounts, sizeof (ncounts), 1, fp); - - for (i = 0; i < ncounts; ++i) - { - fwrite_unlocked (&ptr->addresses[i], sizeof (ptr->addresses[0]), 1, - fp); - fwrite_unlocked (&ptr->counts[i], sizeof (ptr->counts[0]), 1, fp); - } - } - fclose (fp); -} diff --git a/gmon/bb_init_func.c b/gmon/bb_init_func.c deleted file mode 100644 index c635da77b4..0000000000 --- a/gmon/bb_init_func.c +++ /dev/null @@ -1,53 +0,0 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. - This file is part of the GNU C Library. - Contributed by David Mosberger (davidm@cs.arizona.edu). - - 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, see - <http://www.gnu.org/licenses/>. */ - -/* __bb_init_func is invoked at the beginning of each function, before - any registers have been saved. This generic routine should work - provided that calling this function doesn't mangle the arguments - passed to the function being called. If that's not the case, a - system specific routine must be provided. */ - -#include <sys/types.h> -#include <sys/gmon.h> - -#include <stdlib.h> - -void -__bb_init_func (struct __bb *bb) -{ - struct gmonparam *p = &_gmonparam; - - if (bb->zero_word != 0) - { - return; /* handle common case quickly */ - } - - /* insert this basic-block into basic-block list: */ - bb->zero_word = 1; - bb->next = __bb_head; - __bb_head = bb; - - if (bb->next == 0 && p->state != GMON_PROF_ON) - { - /* we didn't register _mcleanup yet and pc profiling doesn't seem - to be active, so let's register it now: */ - extern void *__dso_handle __attribute__ ((__weak__)); - __cxa_atexit ((void (*) (void *)) _mcleanup, NULL, - &__dso_handle ? __dso_handle : NULL); - } -} diff --git a/gmon/gmon.c b/gmon/gmon.c index e9988c06c4..dee64803ad 100644 --- a/gmon/gmon.c +++ b/gmon/gmon.c @@ -46,6 +46,26 @@ #include <libc-internal.h> #include <not-cancel.h> +#ifdef PIC +# include <link.h> + +static int +callback (struct dl_phdr_info *info, size_t size, void *data) +{ + if (info->dlpi_name[0] == '\0') + { + /* The link map for the executable is created by calling + _dl_new_object with "" as filename. dl_iterate_phdr + calls the callback function with filename from the + link map as dlpi_name. */ + u_long *load_address = data; + *load_address = (u_long) info->dlpi_addr; + return 1; + } + + return 0; +} +#endif /* Head of basic-block list or NULL. */ struct __bb *__bb_head attribute_hidden; @@ -58,13 +78,14 @@ struct gmonparam _gmonparam attribute_hidden = { GMON_PROF_OFF }; static int s_scale; #define SCALE_1_TO_1 0x10000L -#define ERR(s) write_not_cancel (STDERR_FILENO, s, sizeof (s) - 1) +#define ERR(s) __write_nocancel (STDERR_FILENO, s, sizeof (s) - 1) void moncontrol (int mode); void __moncontrol (int mode); -static void write_hist (int fd) internal_function; -static void write_call_graph (int fd) internal_function; -static void write_bb_counts (int fd) internal_function; +libc_hidden_proto (__moncontrol) +static void write_hist (int fd, u_long load_address); +static void write_call_graph (int fd, u_long load_address); +static void write_bb_counts (int fd); /* * Control profiling @@ -93,6 +114,7 @@ __moncontrol (int mode) p->state = GMON_PROF_OFF; } } +libc_hidden_def (__moncontrol) weak_alias (__moncontrol, moncontrol) @@ -171,8 +193,7 @@ weak_alias (__monstartup, monstartup) static void -internal_function -write_hist (int fd) +write_hist (int fd, u_long load_address) { u_char tag = GMON_TAG_TIME_HIST; @@ -209,21 +230,20 @@ write_hist (int fd) != offsetof (struct gmon_hist_hdr, dimen_abbrev))) abort (); - thdr.low_pc = (char *) _gmonparam.lowpc; - thdr.high_pc = (char *) _gmonparam.highpc; + thdr.low_pc = (char *) _gmonparam.lowpc - load_address; + thdr.high_pc = (char *) _gmonparam.highpc - load_address; thdr.hist_size = _gmonparam.kcountsize / sizeof (HISTCOUNTER); thdr.prof_rate = __profile_frequency (); strncpy (thdr.dimen, "seconds", sizeof (thdr.dimen)); thdr.dimen_abbrev = 's'; - writev_not_cancel_no_status (fd, iov, 3); + __writev_nocancel_nostatus (fd, iov, 3); } } static void -internal_function -write_call_graph (int fd) +write_call_graph (int fd, u_long load_address) { #define NARCS_PER_WRITEV 32 u_char tag = GMON_TAG_CG_ARC; @@ -266,25 +286,25 @@ write_call_graph (int fd) } arc; - arc.frompc = (char *) frompc; - arc.selfpc = (char *) _gmonparam.tos[to_index].selfpc; + arc.frompc = (char *) frompc - load_address; + arc.selfpc = ((char *) _gmonparam.tos[to_index].selfpc + - load_address); arc.count = _gmonparam.tos[to_index].count; memcpy (raw_arc + nfilled, &arc, sizeof (raw_arc [0])); if (++nfilled == NARCS_PER_WRITEV) { - writev_not_cancel_no_status (fd, iov, 2 * nfilled); + __writev_nocancel_nostatus (fd, iov, 2 * nfilled); nfilled = 0; } } } if (nfilled > 0) - writev_not_cancel_no_status (fd, iov, 2 * nfilled); + __writev_nocancel_nostatus (fd, iov, 2 * nfilled); } static void -internal_function write_bb_counts (int fd) { struct __bb *grp; @@ -312,12 +332,12 @@ write_bb_counts (int fd) for (grp = __bb_head; grp; grp = grp->next) { ncounts = grp->ncounts; - writev_not_cancel_no_status (fd, bbhead, 2); + __writev_nocancel_nostatus (fd, bbhead, 2); for (nfilled = i = 0; i < ncounts; ++i) { if (nfilled > (sizeof (bbbody) / sizeof (bbbody[0])) - 2) { - writev_not_cancel_no_status (fd, bbbody, nfilled); + __writev_nocancel_nostatus (fd, bbbody, nfilled); nfilled = 0; } @@ -325,7 +345,7 @@ write_bb_counts (int fd) bbbody[nfilled++].iov_base = &grp->counts[i]; } if (nfilled > 0) - writev_not_cancel_no_status (fd, bbbody, nfilled); + __writev_nocancel_nostatus (fd, bbbody, nfilled); } } @@ -336,22 +356,18 @@ write_gmon (void) int fd = -1; char *env; -#ifndef O_NOFOLLOW -# define O_NOFOLLOW 0 -#endif - env = getenv ("GMON_OUT_PREFIX"); if (env != NULL && !__libc_enable_secure) { size_t len = strlen (env); char buf[len + 20]; __snprintf (buf, sizeof (buf), "%s.%u", env, __getpid ()); - fd = open_not_cancel (buf, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666); + fd = __open_nocancel (buf, O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666); } if (fd == -1) { - fd = open_not_cancel ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, + fd = __open_nocancel ("gmon.out", O_CREAT|O_TRUNC|O_WRONLY|O_NOFOLLOW, 0666); if (fd < 0) { @@ -379,18 +395,24 @@ write_gmon (void) memcpy (&ghdr.cookie[0], GMON_MAGIC, sizeof (ghdr.cookie)); ghdr.version = GMON_VERSION; memset (ghdr.spare, '\0', sizeof (ghdr.spare)); - write_not_cancel (fd, &ghdr, sizeof (struct gmon_hdr)); + __write_nocancel (fd, &ghdr, sizeof (struct gmon_hdr)); + + /* Get load_address to profile PIE. */ + u_long load_address = 0; +#ifdef PIC + __dl_iterate_phdr (callback, &load_address); +#endif /* write PC histogram: */ - write_hist (fd); + write_hist (fd, load_address); /* write call-graph: */ - write_call_graph (fd); + write_call_graph (fd, load_address); /* write basic-block execution counts: */ write_bb_counts (fd); - close_not_cancel_no_status (fd); + __close_nocancel_nostatus (fd); } diff --git a/gmon/profil.c b/gmon/profil.c index e1eff8bd0f..f0d138ca34 100644 --- a/gmon/profil.c +++ b/gmon/profil.c @@ -1,5 +1,5 @@ /* Low-level statistical profiling support function. Stub version. - Copyright (C) 1995-2016 Free Software Foundation, Inc. + Copyright (C) 1995-2018 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 diff --git a/gmon/sprofil.c b/gmon/sprofil.c index 945cf18071..2f8dc23066 100644 --- a/gmon/sprofil.c +++ b/gmon/sprofil.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. This file is part of the GNU C Library. diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h index 5b430abc3e..b4cc3b043a 100644 --- a/gmon/sys/gmon.h +++ b/gmon/sys/gmon.h @@ -117,7 +117,7 @@ extern struct __bb *__bb_head; /* * The type used to represent indices into gmonparam.tos[]. */ -#define ARCINDEX u_long +#define ARCINDEX unsigned long /* * Maximum number of arcs we want to allow. @@ -130,7 +130,7 @@ extern struct __bb *__bb_head; #define MAXARCS (1 << 20) struct tostruct { - u_long selfpc; + unsigned long selfpc; long count; ARCINDEX link; }; @@ -140,9 +140,9 @@ struct tostruct { * the called site and a count. */ struct rawarc { - u_long raw_frompc; - u_long raw_selfpc; - long raw_count; + unsigned long raw_frompc; + unsigned long raw_selfpc; + long raw_count; }; /* @@ -156,17 +156,17 @@ struct rawarc { */ struct gmonparam { long int state; - u_short *kcount; - u_long kcountsize; + unsigned short *kcount; + unsigned long kcountsize; ARCINDEX *froms; - u_long fromssize; + unsigned long fromssize; struct tostruct *tos; - u_long tossize; + unsigned long tossize; long tolimit; - u_long lowpc; - u_long highpc; - u_long textsize; - u_long hashfraction; + unsigned long lowpc; + unsigned long highpc; + unsigned long textsize; + unsigned long hashfraction; long log_hashfraction; }; @@ -190,8 +190,8 @@ struct gmonparam { __BEGIN_DECLS /* Set up data structures and start profiling. */ -extern void __monstartup (u_long __lowpc, u_long __highpc) __THROW; -extern void monstartup (u_long __lowpc, u_long __highpc) __THROW; +extern void __monstartup (unsigned long __lowpc, unsigned long __highpc) __THROW; +extern void monstartup (unsigned long __lowpc, unsigned long __highpc) __THROW; /* Clean up profiling and write out gmon.out. */ extern void _mcleanup (void) __THROW; diff --git a/gmon/sys/gmon_out.h b/gmon/sys/gmon_out.h index b94879947f..de21d5559a 100644 --- a/gmon/sys/gmon_out.h +++ b/gmon/sys/gmon_out.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger <davidm@cs.arizona.edu>. diff --git a/gmon/sys/profil.h b/gmon/sys/profil.h index 5790fe03b8..b993a658c5 100644 --- a/gmon/sys/profil.h +++ b/gmon/sys/profil.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 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 diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh new file mode 100644 index 0000000000..1afec48b0b --- /dev/null +++ b/gmon/tst-gmon-gprof.sh @@ -0,0 +1,60 @@ +#!/bin/sh +# Check the output of gprof against a carfully crafted binary. +# Copyright (C) 2017-2018 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, see +# <http://www.gnu.org/licenses/>. + +LC_ALL=C +export LC_ALL +set -e +exec 2>&1 + +GPROF="$1" +program="$2" +data="$3" + +actual=$(mktemp) +expected=$(mktemp) +expected_dot=$(mktemp) +cleanup () { + rm -f "$actual" + rm -f "$expected" + rm -f "$expected_dot" +} +trap cleanup 0 + +cat > "$expected" <<EOF +f1 2000 +f2 1000 +EOF + +# Special version for powerpc with function descriptors. +cat > "$expected_dot" <<EOF +.f1 2000 +.f2 1000 +EOF + +"$GPROF" -C "$program" "$data" \ + | awk -F '[(): ]' '/executions/{print $5, $8}' \ + | sort > "$actual" + +if cmp -s "$actual" "$expected_dot" \ + || diff -u --label expected "$expected" --label actual "$actual" ; then + echo "PASS" +else + echo "FAIL" + exit 1 +fi diff --git a/gmon/tst-gmon-pie.c b/gmon/tst-gmon-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/gmon/tst-gmon-static-gprof.sh b/gmon/tst-gmon-static-gprof.sh new file mode 100644 index 0000000000..34dd952bf3 --- /dev/null +++ b/gmon/tst-gmon-static-gprof.sh @@ -0,0 +1,62 @@ +#!/bin/sh +# Check the output of gprof against a carfully crafted static binary. +# Copyright (C) 2017-2018 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, see +# <http://www.gnu.org/licenses/>. + +LC_ALL=C +export LC_ALL +set -e +exec 2>&1 + +GPROF="$1" +program="$2" +data="$3" + +actual=$(mktemp) +expected=$(mktemp) +expected_dot=$(mktemp) +cleanup () { + rm -f "$actual" + rm -f "$expected" + rm -f "$expected_dot" +} +trap cleanup 0 + +cat > "$expected" <<EOF +f1 2000 +f2 1000 +main 1 +EOF + +# Special version for powerpc with function descriptors. +cat > "$expected_dot" <<EOF +.f1 2000 +.f2 1000 +.main 1 +EOF + +"$GPROF" -C "$program" "$data" \ + | awk -F '[(): ]' '/executions/{print $5, $8}' \ + | sort > "$actual" + +if cmp -s "$actual" "$expected_dot" \ + || diff -u --label expected "$expected" --label actual "$actual" ; then + echo "PASS" +else + echo "FAIL" + exit 1 +fi diff --git a/gmon/tst-gmon-static-pie.c b/gmon/tst-gmon-static-pie.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static-pie.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/gmon/tst-gmon-static.c b/gmon/tst-gmon-static.c new file mode 100644 index 0000000000..1eef2583b6 --- /dev/null +++ b/gmon/tst-gmon-static.c @@ -0,0 +1 @@ +#include "tst-gmon.c" diff --git a/gmon/tst-gmon.c b/gmon/tst-gmon.c new file mode 100644 index 0000000000..ea2e55f608 --- /dev/null +++ b/gmon/tst-gmon.c @@ -0,0 +1,50 @@ +/* Test program for profiling information collection (_mcount/gprof). + Copyright (C) 2017-2018 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, see + <http://www.gnu.org/licenses/>. */ + +/* This program does not use the test harness because we want tight + control over the call graph. */ + +__attribute__ ((noinline, noclone, weak)) void +f1 (void) +{ +} + +__attribute__ ((noinline, noclone, weak)) void +f2 (void) +{ + f1 (); + /* Prevent tail call. */ + asm volatile (""); +} + +__attribute__ ((noinline, noclone, weak)) void +f3 (int count) +{ + for (int i = 0; i < count; ++i) + { + f1 (); + f2 (); + } +} + +int +main (void) +{ + f3 (1000); + return 0; +} diff --git a/gmon/tst-sprofil.c b/gmon/tst-sprofil.c index 66cede9719..ac4d1c3f18 100644 --- a/gmon/tst-sprofil.c +++ b/gmon/tst-sprofil.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger-Tang <davidm@hpl.hp.com>. |