From 06ad2699b0f27f901def236813eccb9b4d0f8ccd Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 15 Aug 2017 13:44:56 +0200 Subject: gmon: Add test for basic mcount/gprof functionality --- ChangeLog | 15 +++++++++++++ Makeconfig | 3 ++- aclocal.m4 | 2 ++ config.make.in | 1 + configure | 3 +++ gmon/Makefile | 18 ++++++++++++++- gmon/tst-gmon-gprof.sh | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++ gmon/tst-gmon.c | 50 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 gmon/tst-gmon-gprof.sh create mode 100644 gmon/tst-gmon.c diff --git a/ChangeLog b/ChangeLog index 56540f55a1..651cd923d8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2017-08-15 Florian Weimer + + * gmon/Makefile (tests): Add tst-gmon. + (CFLAGS-tst-gmon.c, LDFLAGS-tst-gmon, CRT-tst-gmon, tst-gmon-ENV): + Set. + (tests-special): Add tst-gmon-prof.out. + (tst-gmon.out): Depend on clean-tst-gmon-data. + (clean-tst-gmon-data, tst-gmon-gprof.out): New targets. + * gmon/tst-gmon.c, gmon/tst-gmon-gprof.sh: New files. + * Makeconfig (+link-before-libc): Add CRT-* hook to override the + startup object. + * aclocal.m4 (GPROF): Set and substitute. + * config.amke.in (GPROF): Set. + * configure: Regenerate. + 2017-08-14 Joseph Myers * conform/data/sys/wait.h-data (si_value): Do not expect for diff --git a/Makeconfig b/Makeconfig index 80aed2a987..19b559701a 100644 --- a/Makeconfig +++ b/Makeconfig @@ -465,7 +465,8 @@ else # not build-pie-default +link-before-libc = $(CC) -nostdlib -nostartfiles -o $@ \ $(sysdep-LDFLAGS) $(LDFLAGS) $(LDFLAGS-$(@F)) \ $(combreloc-LDFLAGS) $(relro-LDFLAGS) $(hashstyle-LDFLAGS) \ - $(addprefix $(csu-objpfx),$(start-installed-name)) \ + $(or $(CRT-$(@F)), $ \ + $(addprefix $(csu-objpfx),$(start-installed-name))) \ $(+preinit) $(+prector) \ $(filter-out $(addprefix $(csu-objpfx),start.o \ $(start-installed-name))\ diff --git a/aclocal.m4 b/aclocal.m4 index 69021558af..fe2a3713cc 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -121,6 +121,8 @@ OBJDUMP=`$CC -print-prog-name=objdump` AC_SUBST(OBJDUMP) OBJCOPY=`$CC -print-prog-name=objcopy` AC_SUBST(OBJCOPY) +GPROF=`$CC -print-prog-name=gprof` +AC_SUBST(GPROF) # Determine whether we are using GNU binutils. AC_CACHE_CHECK(whether $AS is GNU as, libc_cv_prog_as_gnu, diff --git a/config.make.in b/config.make.in index 7eff1daf6a..ea7a42cc19 100644 --- a/config.make.in +++ b/config.make.in @@ -120,6 +120,7 @@ BISON = @BISON@ AUTOCONF = @AUTOCONF@ OBJDUMP = @OBJDUMP@ OBJCOPY = @OBJCOPY@ +GPROF = @GPROF@ READELF = @READELF@ # Installation tools. diff --git a/configure b/configure index e6a54d7841..5cb5210107 100755 --- a/configure +++ b/configure @@ -651,6 +651,7 @@ MSGFMT MAKE LD AS +GPROF OBJCOPY OBJDUMP AR @@ -4572,6 +4573,8 @@ OBJDUMP=`$CC -print-prog-name=objdump` OBJCOPY=`$CC -print-prog-name=objcopy` +GPROF=`$CC -print-prog-name=gprof` + # Determine whether we are using GNU binutils. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $AS is GNU as" >&5 diff --git a/gmon/Makefile b/gmon/Makefile index 6ff4cb0dfb..947e6b5905 100644 --- a/gmon/Makefile +++ b/gmon/Makefile @@ -27,7 +27,7 @@ routines := gmon mcount profil sprofil bb_init_func bb_exit_func 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 @@ -38,6 +38,12 @@ endif # The mcount code won't work without a frame pointer. CFLAGS-mcount.c := -fno-omit-frame-pointer +CFLAGS-tst-gmon.c := -pg +LDFLAGS-tst-gmon := $(no-pie-ldflag) +CRT-tst-gmon := $(csu-objpfx)gcrt1.o +tst-gmon-ENV := GMON_OUT_PREFIX=$(objpfx)tst-gmon.data +tests-special += $(objpfx)tst-gmon-gprof.out + include ../Rules # We cannot compile mcount.c with -pg because that would @@ -53,3 +59,13 @@ 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) diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh new file mode 100644 index 0000000000..b10a6e0763 --- /dev/null +++ b/gmon/tst-gmon-gprof.sh @@ -0,0 +1,59 @@ +#!/bin/sh +# Check the output of gprof against a carfully crafted binary. +# Copyright (C) 2017 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 +# . + +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_dot" +} +trap cleanup 0 + +cat > "$expected" < "$expected_dot" < "$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.c b/gmon/tst-gmon.c new file mode 100644 index 0000000000..46040d7d7b --- /dev/null +++ b/gmon/tst-gmon.c @@ -0,0 +1,50 @@ +/* Test program for profiling information collection (mcount/gprof). + Copyright (C) 2017 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 + . */ + +/* 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; +} -- cgit v1.2.3