diff mbox

Test for profiling support (_mcount/gprof)

Message ID 4d15086e-9e54-014b-1a50-16534f287e24@redhat.com
State New
Headers show

Commit Message

Florian Weimer Aug. 15, 2017, 12:05 p.m. UTC
The attached patch adds an integration test for gcc -pg, _mcount/gmon,
and gprof.

It passes on aarch64, ppc, ppc64, ppc64le, s390, s390x, x86_64, and on
i386 with the _mcount internal_function replacement applied.

The test is compiled with -pg and is linked against gcrt1.o, via the new
CRT-* makefile hook.  As far as I can tell, it is properly isolated from
system glibc (only GCC objects are picked up).

Thanks,
Florian

Comments

Andreas Schwab Aug. 15, 2017, 12:28 p.m. UTC | #1
On Aug 15 2017, Florian Weimer <fweimer@redhat.com> wrote:

> 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))) \

$(or) is a 3.81 feature, we only require 3.79.  You can use $(firstword)
instead.  The lone $ looks like a typo.

Andreas.
Florian Weimer Aug. 15, 2017, 12:45 p.m. UTC | #2
On 08/15/2017 02:28 PM, Andreas Schwab wrote:
> On Aug 15 2017, Florian Weimer <fweimer@redhat.com> wrote:
> 
>> 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))) \
> 
> $(or) is a 3.81 feature, we only require 3.79.  You can use $(firstword)
> instead.

Oh, good point.  $(firstword …) does not really align with the
subsequent $(addprefix …) usage because that has the implication that
$(start-installed-name) contains multiple words.  We can turn

  $(addprefix $(csu-objpfx),$(start-installed-name))

into

  $(csu-objpfx)$(start-installed-name)

though; it should work on all in-tree architectures.  Then $(firstword
…) should have the right semantics.

But can we require make 3.81 instead?  It was released in April 2006,
after all.  That does not mean we'll start using controversial 3.81
features such as $(eval …).

> The lone $ looks like a typo.

Right.  Fixed.

Thanks,
Florian
Andreas Schwab Aug. 15, 2017, 12:56 p.m. UTC | #3
On Aug 15 2017, Florian Weimer <fweimer@redhat.com> wrote:

> On 08/15/2017 02:28 PM, Andreas Schwab wrote:
>> On Aug 15 2017, Florian Weimer <fweimer@redhat.com> wrote:
>> 
>>> 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))) \
>> 
>> $(or) is a 3.81 feature, we only require 3.79.  You can use $(firstword)
>> instead.
>
> Oh, good point.  $(firstword …) does not really align with the
> subsequent $(addprefix …) usage because that has the implication that
> $(start-installed-name) contains multiple words.

Other uses already require $(start-installed-name) to be a single word.
A lot of places use addprefix when not really needed.

Andreas.
diff mbox

Patch

gmon: Add test for basic mcount/gprof functionality

2017-08-15  Florian Weimer  <fweimer@redhat.com>

	* 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.

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
+# <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_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.c b/gmon/tst-gmon.c
new file mode 100644
index 0000000000..ce81aa41b8
--- /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
+   <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;
+}