1999-10-07  Ulrich Drepper  <drepper@cygnus.com>

	* debug/Makefile (install-bin): Add pcprofiledump and xtrace.
	Add rules for both programs.
	* debug/pcprofiledump.c: New file.
	* debug/xtrace.sh: New file.
	* debug/pcprofile.c: Allow creating output file.  Add magic signature
	to let reader recognize file format.
This commit is contained in:
Ulrich Drepper 1999-10-07 07:25:16 +00:00
parent 42d7c59314
commit cab30d75a3
5 changed files with 395 additions and 3 deletions

View File

@ -1,3 +1,12 @@
1999-10-07 Ulrich Drepper <drepper@cygnus.com>
* debug/Makefile (install-bin): Add pcprofiledump and xtrace.
Add rules for both programs.
* debug/pcprofiledump.c: New file.
* debug/xtrace.sh: New file.
* debug/pcprofile.c: Allow creating output file. Add magic signature
to let reader recognize file format.
1999-10-06 Ulrich Drepper <drepper@cygnus.com>
* locale/programs/ld-ctype.c (ctype_read): Fix typos in last patch.

View File

@ -39,12 +39,14 @@ libSegFault-inhibit-o = $(filter-out .os,$(object-suffixes))
libpcprofile-routines = pcprofile
libpcprofile-inhibit-o = $(filter-out .os,$(object-suffixes))
install-bin = pcprofiledump xtrace
include ../Makeconfig
distribute += catchsegv.sh
ifeq ($(elf),yes)
ifeq ($(build-shared),yes)
install-bin = catchsegv
install-bin += catchsegv
endif
endif
generated = catchsegv
@ -57,6 +59,15 @@ $(objpfx)catchsegv: catchsegv.sh $(common-objpfx)soversions.mk \
chmod 555 $@.new
mv -f $@.new $@
$(objpfx)pcprofiledump: $(objpfx)pcprofiledump.o
$(LINK.o) -o $@ $^
$(objpfx)xtrace: xtrace.sh
rm -f $@.new
sed -e 's|@BASH@|$(BASH)|' -e 's|@VERSION@|$(version)|' \
-e 's|@LIBDIR@|$(libdir)|' -e 's|@BINDIR@|$(bindir)|' $^ > $@.new \
&& rm -f $@ && mv $@.new $@ && chmod +x $@
# Depend on libc.so so a DT_NEEDED is generated in the shared objects.
# This ensures they will load libc.so for needed symbols if loaded by
# a statically-linked program that hasn't already loaded it.

View File

@ -18,7 +18,9 @@
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
@ -39,10 +41,25 @@ install (void)
if (outfile != NULL && *outfile != '\0')
{
fd = open (outfile, O_RDWR);
fd = open (outfile, O_RDWR | O_CREAT, 0666);
if (fd != -1)
active = 1;
{
uint32_t word;
active = 1;
/* Write a magic word which tells the reader about the byte
order and the size of the following entries. */
word = 0xdeb00000 | sizeof (void *);
if (TEMP_FAILURE_RETRY (write (fd, &word, 4)) != 4)
{
/* If even this fails we shouldn't try further. */
close (fd);
fd = -1;
active = 0;
}
}
}
}

187
debug/pcprofiledump.c Normal file
View File

@ -0,0 +1,187 @@
/* Dump information generating by PC profiling.
Copyright (C) 1999 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 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
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If not,
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
/* This is mainly and example. It shows how programs which want to use
the information should read the file. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <argp.h>
#include <byteswap.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <inttypes.h>
#include <libintl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "../version.h"
#ifndef _
# define _(Str) gettext (Str)
#endif
#ifndef N_
# define N_(Str) Str
#endif
/* Definitions of arguments for argp functions. */
static const struct argp_option options[] =
{
{ NULL, 0, NULL, 0, NULL }
};
/* Short description of program. */
static const char doc[] = N_("Dump information generating by PC profiling.");
/* Strings for arguments in help texts. */
static const char args_doc[] = N_("[FILE]");
/* Function to print some extra text in the help message. */
static char *more_help (int key, const char *text, void *input);
/* Data structure to communicate with argp functions. */
static struct argp argp =
{
options, NULL, args_doc, doc, NULL, more_help
};
int
main (int argc, char *argv[])
{
int fd;
int remaining;
int must_swap;
uint32_t word;
/* Parse and process arguments. */
argp_parse (&argp, argc, argv, 0, &remaining, NULL);
if (remaining == argc)
fd = STDIN_FILENO;
else if (remaining + 1 != argc)
{
argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
program_invocation_short_name);
exit (1);
}
else
{
/* Open the given file. */
fd = open (argv[remaining], O_RDONLY);
if (fd == -1)
error (EXIT_FAILURE, errno, _("cannot open input file"));
}
/* Read the first 4-byte word. It contains the information about
the word size and the endianess. */
if (TEMP_FAILURE_RETRY (read (fd, &word, 4)) != 4)
error (EXIT_FAILURE, errno, _("cannot read header"));
/* Check whether we have to swap the byte order. */
must_swap = (word & 0xfffffff0) == bswap_32 (0xdeb00000);
if (must_swap)
word = bswap_32 (word);
/* We have two loops, one for 32 bit pointers, one for 64 bit pointers. */
if (word == 0xdeb00004)
{
union
{
uint32_t ptrs[2];
char bytes[8];
} pair;
while (1)
{
size_t len = sizeof (pair);
size_t n;
while (len > 0
&& (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
len))) != 0)
len -= n;
if (len != 0)
/* Nothing to read. */
break;
printf ("this = %#010" PRIx32 ", caller = %#010" PRIx32 "\n",
must_swap ? bswap_32 (pair.ptrs[0]) : pair.ptrs[0],
must_swap ? bswap_32 (pair.ptrs[1]) : pair.ptrs[1]);
}
}
else if (word == 0xdeb00008)
{
union
{
uint64_t ptrs[2];
char bytes[16];
} pair;
while (1)
{
size_t len = sizeof (pair);
size_t n;
while (len > 0
&& (n = TEMP_FAILURE_RETRY (read (fd, &pair.bytes[8 - len],
len))) != 0)
len -= n;
if (len != 0)
/* Nothing to read. */
break;
printf ("this = %#018" PRIx64 ", caller = %#018" PRIx64 "\n",
must_swap ? bswap_64 (pair.ptrs[0]) : pair.ptrs[0],
must_swap ? bswap_64 (pair.ptrs[1]) : pair.ptrs[1]);
}
}
else
/* This should not happen. */
error (EXIT_FAILURE, 0, _("invalid pointer size"));
/* Clean up. */
close (fd);
return 0;
}
static char *
more_help (int key, const char *text, void *input)
{
switch (key)
{
case ARGP_KEY_HELP_EXTRA:
/* We print some extra information. */
return strdup (gettext ("\
Report bugs using the `glibcbug' script to <bugs@gnu.org>.\n"));
default:
break;
}
return (char *) text;
}

168
debug/xtrace.sh Executable file
View File

@ -0,0 +1,168 @@
#! @BASH@
# Copyright (C) 1999 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# Contributed by Ulrich Drepper <drepper@gnu.org>, 1999.
# The GNU C Library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Library General Public License as
# published by the Free Software Foundation; either version 2 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
# Library General Public License for more details.
# You should have received a copy of the GNU Library General Public
# License along with the GNU C Library; see the file COPYING.LIB. If not,
# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
pcprofileso=@LIBDIR@/libpcprofile.so
pcprofiledump=@BINDIR@/pcprofiledump
# Print usage message.
do_usage() {
echo >&2 $"Try \`xtrace --help' for more information."
exit 1
}
# Message for missing argument.
do_missing_arg() {
echo >&2 $"xtrace: option \`$1' requires an argument"
do_usage
}
# Print help message
do_help() {
echo $"Usage: xtrace [OPTION]... PROGRAM [PROGRAMOPTION]...
Trace execution of program by printing currently executed function.
--data=FILE Don't run the program, just print the data from FILE.
-?,--help Print this help and exit
--usage Give a short usage message
-V,--version Print version information and exit
Mandatory arguments to long options are also mandatory for any corresponding
short options.
Report bugs using the \`glibcbug' script to <bugs@gnu.org>."
exit 0
}
do_version() {
echo 'xtrace (GNU libc) @VERSION@'
echo $"Copyright (C) 1999 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Written by Ulrich Drepper."
exit 0
}
# Print out function name, file, and line number is a nice formatted way.
format_line() {
fct=$1
file=${2%%:*}
line=${2##*:}
width=$(expr $COLUMNS - 30)
filelen=$(expr length $file)
if test "$filelen" -gt "$width"; then
rwidth=$(expr $width - 3)
file="...$(expr substr $file $(expr 1 + $filelen - $rwidth) $rwidth)"
fi
printf '%-20s %-*s %6s\n' $fct $width $file $line
}
# If the variable COLUMNS is not set do this now.
COLUMNS=${COLUMNS:-80}
# If `TERM' is not set, set it to `xterm'.
TERM=${TERM:-xterm}
# Process arguments. But stop as soon as the program name is found.
while test $# -gt 0; do
case "$1" in
--d | --da | --dat | --data)
if test $# -eq 1; then
do_missing_arg $1
fi
shift
data="$1"
;;
--d=* | --da=* | --dat=* | --data=*)
data=${1##*=}
;;
--)
# Stop processing arguments.
shift
break
;;
--*)
echo >&2 $"memprof: unrecognized option \`$1'"
do_usage
;;
*)
# Unknown option. This means the rest is the program name and parameters.
break
;;
esac
shift
done
# See whether any arguments are left.
if test $# -eq 0; then
echo >&2 $"No program name given"
do_usage
fi
# Determine the program name and check whether it exists.
program=$1
shift
if test ! -f "$program"; then
echo >2& $"\executable \`$program' not found"
do_usage
fi
if test ! -x "$program"; then
echo >&2 $"\`$program' is no executable"
do_usage
fi
# We have two modes. If a data file is given simply print the included data.
printf "%-20s %-*s %6s\n" Function $(expr $COLUMNS - 30) File Line
for i in $(seq 1 $COLUMNS); do echo -n -; done; echo
if test -n "$data"; then
eval $pcprofiledump $data |
sed 's/this = \([^,]*\).*/\1/' |
addr2line -fC -e $program |
while read fct; do
read file
if test "$fct" != '??' -a "$file" != '??:0'; then
format_line $fct $file
fi
done
else
fifo=$(mktemp -u ${TMPDIR:-/tmp}/xprof.XXXXXX)
mkfifo -m 0600 $fifo || exit 1
# Now start the program and let it write to the FIFO.
eval $TERM -T "'xtrace - $program $*'" -e /bin/sh -c "'LD_PRELOAD=$pcprofileso PCPROFILE_OUTPUT=$fifo $program $*; read $fifo'" &
termpid=$!
eval $pcprofiledump $fifo |
sed 's/this = \([^,]*\).*/\1/' |
addr2line -fC -e $program |
while read fct; do
read file
if test "$fct" != '??' -a "$file" != '??:0'; then
format_line $fct $file
fi
done
read -p "Press return to end the program."
echo > $fifo
rm $fifo
fi
exit 0
# Local Variables:
# mode:ksh
# End: