mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 16:56:41 +08:00
new version 0.5
performance improvements and optimizations bug fixes advanced monitoring
This commit is contained in:
parent
3df912ba51
commit
3aed8a6e6b
@ -1,7 +1,7 @@
|
|||||||
Mtrace
|
Mtrace
|
||||||
------
|
------
|
||||||
|
|
||||||
mtrace-ng is an interactive dynamic memory tracer, debugger and statistical analyses tool for C and C++, which intercepts, records and reports all kinds of dynamic memory allocations.
|
mtrace-ng is a dynamic memory tracer, debugger and statistical analyses tool for C and C++, which intercepts, records and reports all kinds of dynamic memory allocations.
|
||||||
|
|
||||||
It supports the developer to get statistics about the memory usage and finding memory leaks in an arbitrate program. Since mtrace-ng is using breakpoints for tracing the program, there is no need of modification of the source code nor any recompilation.
|
It supports the developer to get statistics about the memory usage and finding memory leaks in an arbitrate program. Since mtrace-ng is using breakpoints for tracing the program, there is no need of modification of the source code nor any recompilation.
|
||||||
|
|
||||||
|
|||||||
2
TODO
2
TODO
@ -2,7 +2,5 @@ ppc single step enhancement
|
|||||||
arm thumb support
|
arm thumb support
|
||||||
dwarf debug support
|
dwarf debug support
|
||||||
arm & ppc hw bp support
|
arm & ppc hw bp support
|
||||||
dwarf caching
|
|
||||||
invalid stack trace cache for unmapped libraries
|
invalid stack trace cache for unmapped libraries
|
||||||
restore REALLOC_TRY when realloc fails
|
|
||||||
mremap revamp
|
mremap revamp
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
@%:@! /bin/sh
|
@%:@! /bin/sh
|
||||||
@%:@ Guess values for system-dependent variables and create Makefiles.
|
@%:@ Guess values for system-dependent variables and create Makefiles.
|
||||||
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.4.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.5.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ Report bugs to <stefani@seibold.net>.
|
@%:@ Report bugs to <stefani@seibold.net>.
|
||||||
@%:@
|
@%:@
|
||||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='mtrace-ng'
|
PACKAGE_NAME='mtrace-ng'
|
||||||
PACKAGE_TARNAME='mtrace-ng'
|
PACKAGE_TARNAME='mtrace-ng'
|
||||||
PACKAGE_VERSION='0.4'
|
PACKAGE_VERSION='0.5'
|
||||||
PACKAGE_STRING='mtrace-ng 0.4'
|
PACKAGE_STRING='mtrace-ng 0.5'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1329,7 +1329,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures mtrace-ng 0.4 to adapt to many kinds of systems.
|
\`configure' configures mtrace-ng 0.5 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1399,7 +1399,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of mtrace-ng 0.4:";;
|
short | recursive ) echo "Configuration of mtrace-ng 0.5:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1518,7 +1518,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
mtrace-ng configure 0.4
|
mtrace-ng configure 0.5
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2124,7 +2124,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by mtrace-ng $as_me 0.4, which was
|
It was created by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12006,7 +12006,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace-ng'
|
PACKAGE='mtrace-ng'
|
||||||
VERSION='0.4'
|
VERSION='0.5'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -13238,6 +13238,7 @@ for ac_func in \
|
|||||||
atexit \
|
atexit \
|
||||||
getcwd \
|
getcwd \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
|
clock_gettime \
|
||||||
memset \
|
memset \
|
||||||
mkdir \
|
mkdir \
|
||||||
rmdir \
|
rmdir \
|
||||||
@ -13260,6 +13261,54 @@ fi
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||||
|
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
|
||||||
|
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char clock_gettime ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return clock_gettime ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_lib_rt_clock_gettime=yes
|
||||||
|
else
|
||||||
|
ac_cv_lib_rt_clock_gettime=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
|
||||||
|
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
|
||||||
|
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@%:@define HAVE_LIBRT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
as_fn_error $? "*** librt not found on your system" "$LINENO" 5
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Debugging
|
# Debugging
|
||||||
@ -13844,7 +13893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by mtrace-ng $as_me 0.4, which was
|
This file was extended by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -13910,7 +13959,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
mtrace-ng config.status 0.4
|
mtrace-ng config.status 0.5
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
@%:@! /bin/sh
|
@%:@! /bin/sh
|
||||||
@%:@ Guess values for system-dependent variables and create Makefiles.
|
@%:@ Guess values for system-dependent variables and create Makefiles.
|
||||||
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.4.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.5.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ Report bugs to <stefani@seibold.net>.
|
@%:@ Report bugs to <stefani@seibold.net>.
|
||||||
@%:@
|
@%:@
|
||||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='mtrace-ng'
|
PACKAGE_NAME='mtrace-ng'
|
||||||
PACKAGE_TARNAME='mtrace-ng'
|
PACKAGE_TARNAME='mtrace-ng'
|
||||||
PACKAGE_VERSION='0.4'
|
PACKAGE_VERSION='0.5'
|
||||||
PACKAGE_STRING='mtrace-ng 0.4'
|
PACKAGE_STRING='mtrace-ng 0.5'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1329,7 +1329,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures mtrace-ng 0.4 to adapt to many kinds of systems.
|
\`configure' configures mtrace-ng 0.5 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1399,7 +1399,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of mtrace-ng 0.4:";;
|
short | recursive ) echo "Configuration of mtrace-ng 0.5:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1518,7 +1518,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
mtrace-ng configure 0.4
|
mtrace-ng configure 0.5
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2124,7 +2124,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by mtrace-ng $as_me 0.4, which was
|
It was created by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12006,7 +12006,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace-ng'
|
PACKAGE='mtrace-ng'
|
||||||
VERSION='0.4'
|
VERSION='0.5'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -13238,6 +13238,7 @@ for ac_func in \
|
|||||||
atexit \
|
atexit \
|
||||||
getcwd \
|
getcwd \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
|
clock_gettime \
|
||||||
memset \
|
memset \
|
||||||
mkdir \
|
mkdir \
|
||||||
rmdir \
|
rmdir \
|
||||||
@ -13260,6 +13261,54 @@ fi
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||||
|
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
|
||||||
|
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char clock_gettime ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return clock_gettime ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_lib_rt_clock_gettime=yes
|
||||||
|
else
|
||||||
|
ac_cv_lib_rt_clock_gettime=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
|
||||||
|
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
|
||||||
|
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@%:@define HAVE_LIBRT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
as_fn_error $? "*** librt not found on your system" "$LINENO" 5
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Debugging
|
# Debugging
|
||||||
@ -13844,7 +13893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by mtrace-ng $as_me 0.4, which was
|
This file was extended by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -13910,7 +13959,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
mtrace-ng config.status 0.4
|
mtrace-ng config.status 0.5
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
@%:@! /bin/sh
|
@%:@! /bin/sh
|
||||||
@%:@ Guess values for system-dependent variables and create Makefiles.
|
@%:@ Guess values for system-dependent variables and create Makefiles.
|
||||||
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.4.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace-ng 0.5.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ Report bugs to <stefani@seibold.net>.
|
@%:@ Report bugs to <stefani@seibold.net>.
|
||||||
@%:@
|
@%:@
|
||||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='mtrace-ng'
|
PACKAGE_NAME='mtrace-ng'
|
||||||
PACKAGE_TARNAME='mtrace-ng'
|
PACKAGE_TARNAME='mtrace-ng'
|
||||||
PACKAGE_VERSION='0.4'
|
PACKAGE_VERSION='0.5'
|
||||||
PACKAGE_STRING='mtrace-ng 0.4'
|
PACKAGE_STRING='mtrace-ng 0.5'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1329,7 +1329,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures mtrace-ng 0.4 to adapt to many kinds of systems.
|
\`configure' configures mtrace-ng 0.5 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1399,7 +1399,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of mtrace-ng 0.4:";;
|
short | recursive ) echo "Configuration of mtrace-ng 0.5:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1518,7 +1518,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
mtrace-ng configure 0.4
|
mtrace-ng configure 0.5
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2124,7 +2124,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by mtrace-ng $as_me 0.4, which was
|
It was created by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12006,7 +12006,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace-ng'
|
PACKAGE='mtrace-ng'
|
||||||
VERSION='0.4'
|
VERSION='0.5'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -13238,6 +13238,7 @@ for ac_func in \
|
|||||||
atexit \
|
atexit \
|
||||||
getcwd \
|
getcwd \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
|
clock_gettime \
|
||||||
memset \
|
memset \
|
||||||
mkdir \
|
mkdir \
|
||||||
rmdir \
|
rmdir \
|
||||||
@ -13260,6 +13261,54 @@ fi
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||||
|
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
|
||||||
|
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char clock_gettime ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return clock_gettime ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_lib_rt_clock_gettime=yes
|
||||||
|
else
|
||||||
|
ac_cv_lib_rt_clock_gettime=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
|
||||||
|
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
|
||||||
|
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
@%:@define HAVE_LIBRT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
as_fn_error $? "*** librt not found on your system" "$LINENO" 5
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Debugging
|
# Debugging
|
||||||
@ -13844,7 +13893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by mtrace-ng $as_me 0.4, which was
|
This file was extended by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -13910,7 +13959,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
mtrace-ng config.status 0.4
|
mtrace-ng config.status 0.5
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@ -42,186 +42,186 @@
|
|||||||
'configure.ac'
|
'configure.ac'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'_LT_AC_TAGVAR' => 1,
|
|
||||||
'LT_OUTPUT' => 1,
|
|
||||||
'LTVERSION_VERSION' => 1,
|
|
||||||
'_AM_MANGLE_OPTION' => 1,
|
|
||||||
'_AM_PROG_CC_C_O' => 1,
|
|
||||||
'LTOBSOLETE_VERSION' => 1,
|
|
||||||
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'AM_RUN_LOG' => 1,
|
|
||||||
'AC_LIBTOOL_WIN32_DLL' => 1,
|
|
||||||
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
|
||||||
'_LT_DLL_DEF_P' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
|
||||||
'AC_LTDL_ENABLE_INSTALL' => 1,
|
|
||||||
'LT_WITH_LTDL' => 1,
|
|
||||||
'AC_LTDL_DLSYM_USCORE' => 1,
|
|
||||||
'_LT_COMPILER_OPTION' => 1,
|
|
||||||
'LTSUGAR_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
|
||||||
'LT_PATH_LD' => 1,
|
|
||||||
'AC_LTDL_SHLIBEXT' => 1,
|
|
||||||
'_LT_AC_SHELL_INIT' => 1,
|
|
||||||
'AM_SILENT_RULES' => 1,
|
|
||||||
'AM_PROG_LD' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
|
||||||
'_LT_WITH_SYSROOT' => 1,
|
|
||||||
'AC_DISABLE_FAST_INSTALL' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
|
||||||
'AC_PROG_EGREP' => 1,
|
|
||||||
'_LT_AC_SYS_COMPILER' => 1,
|
|
||||||
'LT_CMD_MAX_LEN' => 1,
|
|
||||||
'LTDL_INIT' => 1,
|
|
||||||
'AC_LIBLTDL_INSTALLABLE' => 1,
|
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
|
||||||
'AC_ENABLE_SHARED' => 1,
|
|
||||||
'LT_AC_PROG_EGREP' => 1,
|
|
||||||
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
|
||||||
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
|
||||||
'AM_SUBST_NOTMAKE' => 1,
|
'AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
|
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AM_DEP_TRACK' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
|
'AM_ENABLE_STATIC' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'LTDL_INIT' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'AC_DISABLE_SHARED' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'_LT_PROG_FC' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'AC_LTDL_SHLIBPATH' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
||||||
'_LTDL_SETUP' => 1,
|
'_LTDL_SETUP' => 1,
|
||||||
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
|
||||||
'LT_PROG_GO' => 1,
|
|
||||||
'AM_DISABLE_STATIC' => 1,
|
|
||||||
'_LT_LINKER_BOILERPLATE' => 1,
|
|
||||||
'AM_PROG_LIBTOOL' => 1,
|
|
||||||
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
|
||||||
'AC_LTDL_SHLIBPATH' => 1,
|
|
||||||
'LT_LIB_M' => 1,
|
|
||||||
'AC_LIBLTDL_CONVENIENCE' => 1,
|
|
||||||
'LT_SYS_SYMBOL_USCORE' => 1,
|
|
||||||
'LT_FUNC_ARGZ' => 1,
|
|
||||||
'_LT_LIBOBJ' => 1,
|
|
||||||
'm4_pattern_forbid' => 1,
|
|
||||||
'AM_DISABLE_SHARED' => 1,
|
|
||||||
'_LT_AC_LANG_C_CONFIG' => 1,
|
|
||||||
'_LT_PROG_F77' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
|
||||||
'AM_PROG_NM' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'_LT_LINKER_OPTION' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
|
||||||
'AC_DISABLE_SHARED' => 1,
|
|
||||||
'LT_PROG_GCJ' => 1,
|
|
||||||
'AM_ENABLE_SHARED' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN' => 1,
|
|
||||||
'_LT_AC_LOCK' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
|
||||||
'AC_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AC_CHECK_LIBM' => 1,
|
|
||||||
'AC_LIBTOOL_PICMODE' => 1,
|
|
||||||
'AU_DEFUN' => 1,
|
|
||||||
'_AM_SET_OPTIONS' => 1,
|
|
||||||
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
|
||||||
'LT_AC_PROG_SED' => 1,
|
|
||||||
'AC_DEFUN_ONCE' => 1,
|
|
||||||
'AC_WITH_LTDL' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
|
||||||
'AC_LIBTOOL_SETUP' => 1,
|
|
||||||
'_LT_CC_BASENAME' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
|
||||||
'_LT_AC_CHECK_DLFCN' => 1,
|
|
||||||
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
|
||||||
'AC_LIBTOOL_CXX' => 1,
|
|
||||||
'AC_LIBTOOL_GCJ' => 1,
|
|
||||||
'LT_SYS_DLOPEN_SELF' => 1,
|
|
||||||
'LT_PROG_RC' => 1,
|
|
||||||
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
|
||||||
'LT_AC_PROG_RC' => 1,
|
|
||||||
'AC_PROG_LD_GNU' => 1,
|
|
||||||
'LT_AC_PROG_GCJ' => 1,
|
|
||||||
'm4_include' => 1,
|
|
||||||
'AC_LTDL_SYSSEARCHPATH' => 1,
|
|
||||||
'AM_PROG_INSTALL_SH' => 1,
|
|
||||||
'_LT_AC_PROG_CXXCPP' => 1,
|
|
||||||
'AC_LTDL_PREOPEN' => 1,
|
|
||||||
'AC_DEFUN' => 1,
|
|
||||||
'AC_LIBTOOL_OBJDIR' => 1,
|
|
||||||
'AM_AUX_DIR_EXPAND' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
|
||||||
'_AM_AUTOCONF_VERSION' => 1,
|
|
||||||
'_LT_AC_LANG_CXX' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'AM_SET_DEPDIR' => 1,
|
|
||||||
'_AM_SET_OPTION' => 1,
|
|
||||||
'AM_ENABLE_STATIC' => 1,
|
|
||||||
'AC_PROG_NM' => 1,
|
|
||||||
'_LT_AC_LANG_F77' => 1,
|
|
||||||
'_LT_PROG_CXX' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
|
||||||
'AC_LIBTOOL_FC' => 1,
|
|
||||||
'_LT_PROG_LTMAIN' => 1,
|
|
||||||
'LTOPTIONS_VERSION' => 1,
|
|
||||||
'_LT_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AM_SET_LEADING_DOT' => 1,
|
|
||||||
'_AM_CONFIG_MACRO_DIRS' => 1,
|
|
||||||
'AC_ENABLE_FAST_INSTALL' => 1,
|
|
||||||
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
|
||||||
'_AM_PROG_TAR' => 1,
|
|
||||||
'include' => 1,
|
|
||||||
'AC_PATH_MAGIC' => 1,
|
|
||||||
'_LT_PROG_FC' => 1,
|
|
||||||
'AM_PROG_INSTALL_STRIP' => 1,
|
|
||||||
'LT_FUNC_DLSYM_USCORE' => 1,
|
|
||||||
'LT_LIB_DLLOAD' => 1,
|
|
||||||
'AC_LTDL_OBJDIR' => 1,
|
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
|
||||||
'LT_LANG' => 1,
|
|
||||||
'AC_LIB_LTDL' => 1,
|
|
||||||
'_AC_PROG_LIBTOOL' => 1,
|
|
||||||
'AM_MISSING_PROG' => 1,
|
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
|
||||||
'_m4_warn' => 1,
|
|
||||||
'AC_PROG_LD' => 1,
|
|
||||||
'LT_PATH_NM' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
|
||||||
'AC_LIBTOOL_CONFIG' => 1,
|
|
||||||
'LT_SYS_DLSEARCH_PATH' => 1,
|
|
||||||
'_LT_AC_LANG_F77_CONFIG' => 1,
|
|
||||||
'AM_DEP_TRACK' => 1,
|
|
||||||
'LTDL_INSTALLABLE' => 1,
|
|
||||||
'LT_SYS_MODULE_PATH' => 1,
|
|
||||||
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'_AM_DEPENDENCIES' => 1,
|
|
||||||
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
|
||||||
'AM_CONDITIONAL' => 1,
|
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
|
||||||
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
|
||||||
'AM_MAKE_INCLUDE' => 1,
|
|
||||||
'LT_INIT' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ' => 1,
|
|
||||||
'AM_MISSING_HAS_RUN' => 1,
|
|
||||||
'_LT_AC_FILE_LTDLL_C' => 1,
|
|
||||||
'LT_SYS_MODULE_EXT' => 1,
|
|
||||||
'AC_DISABLE_STATIC' => 1,
|
|
||||||
'_AM_IF_OPTION' => 1,
|
|
||||||
'AM_SANITY_CHECK' => 1,
|
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
|
||||||
'AC_LIBTOOL_F77' => 1,
|
|
||||||
'_LT_AC_LANG_RC_CONFIG' => 1,
|
|
||||||
'AC_LIBTOOL_RC' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
|
||||||
'AC_ENABLE_STATIC' => 1,
|
|
||||||
'AC_LTDL_DLLIB' => 1,
|
|
||||||
'AC_LTDL_SYMBOL_USCORE' => 1,
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
'LTDL_CONVENIENCE' => 1,
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_LTDL_DLLIB' => 1,
|
||||||
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AM_MISSING_PROG' => 1,
|
||||||
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR' => 1,
|
||||||
|
'AC_DISABLE_STATIC' => 1,
|
||||||
|
'_LT_AC_PROG_CXXCPP' => 1,
|
||||||
|
'_LT_PROG_F77' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'AM_DISABLE_SHARED' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
|
'_AM_IF_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
||||||
|
'AM_SILENT_RULES' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'_LT_CC_BASENAME' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'_AM_DEPENDENCIES' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
|
'LT_FUNC_ARGZ' => 1,
|
||||||
|
'AM_SANITY_CHECK' => 1,
|
||||||
|
'AC_DEFUN' => 1,
|
||||||
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AC_DEFUN_ONCE' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
'AM_PROG_CC_C_O' => 1,
|
'AM_PROG_CC_C_O' => 1,
|
||||||
'_LT_COMPILER_BOILERPLATE' => 1
|
'AC_PROG_NM' => 1,
|
||||||
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
|
'_AM_CONFIG_MACRO_DIRS' => 1,
|
||||||
|
'LT_LIB_DLLOAD' => 1,
|
||||||
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
|
'AU_DEFUN' => 1,
|
||||||
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
|
'_LT_DLL_DEF_P' => 1,
|
||||||
|
'LT_PROG_GO' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'AM_DISABLE_STATIC' => 1,
|
||||||
|
'AC_CHECK_LIBM' => 1,
|
||||||
|
'_AM_SET_OPTIONS' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'LT_AC_PROG_RC' => 1,
|
||||||
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'_AM_PROG_CC_C_O' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'_LT_WITH_SYSROOT' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'LT_OUTPUT' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'AM_PROG_NM' => 1,
|
||||||
|
'LT_WITH_LTDL' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'_LT_PROG_CXX' => 1,
|
||||||
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
|
'LTSUGAR_VERSION' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' ),
|
], 'Autom4te::Request' ),
|
||||||
bless( [
|
bless( [
|
||||||
@ -263,186 +263,186 @@
|
|||||||
'configure.ac'
|
'configure.ac'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'AC_LTDL_ENABLE_INSTALL' => 1,
|
|
||||||
'LT_WITH_LTDL' => 1,
|
|
||||||
'AC_LTDL_DLSYM_USCORE' => 1,
|
|
||||||
'_LT_COMPILER_OPTION' => 1,
|
|
||||||
'LTSUGAR_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
|
||||||
'LT_PATH_LD' => 1,
|
|
||||||
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'_LT_AC_TAGVAR' => 1,
|
|
||||||
'LT_OUTPUT' => 1,
|
|
||||||
'_AM_MANGLE_OPTION' => 1,
|
|
||||||
'LTVERSION_VERSION' => 1,
|
|
||||||
'_AM_PROG_CC_C_O' => 1,
|
|
||||||
'LTOBSOLETE_VERSION' => 1,
|
|
||||||
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'AM_RUN_LOG' => 1,
|
|
||||||
'AC_LIBTOOL_WIN32_DLL' => 1,
|
|
||||||
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
|
||||||
'_LT_DLL_DEF_P' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
|
||||||
'LT_AC_PROG_EGREP' => 1,
|
|
||||||
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
|
||||||
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
|
||||||
'AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
|
||||||
'_LTDL_SETUP' => 1,
|
|
||||||
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
|
||||||
'AM_DISABLE_STATIC' => 1,
|
|
||||||
'LT_PROG_GO' => 1,
|
|
||||||
'_LT_LINKER_BOILERPLATE' => 1,
|
|
||||||
'AM_PROG_LIBTOOL' => 1,
|
|
||||||
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
|
||||||
'AC_LTDL_SHLIBEXT' => 1,
|
|
||||||
'_LT_AC_SHELL_INIT' => 1,
|
|
||||||
'AM_PROG_LD' => 1,
|
|
||||||
'AM_SILENT_RULES' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
|
||||||
'AC_DISABLE_FAST_INSTALL' => 1,
|
|
||||||
'_LT_WITH_SYSROOT' => 1,
|
|
||||||
'AC_PROG_EGREP' => 1,
|
|
||||||
'_LT_AC_SYS_COMPILER' => 1,
|
|
||||||
'LT_CMD_MAX_LEN' => 1,
|
|
||||||
'AC_LIBLTDL_INSTALLABLE' => 1,
|
|
||||||
'LTDL_INIT' => 1,
|
|
||||||
'AC_ENABLE_SHARED' => 1,
|
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR' => 1,
|
|
||||||
'_LT_LINKER_OPTION' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
|
||||||
'AC_DISABLE_SHARED' => 1,
|
|
||||||
'AM_ENABLE_SHARED' => 1,
|
|
||||||
'LT_PROG_GCJ' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN' => 1,
|
|
||||||
'_LT_AC_LOCK' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
|
||||||
'AC_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AC_CHECK_LIBM' => 1,
|
|
||||||
'AC_LTDL_SHLIBPATH' => 1,
|
|
||||||
'LT_LIB_M' => 1,
|
|
||||||
'AC_LIBLTDL_CONVENIENCE' => 1,
|
|
||||||
'LT_SYS_SYMBOL_USCORE' => 1,
|
|
||||||
'LT_FUNC_ARGZ' => 1,
|
'LT_FUNC_ARGZ' => 1,
|
||||||
'_LT_LIBOBJ' => 1,
|
'AM_SANITY_CHECK' => 1,
|
||||||
'm4_pattern_forbid' => 1,
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
'_LT_AC_LANG_C_CONFIG' => 1,
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
'AM_DISABLE_SHARED' => 1,
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
'_LT_PROG_F77' => 1,
|
|
||||||
'AM_PROG_NM' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
|
||||||
'AC_LIBTOOL_SETUP' => 1,
|
|
||||||
'_LT_CC_BASENAME' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
|
||||||
'_LT_AC_CHECK_DLFCN' => 1,
|
|
||||||
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
|
||||||
'AC_LIBTOOL_CXX' => 1,
|
|
||||||
'AC_LIBTOOL_GCJ' => 1,
|
|
||||||
'LT_SYS_DLOPEN_SELF' => 1,
|
|
||||||
'LT_PROG_RC' => 1,
|
|
||||||
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
|
||||||
'AU_DEFUN' => 1,
|
|
||||||
'AC_LIBTOOL_PICMODE' => 1,
|
|
||||||
'_AM_SET_OPTIONS' => 1,
|
|
||||||
'LT_AC_PROG_SED' => 1,
|
|
||||||
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
|
||||||
'AC_DEFUN_ONCE' => 1,
|
|
||||||
'AC_WITH_LTDL' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
|
||||||
'_AM_AUTOCONF_VERSION' => 1,
|
|
||||||
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
|
||||||
'AM_SET_DEPDIR' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'_LT_AC_LANG_CXX' => 1,
|
|
||||||
'_AM_SET_OPTION' => 1,
|
|
||||||
'AM_ENABLE_STATIC' => 1,
|
|
||||||
'AC_PROG_NM' => 1,
|
|
||||||
'_LT_PROG_CXX' => 1,
|
|
||||||
'_LT_AC_LANG_F77' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
|
||||||
'AC_LIBTOOL_FC' => 1,
|
|
||||||
'_LT_PROG_LTMAIN' => 1,
|
|
||||||
'LT_AC_PROG_RC' => 1,
|
|
||||||
'AC_PROG_LD_GNU' => 1,
|
|
||||||
'LT_AC_PROG_GCJ' => 1,
|
|
||||||
'm4_include' => 1,
|
|
||||||
'AC_LTDL_SYSSEARCHPATH' => 1,
|
|
||||||
'AM_PROG_INSTALL_SH' => 1,
|
|
||||||
'AC_LTDL_PREOPEN' => 1,
|
|
||||||
'AC_DEFUN' => 1,
|
'AC_DEFUN' => 1,
|
||||||
'_LT_AC_PROG_CXXCPP' => 1,
|
'AC_DEFUN_ONCE' => 1,
|
||||||
'AM_AUX_DIR_EXPAND' => 1,
|
|
||||||
'AC_LIBTOOL_OBJDIR' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'_AM_PROG_TAR' => 1,
|
|
||||||
'include' => 1,
|
|
||||||
'AC_PATH_MAGIC' => 1,
|
|
||||||
'_LT_PROG_FC' => 1,
|
|
||||||
'LT_FUNC_DLSYM_USCORE' => 1,
|
|
||||||
'AM_PROG_INSTALL_STRIP' => 1,
|
|
||||||
'LT_LIB_DLLOAD' => 1,
|
|
||||||
'AC_LTDL_OBJDIR' => 1,
|
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
|
||||||
'LT_LANG' => 1,
|
|
||||||
'_AC_PROG_LIBTOOL' => 1,
|
|
||||||
'AC_LIB_LTDL' => 1,
|
|
||||||
'AM_MISSING_PROG' => 1,
|
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'_m4_warn' => 1,
|
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
|
||||||
'AC_PROG_LD' => 1,
|
|
||||||
'LT_PATH_NM' => 1,
|
|
||||||
'LTOPTIONS_VERSION' => 1,
|
|
||||||
'_LT_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AM_SET_LEADING_DOT' => 1,
|
|
||||||
'AC_ENABLE_FAST_INSTALL' => 1,
|
|
||||||
'_AM_CONFIG_MACRO_DIRS' => 1,
|
|
||||||
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
|
||||||
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
|
||||||
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
'AM_CONDITIONAL' => 1,
|
'AM_CONDITIONAL' => 1,
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
'_AM_CONFIG_MACRO_DIRS' => 1,
|
||||||
'AM_MAKE_INCLUDE' => 1,
|
'AC_PROG_NM' => 1,
|
||||||
'LT_INIT' => 1,
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
'LT_LIB_DLLOAD' => 1,
|
||||||
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
'AC_LIBTOOL_CONFIG' => 1,
|
'_LT_DLL_DEF_P' => 1,
|
||||||
'LT_SYS_DLSEARCH_PATH' => 1,
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
'_LT_AC_LANG_F77_CONFIG' => 1,
|
'AU_DEFUN' => 1,
|
||||||
'AM_DEP_TRACK' => 1,
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
'LTDL_INSTALLABLE' => 1,
|
|
||||||
'LT_SYS_MODULE_PATH' => 1,
|
|
||||||
'_AM_DEPENDENCIES' => 1,
|
|
||||||
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
|
||||||
'AC_LIBTOOL_F77' => 1,
|
|
||||||
'AC_LIBTOOL_RC' => 1,
|
|
||||||
'_LT_AC_LANG_RC_CONFIG' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'_AM_IF_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'AM_SILENT_RULES' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'_LT_CC_BASENAME' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'_AM_DEPENDENCIES' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
|
'LT_AC_PROG_RC' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'_AM_PROG_CC_C_O' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'_LT_WITH_SYSROOT' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
|
'LT_WITH_LTDL' => 1,
|
||||||
|
'AM_PROG_NM' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'LT_OUTPUT' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'_LT_PROG_CXX' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
||||||
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1,
|
||||||
|
'LTSUGAR_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'AM_DISABLE_STATIC' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'LT_PROG_GO' => 1,
|
||||||
|
'_AM_SET_OPTIONS' => 1,
|
||||||
|
'AC_CHECK_LIBM' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
'AC_ENABLE_STATIC' => 1,
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'AM_DEP_TRACK' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'AM_ENABLE_STATIC' => 1,
|
||||||
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'LTDL_INIT' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AC_DISABLE_SHARED' => 1,
|
||||||
|
'AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
|
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'_LTDL_SETUP' => 1,
|
||||||
|
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
'AC_LTDL_SYMBOL_USCORE' => 1,
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
'AC_LTDL_DLLIB' => 1,
|
'AC_LTDL_DLLIB' => 1,
|
||||||
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
'_m4_warn' => 1,
|
||||||
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
'LTDL_CONVENIENCE' => 1,
|
'AM_MISSING_PROG' => 1,
|
||||||
'AM_PROG_CC_C_O' => 1,
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
'_LT_COMPILER_BOILERPLATE' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ' => 1,
|
|
||||||
'AM_MISSING_HAS_RUN' => 1,
|
|
||||||
'_LT_AC_FILE_LTDLL_C' => 1,
|
|
||||||
'LT_SYS_MODULE_EXT' => 1,
|
|
||||||
'AC_DISABLE_STATIC' => 1,
|
'AC_DISABLE_STATIC' => 1,
|
||||||
'AM_SANITY_CHECK' => 1,
|
'AC_CONFIG_MACRO_DIR' => 1,
|
||||||
'_AM_IF_OPTION' => 1
|
'AM_DISABLE_SHARED' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'_LT_PROG_F77' => 1,
|
||||||
|
'_LT_AC_PROG_CXXCPP' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_PROG_FC' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'AC_LTDL_SHLIBPATH' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' ),
|
], 'Autom4te::Request' ),
|
||||||
bless( [
|
bless( [
|
||||||
@ -457,65 +457,65 @@
|
|||||||
'configure.ac'
|
'configure.ac'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
|
||||||
'AC_FC_FREEFORM' => 1,
|
|
||||||
'AC_REQUIRE_AUX_FILE' => 1,
|
|
||||||
'AC_CANONICAL_TARGET' => 1,
|
|
||||||
'AC_SUBST' => 1,
|
|
||||||
'm4_include' => 1,
|
|
||||||
'AC_CONFIG_AUX_DIR' => 1,
|
|
||||||
'AC_FC_PP_SRCEXT' => 1,
|
|
||||||
'AM_PROG_CXX_C_O' => 1,
|
|
||||||
'AC_CONFIG_FILES' => 1,
|
|
||||||
'm4_pattern_forbid' => 1,
|
|
||||||
'AC_CONFIG_LINKS' => 1,
|
|
||||||
'AC_DEFINE_TRACE_LITERAL' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'_AM_COND_ENDIF' => 1,
|
|
||||||
'AM_ENABLE_MULTILIB' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'sinclude' => 1,
|
|
||||||
'AC_CANONICAL_BUILD' => 1,
|
|
||||||
'AM_PROG_AR' => 1,
|
|
||||||
'AC_FC_PP_DEFINE' => 1,
|
|
||||||
'AC_CONFIG_HEADERS' => 1,
|
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
|
||||||
'AM_POT_TOOLS' => 1,
|
|
||||||
'AM_CONDITIONAL' => 1,
|
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
|
||||||
'AM_XGETTEXT_OPTION' => 1,
|
|
||||||
'_AM_MAKEFILE_INCLUDE' => 1,
|
|
||||||
'_AM_COND_IF' => 1,
|
|
||||||
'LT_INIT' => 1,
|
|
||||||
'AM_PROG_F77_C_O' => 1,
|
|
||||||
'AM_MAKEFILE_INCLUDE' => 1,
|
|
||||||
'AC_CONFIG_SUBDIRS' => 1,
|
|
||||||
'AC_SUBST_TRACE' => 1,
|
'AC_SUBST_TRACE' => 1,
|
||||||
'AM_PROG_MKDIR_P' => 1,
|
'm4_pattern_allow' => 1,
|
||||||
'AM_NLS' => 1,
|
|
||||||
'AM_SILENT_RULES' => 1,
|
|
||||||
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
|
|
||||||
'_AM_COND_ELSE' => 1,
|
|
||||||
'AC_INIT' => 1,
|
|
||||||
'AC_FC_SRCEXT' => 1,
|
|
||||||
'AM_PATH_GUILE' => 1,
|
|
||||||
'AC_CANONICAL_HOST' => 1,
|
|
||||||
'm4_sinclude' => 1,
|
|
||||||
'AC_CANONICAL_SYSTEM' => 1,
|
|
||||||
'AM_GNU_GETTEXT' => 1,
|
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
'AC_FC_PP_SRCEXT' => 1,
|
||||||
'AH_OUTPUT' => 1,
|
'AC_CANONICAL_SYSTEM' => 1,
|
||||||
'AM_PROG_MOC' => 1,
|
'AC_CONFIG_FILES' => 1,
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
'AC_FC_SRCEXT' => 1,
|
||||||
'include' => 1,
|
'AC_CONFIG_AUX_DIR' => 1,
|
||||||
'AC_LIBSOURCE' => 1,
|
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
|
||||||
'AM_PROG_FC_C_O' => 1,
|
'AM_PROG_FC_C_O' => 1,
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
'AC_CANONICAL_BUILD' => 1,
|
||||||
'_m4_warn' => 1,
|
'AC_CANONICAL_TARGET' => 1,
|
||||||
|
'AM_ENABLE_MULTILIB' => 1,
|
||||||
|
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
|
||||||
|
'AM_PROG_MOC' => 1,
|
||||||
|
'AC_REQUIRE_AUX_FILE' => 1,
|
||||||
|
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
||||||
|
'AH_OUTPUT' => 1,
|
||||||
|
'AM_PROG_CXX_C_O' => 1,
|
||||||
|
'AC_FC_FREEFORM' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'_AM_COND_ENDIF' => 1,
|
||||||
|
'AM_PROG_MKDIR_P' => 1,
|
||||||
|
'AM_MAKEFILE_INCLUDE' => 1,
|
||||||
|
'AM_SILENT_RULES' => 1,
|
||||||
|
'AC_CONFIG_HEADERS' => 1,
|
||||||
|
'_AM_MAKEFILE_INCLUDE' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'AC_FC_PP_DEFINE' => 1,
|
||||||
|
'_AM_COND_IF' => 1,
|
||||||
|
'AM_GNU_GETTEXT' => 1,
|
||||||
|
'AC_CONFIG_SUBDIRS' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AM_PROG_AR' => 1,
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
'AM_PROG_CC_C_O' => 1
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'AM_PATH_GUILE' => 1,
|
||||||
|
'AC_DEFINE_TRACE_LITERAL' => 1,
|
||||||
|
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
||||||
|
'AM_POT_TOOLS' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'm4_sinclude' => 1,
|
||||||
|
'_AM_COND_ELSE' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION' => 1,
|
||||||
|
'AC_LIBSOURCE' => 1,
|
||||||
|
'AC_INIT' => 1,
|
||||||
|
'sinclude' => 1,
|
||||||
|
'AM_NLS' => 1,
|
||||||
|
'AC_SUBST' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'AC_CONFIG_LINKS' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AM_PROG_F77_C_O' => 1,
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AC_CANONICAL_HOST' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' )
|
], 'Autom4te::Request' )
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2746,18 +2746,19 @@ m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
|||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^vfork$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^vfork$])
|
||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
||||||
m4trace:configure.ac:255: -1- m4_pattern_allow([^DEBUG$])
|
m4trace:configure.ac:242: -1- m4_pattern_allow([^HAVE_LIBRT$])
|
||||||
m4trace:configure.ac:269: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:259: -1- m4_pattern_allow([^DEBUG$])
|
||||||
m4trace:configure.ac:270: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:273: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:271: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:274: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:272: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:275: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:276: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:283: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:287: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:283: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:283: -1- _LT_PROG_LTMAIN
|
m4trace:configure.ac:287: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
||||||
m4trace:configure.ac:283: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
m4trace:configure.ac:287: -1- _LT_PROG_LTMAIN
|
||||||
|
m4trace:configure.ac:287: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||||
|
|||||||
@ -2746,18 +2746,19 @@ m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
|||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^vfork$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^vfork$])
|
||||||
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
m4trace:configure.ac:224: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
||||||
m4trace:configure.ac:255: -1- m4_pattern_allow([^DEBUG$])
|
m4trace:configure.ac:242: -1- m4_pattern_allow([^HAVE_LIBRT$])
|
||||||
m4trace:configure.ac:269: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:259: -1- m4_pattern_allow([^DEBUG$])
|
||||||
m4trace:configure.ac:270: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:273: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:271: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:274: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:272: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:275: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:276: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:283: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:287: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:283: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:283: -1- _LT_PROG_LTMAIN
|
m4trace:configure.ac:287: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
||||||
m4trace:configure.ac:283: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
m4trace:configure.ac:287: -1- _LT_PROG_LTMAIN
|
||||||
|
m4trace:configure.ac:287: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||||
|
|||||||
@ -3,7 +3,7 @@ m4trace:aclocal.m4:1190: -1- m4_include([config/m4/ltoptions.m4])
|
|||||||
m4trace:aclocal.m4:1191: -1- m4_include([config/m4/ltsugar.m4])
|
m4trace:aclocal.m4:1191: -1- m4_include([config/m4/ltsugar.m4])
|
||||||
m4trace:aclocal.m4:1192: -1- m4_include([config/m4/ltversion.m4])
|
m4trace:aclocal.m4:1192: -1- m4_include([config/m4/ltversion.m4])
|
||||||
m4trace:aclocal.m4:1193: -1- m4_include([config/m4/lt~obsolete.m4])
|
m4trace:aclocal.m4:1193: -1- m4_include([config/m4/lt~obsolete.m4])
|
||||||
m4trace:configure.ac:27: -1- AC_INIT([mtrace-ng], [0.4], [stefani@seibold.net])
|
m4trace:configure.ac:27: -1- AC_INIT([mtrace-ng], [0.5], [stefani@seibold.net])
|
||||||
m4trace:configure.ac:27: -1- m4_pattern_forbid([^_?A[CHUM]_])
|
m4trace:configure.ac:27: -1- m4_pattern_forbid([^_?A[CHUM]_])
|
||||||
m4trace:configure.ac:27: -1- m4_pattern_forbid([_AC_])
|
m4trace:configure.ac:27: -1- m4_pattern_forbid([_AC_])
|
||||||
m4trace:configure.ac:27: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
|
m4trace:configure.ac:27: -1- m4_pattern_forbid([^LIBOBJS$], [do not use LIBOBJS directly, use AC_LIBOBJ (see section `AC_LIBOBJ vs LIBOBJS'])
|
||||||
@ -655,6 +655,8 @@ m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you ha
|
|||||||
@%:@undef HAVE_GETCWD])
|
@%:@undef HAVE_GETCWD])
|
||||||
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
|
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
|
||||||
@%:@undef HAVE_GETTIMEOFDAY])
|
@%:@undef HAVE_GETTIMEOFDAY])
|
||||||
|
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_CLOCK_GETTIME], [/* Define to 1 if you have the `clock_gettime\' function. */
|
||||||
|
@%:@undef HAVE_CLOCK_GETTIME])
|
||||||
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
|
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
|
||||||
@%:@undef HAVE_MEMSET])
|
@%:@undef HAVE_MEMSET])
|
||||||
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_MKDIR], [/* Define to 1 if you have the `mkdir\' function. */
|
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_MKDIR], [/* Define to 1 if you have the `mkdir\' function. */
|
||||||
@ -673,23 +675,27 @@ m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you h
|
|||||||
@%:@undef HAVE_STRTOUL])
|
@%:@undef HAVE_STRTOUL])
|
||||||
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_PROCESS_VM_READV], [/* Define to 1 if you have the `process_vm_readv\' function. */
|
m4trace:configure.ac:225: -1- AH_OUTPUT([HAVE_PROCESS_VM_READV], [/* Define to 1 if you have the `process_vm_readv\' function. */
|
||||||
@%:@undef HAVE_PROCESS_VM_READV])
|
@%:@undef HAVE_PROCESS_VM_READV])
|
||||||
m4trace:configure.ac:255: -1- AC_DEFINE_TRACE_LITERAL([DEBUG])
|
m4trace:configure.ac:242: -1- AH_OUTPUT([HAVE_LIBRT], [/* Define to 1 if you have the `rt\' library (-lrt). */
|
||||||
m4trace:configure.ac:255: -1- m4_pattern_allow([^DEBUG$])
|
@%:@undef HAVE_LIBRT])
|
||||||
m4trace:configure.ac:255: -1- AH_OUTPUT([DEBUG], [/* debugging */
|
m4trace:configure.ac:242: -1- AC_DEFINE_TRACE_LITERAL([HAVE_LIBRT])
|
||||||
|
m4trace:configure.ac:242: -1- m4_pattern_allow([^HAVE_LIBRT$])
|
||||||
|
m4trace:configure.ac:259: -1- AC_DEFINE_TRACE_LITERAL([DEBUG])
|
||||||
|
m4trace:configure.ac:259: -1- m4_pattern_allow([^DEBUG$])
|
||||||
|
m4trace:configure.ac:259: -1- AH_OUTPUT([DEBUG], [/* debugging */
|
||||||
@%:@undef DEBUG])
|
@%:@undef DEBUG])
|
||||||
m4trace:configure.ac:269: -1- AC_SUBST([AM_CPPFLAGS])
|
m4trace:configure.ac:273: -1- AC_SUBST([AM_CPPFLAGS])
|
||||||
m4trace:configure.ac:269: -1- AC_SUBST_TRACE([AM_CPPFLAGS])
|
m4trace:configure.ac:273: -1- AC_SUBST_TRACE([AM_CPPFLAGS])
|
||||||
m4trace:configure.ac:269: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:273: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:270: -1- AC_SUBST([AM_CFLAGS])
|
m4trace:configure.ac:274: -1- AC_SUBST([AM_CFLAGS])
|
||||||
m4trace:configure.ac:270: -1- AC_SUBST_TRACE([AM_CFLAGS])
|
m4trace:configure.ac:274: -1- AC_SUBST_TRACE([AM_CFLAGS])
|
||||||
m4trace:configure.ac:270: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:274: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:271: -1- AC_SUBST([AM_LDFLAGS])
|
m4trace:configure.ac:275: -1- AC_SUBST([AM_LDFLAGS])
|
||||||
m4trace:configure.ac:271: -1- AC_SUBST_TRACE([AM_LDFLAGS])
|
m4trace:configure.ac:275: -1- AC_SUBST_TRACE([AM_LDFLAGS])
|
||||||
m4trace:configure.ac:271: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:275: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:272: -1- AC_SUBST([libelf_LD_LIBRARY_PATH])
|
m4trace:configure.ac:276: -1- AC_SUBST([libelf_LD_LIBRARY_PATH])
|
||||||
m4trace:configure.ac:272: -1- AC_SUBST_TRACE([libelf_LD_LIBRARY_PATH])
|
m4trace:configure.ac:276: -1- AC_SUBST_TRACE([libelf_LD_LIBRARY_PATH])
|
||||||
m4trace:configure.ac:272: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:276: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:274: -1- AC_CONFIG_FILES([
|
m4trace:configure.ac:278: -1- AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
client/Makefile
|
client/Makefile
|
||||||
sysdeps/Makefile
|
sysdeps/Makefile
|
||||||
@ -698,30 +704,30 @@ m4trace:configure.ac:274: -1- AC_CONFIG_FILES([
|
|||||||
sysdeps/linux-gnu/ppc/Makefile
|
sysdeps/linux-gnu/ppc/Makefile
|
||||||
sysdeps/linux-gnu/arm/Makefile
|
sysdeps/linux-gnu/arm/Makefile
|
||||||
])
|
])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
|
m4trace:configure.ac:287: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
|
m4trace:configure.ac:287: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([LTLIBOBJS])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([LTLIBOBJS])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:283: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:287: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST([am__EXEEXT_TRUE])
|
m4trace:configure.ac:287: -1- AC_SUBST([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST([am__EXEEXT_FALSE])
|
m4trace:configure.ac:287: -1- AC_SUBST([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:283: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:287: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:283: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:287: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([top_builddir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([top_builddir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([top_build_prefix])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([top_build_prefix])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([srcdir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([srcdir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([abs_srcdir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([abs_srcdir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([top_srcdir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([top_srcdir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([abs_top_srcdir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([abs_top_srcdir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([builddir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([builddir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([abs_builddir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([abs_builddir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([abs_top_builddir])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([abs_top_builddir])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([INSTALL])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([INSTALL])
|
||||||
m4trace:configure.ac:283: -1- AC_SUBST_TRACE([MKDIR_P])
|
m4trace:configure.ac:287: -1- AC_SUBST_TRACE([MKDIR_P])
|
||||||
m4trace:configure.ac:283: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
|
m4trace:configure.ac:287: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
|
||||||
|
|||||||
69
backtrace.h
69
backtrace.h
@ -23,25 +23,82 @@
|
|||||||
#ifndef _INC_BACKTRACE_H
|
#ifndef _INC_BACKTRACE_H
|
||||||
#define _INC_BACKTRACE_H
|
#define _INC_BACKTRACE_H
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "dwarf.h"
|
||||||
|
#include "main.h"
|
||||||
|
#include "options.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
/* init backtrace for given leader task */
|
/* init backtrace for given leader task */
|
||||||
int backtrace_init(struct task *task);
|
static inline int backtrace_init(struct task *task)
|
||||||
|
{
|
||||||
|
assert(task->leader == task);
|
||||||
|
assert(task->backtrace == NULL);
|
||||||
|
|
||||||
|
task->backtrace = dwarf_init(task->is_64bit);
|
||||||
|
|
||||||
|
return task->backtrace != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* destroy backtrace for given leader task */
|
/* destroy backtrace for given leader task */
|
||||||
void backtrace_destroy(struct task *task);
|
static inline void backtrace_destroy(struct task *task)
|
||||||
|
{
|
||||||
|
assert(task->leader == task);
|
||||||
|
|
||||||
|
if (task->backtrace) {
|
||||||
|
dwarf_destroy(task->backtrace);
|
||||||
|
|
||||||
|
task->backtrace = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* start backtrace for given task */
|
/* start backtrace for given task */
|
||||||
int backtrace_init_unwind(struct task *task);
|
static inline int backtrace_init_unwind(struct task *task)
|
||||||
|
{
|
||||||
|
assert(task->leader);
|
||||||
|
assert(task->leader->backtrace);
|
||||||
|
|
||||||
|
return dwarf_init_unwind(task->leader->backtrace, task);
|
||||||
|
}
|
||||||
|
|
||||||
/* get backtrace IP address for given task */
|
/* get backtrace IP address for given task */
|
||||||
unsigned long backtrace_get_ip(struct task *task);
|
static inline unsigned long backtrace_get_ip(struct task *task)
|
||||||
|
{
|
||||||
|
assert(task->leader);
|
||||||
|
assert(task->leader->backtrace);
|
||||||
|
|
||||||
|
return dwarf_get_ip(task->leader->backtrace);
|
||||||
|
}
|
||||||
|
|
||||||
/* step to next backtrace given task */
|
/* step to next backtrace given task */
|
||||||
int backtrace_step(struct task *task);
|
static inline int backtrace_step(struct task *task)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
|
assert(task->leader);
|
||||||
|
assert(task->leader->backtrace);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
|
ret = dwarf_step(task->leader->backtrace);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &backtrace_time);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/* get backtrace location type of given task */
|
/* get backtrace location type of given task */
|
||||||
int backtrace_location_type(struct task *task);
|
static inline int backtrace_location_type(struct task *task)
|
||||||
|
{
|
||||||
|
assert(task->leader);
|
||||||
|
assert(task->leader->backtrace);
|
||||||
|
|
||||||
|
return dwarf_location_type(task->leader->backtrace);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
36
breakpoint.c
36
breakpoint.c
@ -108,7 +108,7 @@ static void enable_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
task->hw_bp[slot] = bp;
|
task->hw_bp[slot] = bp;
|
||||||
|
|
||||||
if (set_hw_bp(task, slot, bp->addr) == -1)
|
if (unlikely(set_hw_bp(task, slot, bp->addr) == -1))
|
||||||
fatal("set_hw_bp");
|
fatal("set_hw_bp");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,12 +116,12 @@ static void disable_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
{
|
{
|
||||||
unsigned int slot = bp->hw_bp_slot;
|
unsigned int slot = bp->hw_bp_slot;
|
||||||
|
|
||||||
if (!task->hw_bp[slot])
|
if (unlikely(!task->hw_bp[slot]))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(task->hw_bp[slot] == bp);
|
assert(task->hw_bp[slot] == bp);
|
||||||
|
|
||||||
if (reset_hw_bp(task, slot) == -1)
|
if (unlikely(reset_hw_bp(task, slot) == -1))
|
||||||
fatal("reset_hw_bp");
|
fatal("reset_hw_bp");
|
||||||
|
|
||||||
task->hw_bp[slot] = NULL;
|
task->hw_bp[slot] = NULL;
|
||||||
@ -286,10 +286,10 @@ void breakpoint_hw_destroy(struct task *task)
|
|||||||
|
|
||||||
void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp->deleted)
|
if (unlikely(bp->deleted))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bp->type != BP_HW_SCRATCH)
|
if (unlikely(bp->type != BP_HW_SCRATCH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
||||||
@ -300,10 +300,10 @@ void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp->deleted)
|
if (unlikely(bp->deleted))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bp->type != BP_HW_SCRATCH)
|
if (unlikely(bp->type != BP_HW_SCRATCH))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
||||||
@ -385,12 +385,12 @@ struct breakpoint *breakpoint_new(struct task *task, arch_addr_t addr, struct li
|
|||||||
|
|
||||||
void breakpoint_enable(struct task *task, struct breakpoint *bp)
|
void breakpoint_enable(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp->deleted)
|
if (unlikely(bp->deleted))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
||||||
|
|
||||||
if (!bp->enabled) {
|
if (likely(!bp->enabled)) {
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
if (bp->type == BP_HW_SCRATCH) {
|
if (bp->type == BP_HW_SCRATCH) {
|
||||||
bp->enabled = 1;
|
bp->enabled = 1;
|
||||||
@ -412,12 +412,12 @@ void breakpoint_enable(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
void breakpoint_disable(struct task *task, struct breakpoint *bp)
|
void breakpoint_disable(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp->deleted)
|
if (unlikely(bp->deleted))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
debug(DEBUG_PROCESS, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
||||||
|
|
||||||
if (bp->enabled) {
|
if (likely(bp->enabled)) {
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
if (bp->hw) {
|
if (bp->hw) {
|
||||||
struct task *leader = task->leader;
|
struct task *leader = task->leader;
|
||||||
@ -449,13 +449,13 @@ struct breakpoint *breakpoint_insert(struct task *task, arch_addr_t addr, struct
|
|||||||
{
|
{
|
||||||
debug(DEBUG_FUNCTION, "pid=%d, addr=%lx, symbol=%s", task->pid, addr, libsym ? libsym->func->name : "NULL");
|
debug(DEBUG_FUNCTION, "pid=%d, addr=%lx, symbol=%s", task->pid, addr, libsym ? libsym->func->name : "NULL");
|
||||||
|
|
||||||
if (!addr)
|
if (unlikely(!addr))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
struct breakpoint *bp = breakpoint_find(task, addr);
|
struct breakpoint *bp = breakpoint_find(task, addr);
|
||||||
if (!bp) {
|
if (unlikely(!bp)) {
|
||||||
bp = breakpoint_new(task, addr, libsym, type);
|
bp = breakpoint_new(task, addr, libsym, type);
|
||||||
if (!bp)
|
if (unlikely(!bp))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -484,7 +484,7 @@ void breakpoint_delete(struct task *task, struct breakpoint *bp)
|
|||||||
#endif
|
#endif
|
||||||
dict_remove_entry(leader->breakpoints, (unsigned long)bp->addr);
|
dict_remove_entry(leader->breakpoints, (unsigned long)bp->addr);
|
||||||
|
|
||||||
if (options.verbose > 1 && bp->libsym) {
|
if (unlikely(options.verbose > 1 && bp->libsym)) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"delete %s breakpoint %s:%s [%#lx] count=%u\n",
|
"delete %s breakpoint %s:%s [%#lx] count=%u\n",
|
||||||
bp->type == BP_SW ? "sw" : "hw",
|
bp->type == BP_SW ? "sw" : "hw",
|
||||||
@ -662,7 +662,7 @@ static int clone_single_cb(unsigned long key, const void *value, void *data)
|
|||||||
new_task->hw_bp[new_bp->hw_bp_slot] = new_bp;
|
new_task->hw_bp[new_bp->hw_bp_slot] = new_bp;
|
||||||
|
|
||||||
if (new_bp->enabled) {
|
if (new_bp->enabled) {
|
||||||
if (set_hw_bp(new_task, new_bp->hw_bp_slot, new_bp->addr) == -1)
|
if (unlikely(set_hw_bp(new_task, new_bp->hw_bp_slot, new_bp->addr) == -1))
|
||||||
fatal("set_hw_bp");
|
fatal("set_hw_bp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -692,14 +692,14 @@ int breakpoint_clone_all(struct task *clone, struct task *leader)
|
|||||||
|
|
||||||
struct breakpoint *breakpoint_get(struct breakpoint *bp)
|
struct breakpoint *breakpoint_get(struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp)
|
if (likely(bp))
|
||||||
++bp->refcnt;
|
++bp->refcnt;
|
||||||
return bp;
|
return bp;
|
||||||
}
|
}
|
||||||
|
|
||||||
int breakpoint_put(struct breakpoint *bp)
|
int breakpoint_put(struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
if (bp) {
|
if (likely(bp)) {
|
||||||
assert(bp->refcnt != 0);
|
assert(bp->refcnt != 0);
|
||||||
|
|
||||||
if (--bp->refcnt)
|
if (--bp->refcnt)
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
|
||||||
#define BP_REORDER_THRESHOLD 1024U
|
#define BP_REORDER_THRESHOLD 2048U
|
||||||
|
|
||||||
#define BP_SW 0
|
#define BP_SW 0
|
||||||
#define BP_HW_SCRATCH 1
|
#define BP_HW_SCRATCH 1
|
||||||
|
|||||||
125
client/client.c
125
client/client.c
@ -224,7 +224,7 @@ static int parse_config(const char *filename)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rb_process *pid_rb_search(struct rb_root *root, pid_t pid)
|
static struct rb_process *pid_rb_search(struct rb_root *root, unsigned int pid)
|
||||||
{
|
{
|
||||||
struct rb_node *node = root->rb_node;
|
struct rb_node *node = root->rb_node;
|
||||||
|
|
||||||
@ -241,7 +241,7 @@ static struct rb_process *pid_rb_search(struct rb_root *root, pid_t pid)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct process *pid_rb_delete(struct rb_root *root, pid_t pid)
|
static struct process *pid_rb_delete(struct rb_root *root, unsigned int pid)
|
||||||
{
|
{
|
||||||
struct rb_process *data = pid_rb_search(root, pid);
|
struct rb_process *data = pid_rb_search(root, pid);
|
||||||
struct process *process;
|
struct process *process;
|
||||||
@ -289,35 +289,34 @@ static void swap_msg(struct mt_msg *mt_msg)
|
|||||||
{
|
{
|
||||||
mt_msg->operation = bswap_16(mt_msg->operation);
|
mt_msg->operation = bswap_16(mt_msg->operation);
|
||||||
mt_msg->payload_len = bswap_32(mt_msg->payload_len);
|
mt_msg->payload_len = bswap_32(mt_msg->payload_len);
|
||||||
mt_msg->pid = bswap_32(mt_msg->pid);
|
mt_msg->pid = bswap_16(mt_msg->pid);
|
||||||
mt_msg->tid = bswap_32(mt_msg->tid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_read_msg(struct mt_msg *mt_msg, void **payload, unsigned int *swap_endian)
|
static int socket_read_msg(struct mt_msg *mt_msg, void **payload, unsigned int *swap_endian)
|
||||||
{
|
{
|
||||||
|
size_t payload_len;
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY(safe_read(client_fd, mt_msg, sizeof(*mt_msg))) <= 0)
|
if (TEMP_FAILURE_RETRY(safe_read(client_fd, mt_msg, sizeof(*mt_msg))) <= 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if (mt_msg->operation > 0xff) {
|
*swap_endian = mt_msg->operation > 0xff;
|
||||||
|
|
||||||
|
if (*swap_endian)
|
||||||
swap_msg(mt_msg);
|
swap_msg(mt_msg);
|
||||||
|
|
||||||
*swap_endian = 1;
|
payload_len = mt_msg->payload_len;
|
||||||
}
|
|
||||||
else
|
|
||||||
*swap_endian = 0;
|
|
||||||
|
|
||||||
|
if (payload_len) {
|
||||||
|
*payload = malloc(payload_len);
|
||||||
|
|
||||||
if (mt_msg->payload_len) {
|
if (TEMP_FAILURE_RETRY(safe_read(client_fd, *payload, payload_len)) <= 0)
|
||||||
*payload = malloc(mt_msg->payload_len);
|
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY(safe_read(client_fd, *payload, mt_msg->payload_len)) <= 0)
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static pid_t pid_payload(struct process *process, void *payload)
|
static unsigned int pid_payload(struct process *process, void *payload)
|
||||||
{
|
{
|
||||||
struct mt_pid_payload *mt_pid = payload;
|
struct mt_pid_payload *mt_pid = payload;
|
||||||
|
|
||||||
@ -369,6 +368,14 @@ static void client_remove_process(struct process *process)
|
|||||||
free(process);
|
free(process);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void store_timer_info(struct memtrace_timer_info *dst, struct memtrace_timer_info *src)
|
||||||
|
{
|
||||||
|
dst->max = bswap_32(src->max);
|
||||||
|
dst->count = bswap_32(src->count);
|
||||||
|
dst->culminate = bswap_64(src->culminate);
|
||||||
|
}
|
||||||
|
|
||||||
static int client_func(void)
|
static int client_func(void)
|
||||||
{
|
{
|
||||||
struct mt_msg mt_msg;
|
struct mt_msg mt_msg;
|
||||||
@ -393,7 +400,27 @@ static int client_func(void)
|
|||||||
client_close();
|
client_close();
|
||||||
break;
|
break;
|
||||||
case MT_INFO:
|
case MT_INFO:
|
||||||
|
if (swap_endian) {
|
||||||
|
struct memtrace_info *p = payload;
|
||||||
|
|
||||||
|
mt_info.version = p->version;
|
||||||
|
mt_info.mode = p->mode;
|
||||||
|
mt_info.do_trace = p->do_trace;
|
||||||
|
mt_info.stack_depth = p->stack_depth;
|
||||||
|
mt_info.verbose = p->verbose;
|
||||||
|
|
||||||
|
store_timer_info(&mt_info.stop_time, &p->stop_time);
|
||||||
|
store_timer_info(&mt_info.sw_bp_time, &p->sw_bp_time);
|
||||||
|
store_timer_info(&mt_info.hw_bp_time, &p->hw_bp_time);
|
||||||
|
store_timer_info(&mt_info.backtrace_time, &p->backtrace_time);
|
||||||
|
store_timer_info(&mt_info.reorder_time, &p->reorder_time);
|
||||||
|
store_timer_info(&mt_info.report_in_time, &p->report_in_time);
|
||||||
|
store_timer_info(&mt_info.report_out_time, &p->report_out_time);
|
||||||
|
store_timer_info(&mt_info.skip_bp_time, &p->skip_bp_time);
|
||||||
|
}
|
||||||
|
else
|
||||||
memcpy(&mt_info, payload, sizeof(mt_info));
|
memcpy(&mt_info, payload, sizeof(mt_info));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fatal("protocol violation 0x%08x", mt_msg.operation);
|
fatal("protocol violation 0x%08x", mt_msg.operation);
|
||||||
@ -419,7 +446,6 @@ static int client_func(void)
|
|||||||
switch(mt_msg.operation) {
|
switch(mt_msg.operation) {
|
||||||
case MT_MALLOC:
|
case MT_MALLOC:
|
||||||
case MT_REALLOC:
|
case MT_REALLOC:
|
||||||
case MT_REALLOC_FAILED:
|
|
||||||
case MT_MEMALIGN:
|
case MT_MEMALIGN:
|
||||||
case MT_POSIX_MEMALIGN:
|
case MT_POSIX_MEMALIGN:
|
||||||
case MT_ALIGNED_ALLOC:
|
case MT_ALIGNED_ALLOC:
|
||||||
@ -431,6 +457,9 @@ static int client_func(void)
|
|||||||
case MT_NEW_ARRAY:
|
case MT_NEW_ARRAY:
|
||||||
process_alloc(process, &mt_msg, payload);
|
process_alloc(process, &mt_msg, payload);
|
||||||
break;
|
break;
|
||||||
|
case MT_REALLOC_DONE:
|
||||||
|
process_realloc_done(process, &mt_msg, payload);
|
||||||
|
break;
|
||||||
case MT_REALLOC_ENTER:
|
case MT_REALLOC_ENTER:
|
||||||
case MT_FREE:
|
case MT_FREE:
|
||||||
case MT_DELETE:
|
case MT_DELETE:
|
||||||
@ -487,16 +516,6 @@ static int client_func(void)
|
|||||||
return mt_msg.operation;
|
return mt_msg.operation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_show_info(void)
|
|
||||||
{
|
|
||||||
printf("memtrace info:\n");
|
|
||||||
printf(" follow fork: %s\n", mt_info.mode & MEMTRACE_SI_FORK ? "yes" : "no");
|
|
||||||
printf(" follow exec: %s\n", mt_info.mode & MEMTRACE_SI_EXEC ? "yes" : "no");
|
|
||||||
printf(" verbose: %s\n", mt_info.mode & MEMTRACE_SI_VERBOSE ? "yes" : "no");
|
|
||||||
printf(" do trace: %s\n", mt_info.do_trace ? "yes" : "no");
|
|
||||||
printf(" stack depth: %u\n", mt_info.stack_depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
int client_wait_op(enum mt_operation op)
|
int client_wait_op(enum mt_operation op)
|
||||||
{
|
{
|
||||||
if (options.logfile)
|
if (options.logfile)
|
||||||
@ -515,6 +534,52 @@ int client_wait_op(enum mt_operation op)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void show_timer_info(const char *str, struct memtrace_timer_info *info)
|
||||||
|
{
|
||||||
|
if (!info->count)
|
||||||
|
return;
|
||||||
|
|
||||||
|
printf(" %s\n count: %-9lu max. us: %-6lu culminate us:%-11llu average ns:%llu\n",
|
||||||
|
str,
|
||||||
|
(unsigned long)info->count,
|
||||||
|
(unsigned long)info->max,
|
||||||
|
(unsigned long long)info->culminate,
|
||||||
|
(unsigned long long)(info->culminate * 1000) / info->count
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_show_info(void)
|
||||||
|
{
|
||||||
|
printf("memtrace info:\n");
|
||||||
|
printf(" follow fork: %s\n", mt_info.mode & MEMTRACE_SI_FORK ? "yes" : "no");
|
||||||
|
printf(" follow exec: %s\n", mt_info.mode & MEMTRACE_SI_EXEC ? "yes" : "no");
|
||||||
|
printf(" verbose: %s\n", mt_info.mode & MEMTRACE_SI_VERBOSE ? "yes" : "no");
|
||||||
|
printf(" do trace: %s\n", mt_info.do_trace ? "yes" : "no");
|
||||||
|
printf(" stack depth: %u\n", mt_info.stack_depth);
|
||||||
|
|
||||||
|
if (mt_info.verbose > 1) {
|
||||||
|
show_timer_info("threads stop", &mt_info.stop_time);
|
||||||
|
show_timer_info("breakpoint sw", &mt_info.sw_bp_time);
|
||||||
|
show_timer_info("breakpoint hw", &mt_info.hw_bp_time);
|
||||||
|
show_timer_info("backtrace step", &mt_info.backtrace_time);
|
||||||
|
show_timer_info("reorder", &mt_info.reorder_time);
|
||||||
|
show_timer_info("report in", &mt_info.report_in_time);
|
||||||
|
show_timer_info("report out", &mt_info.report_out_time);
|
||||||
|
show_timer_info("skip breakpoint", &mt_info.skip_bp_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void client_request_info(void)
|
||||||
|
{
|
||||||
|
if (sock_send_msg(client_fd, MT_INFO, 0, NULL, 0) < 0) {
|
||||||
|
client_broken();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (client_wait_op(MT_INFO) < 0)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
static int client_iterate_process(struct rb_node *node, void *user)
|
static int client_iterate_process(struct rb_node *node, void *user)
|
||||||
{
|
{
|
||||||
struct rb_process *data = (struct rb_process *)node;
|
struct rb_process *data = (struct rb_process *)node;
|
||||||
@ -528,7 +593,7 @@ void client_iterate_processes(int (*func)(struct process *process))
|
|||||||
rb_iterate(&pid_table, client_iterate_process, func);
|
rb_iterate(&pid_table, client_iterate_process, func);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct process *client_find_process(pid_t pid)
|
struct process *client_find_process(unsigned int pid)
|
||||||
{
|
{
|
||||||
struct rb_process *data;
|
struct rb_process *data;
|
||||||
|
|
||||||
@ -608,6 +673,8 @@ int client_start(void)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ioevent_add_input(client_fd, client_func);
|
||||||
|
|
||||||
if (client_wait_op(MT_INFO) == -1) {
|
if (client_wait_op(MT_INFO) == -1) {
|
||||||
fprintf(stderr, "could not talk to server\n");
|
fprintf(stderr, "could not talk to server\n");
|
||||||
return -1;
|
return -1;
|
||||||
@ -625,8 +692,6 @@ int client_start(void)
|
|||||||
|
|
||||||
client_show_info();
|
client_show_info();
|
||||||
|
|
||||||
ioevent_add_input(client_fd, client_func);
|
|
||||||
|
|
||||||
if (options.interactive) {
|
if (options.interactive) {
|
||||||
int old_client_fd = client_fd;
|
int old_client_fd = client_fd;
|
||||||
|
|
||||||
@ -648,7 +713,7 @@ int client_start(void)
|
|||||||
readline_exit();
|
readline_exit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (pipe(pipefd) == -1) {
|
if (pipe2(pipefd, O_NONBLOCK | O_CLOEXEC) == -1) {
|
||||||
fprintf(stderr, "could not create pipe (%s)", strerror(errno));
|
fprintf(stderr, "could not create pipe (%s)", strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -713,7 +778,7 @@ int client_send_msg(struct process *process, enum mt_operation op, void *payload
|
|||||||
if (options.logfile)
|
if (options.logfile)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ret = sock_send_msg(client_fd, process->val16(op), process->pid, 0, payload, payload_len);
|
ret = sock_send_msg(client_fd, process->val16(op), process->pid, payload, payload_len);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
client_broken();
|
client_broken();
|
||||||
|
|||||||
@ -28,9 +28,10 @@
|
|||||||
struct process;
|
struct process;
|
||||||
|
|
||||||
struct process *client_first_process(void);
|
struct process *client_first_process(void);
|
||||||
struct process *client_find_process(pid_t pid);
|
struct process *client_find_process(unsigned int pid);
|
||||||
void client_iterate_processes(int (*func)(struct process *process));
|
void client_iterate_processes(int (*func)(struct process *process));
|
||||||
void client_show_info(void);
|
void client_show_info(void);
|
||||||
|
void client_request_info(void);
|
||||||
int client_wait_op(enum mt_operation op);
|
int client_wait_op(enum mt_operation op);
|
||||||
void client_close(void);
|
void client_close(void);
|
||||||
int client_send_msg(struct process *process, enum mt_operation op, void *payload, unsigned int payload_len);
|
int client_send_msg(struct process *process, enum mt_operation op, void *payload, unsigned int payload_len);
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
static int dump_term;
|
static int dump_term;
|
||||||
static FILE *dump_outfile;
|
static FILE *dump_outfile;
|
||||||
|
static int dump_char;
|
||||||
|
|
||||||
static int rows, cols;
|
static int rows, cols;
|
||||||
static int row, col;
|
static int row, col;
|
||||||
@ -99,12 +100,18 @@ int dump_init(FILE *file)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dump_getchar(void)
|
||||||
|
{
|
||||||
|
dump_char = getchar();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int dump_pager(void)
|
static int dump_pager(void)
|
||||||
{
|
{
|
||||||
struct termios termios;
|
struct termios termios;
|
||||||
struct termios termios_old;
|
struct termios termios_old;
|
||||||
int c;
|
|
||||||
int len;
|
int len;
|
||||||
|
ioevent_func oldfunc;
|
||||||
|
|
||||||
len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1;
|
len = printf("Press <space> for next line, q for quit and any other for next page\r") - 1;
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
@ -114,14 +121,20 @@ static int dump_pager(void)
|
|||||||
cfmakeraw(&termios);
|
cfmakeraw(&termios);
|
||||||
|
|
||||||
tcsetattr(0, TCSADRAIN, &termios);
|
tcsetattr(0, TCSADRAIN, &termios);
|
||||||
ioevent_wait_input(0, -1);
|
oldfunc = ioevent_set_input_func(0, dump_getchar);
|
||||||
c = getchar();
|
|
||||||
|
dump_char = 0;
|
||||||
|
do {
|
||||||
|
ioevent_watch(-1);
|
||||||
|
} while(!dump_char);
|
||||||
|
|
||||||
|
ioevent_set_input_func(0, oldfunc);
|
||||||
tcsetattr(0, TCSANOW, &termios_old);
|
tcsetattr(0, TCSANOW, &termios_old);
|
||||||
|
|
||||||
printf("%*s\r", len, "");
|
printf("%*s\r", len, "");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
switch(c) {
|
switch(dump_char) {
|
||||||
case '\03':
|
case '\03':
|
||||||
case 'q':
|
case 'q':
|
||||||
if (col)
|
if (col)
|
||||||
|
|||||||
217
client/process.c
217
client/process.c
@ -64,6 +64,7 @@ struct stack {
|
|||||||
struct rb_stack {
|
struct rb_stack {
|
||||||
struct rb_node node;
|
struct rb_node node;
|
||||||
struct stack *stack;
|
struct stack *stack;
|
||||||
|
unsigned long refcnt;
|
||||||
unsigned long leaks;
|
unsigned long leaks;
|
||||||
unsigned long long n_allocations;
|
unsigned long long n_allocations;
|
||||||
unsigned long long total_allocations;
|
unsigned long long total_allocations;
|
||||||
@ -83,6 +84,16 @@ struct map {
|
|||||||
unsigned int ignore:1;
|
unsigned int ignore:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct realloc_entry {
|
||||||
|
struct list_head list;
|
||||||
|
unsigned int pid;
|
||||||
|
unsigned long addr;
|
||||||
|
unsigned long size;
|
||||||
|
unsigned long flags;
|
||||||
|
struct rb_stack *stack;
|
||||||
|
enum mt_operation operation;
|
||||||
|
};
|
||||||
|
|
||||||
struct regex_list {
|
struct regex_list {
|
||||||
regex_t re;
|
regex_t re;
|
||||||
struct regex_list *next;
|
struct regex_list *next;
|
||||||
@ -120,8 +131,8 @@ static const char *str_operation(enum mt_operation operation)
|
|||||||
return "realloc enter";
|
return "realloc enter";
|
||||||
case MT_REALLOC:
|
case MT_REALLOC:
|
||||||
return "realloc";
|
return "realloc";
|
||||||
case MT_REALLOC_FAILED:
|
case MT_REALLOC_DONE:
|
||||||
return "realloc failed";
|
return "realloc done";
|
||||||
case MT_MEMALIGN:
|
case MT_MEMALIGN:
|
||||||
return "memalign";
|
return "memalign";
|
||||||
case MT_POSIX_MEMALIGN:
|
case MT_POSIX_MEMALIGN:
|
||||||
@ -389,9 +400,22 @@ static void stack_resolv(struct process *process, struct stack *stack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stack_put(struct stack *stack)
|
static struct rb_stack *stack_get(struct rb_stack *stack_node)
|
||||||
{
|
{
|
||||||
if (--stack->refcnt == 0) {
|
++stack_node->refcnt;
|
||||||
|
++stack_node->stack->refcnt;
|
||||||
|
|
||||||
|
return stack_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stack_put(struct rb_stack *stack_node)
|
||||||
|
{
|
||||||
|
struct stack *stack = stack_node->stack;
|
||||||
|
|
||||||
|
if (!--stack_node->refcnt)
|
||||||
|
free(stack_node);
|
||||||
|
|
||||||
|
if (!--stack->refcnt) {
|
||||||
if (stack->syms) {
|
if (stack->syms) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -431,6 +455,7 @@ static struct rb_stack *stack_clone(struct process *process, struct rb_stack *st
|
|||||||
if (!this)
|
if (!this)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
this->refcnt = 0;
|
||||||
this->leaks = stack_node->leaks;
|
this->leaks = stack_node->leaks;
|
||||||
this->n_allocations = stack_node->n_allocations;
|
this->n_allocations = stack_node->n_allocations;
|
||||||
this->n_mismatched = stack_node->n_mismatched;
|
this->n_mismatched = stack_node->n_mismatched;
|
||||||
@ -439,7 +464,8 @@ static struct rb_stack *stack_clone(struct process *process, struct rb_stack *st
|
|||||||
this->bytes_leaked = stack_node->bytes_leaked;
|
this->bytes_leaked = stack_node->bytes_leaked;
|
||||||
this->tsc = stack_node->tsc;
|
this->tsc = stack_node->tsc;
|
||||||
this->stack = stack_node->stack;
|
this->stack = stack_node->stack;
|
||||||
this->stack->refcnt++;
|
|
||||||
|
stack_get(this);
|
||||||
|
|
||||||
/* Add new node and rebalance tree. */
|
/* Add new node and rebalance tree. */
|
||||||
rb_link_node(&this->node, parent, new);
|
rb_link_node(&this->node, parent, new);
|
||||||
@ -450,7 +476,7 @@ static struct rb_stack *stack_clone(struct process *process, struct rb_stack *st
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addrs, uint32_t stack_size, enum mt_operation operation)
|
static struct rb_stack *stack_add(struct process *process, unsigned int pid, void *addrs, uint32_t stack_size, enum mt_operation operation)
|
||||||
{
|
{
|
||||||
struct rb_root *root = &process->stack_table;
|
struct rb_root *root = &process->stack_table;
|
||||||
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
||||||
@ -487,7 +513,7 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
stack->refcnt = 1;
|
stack->refcnt = 0;
|
||||||
stack->addrs = malloc(stack_size);
|
stack->addrs = malloc(stack_size);
|
||||||
stack->size = stack_size;
|
stack->size = stack_size;
|
||||||
stack->entries = stack_size / process->ptr_size;
|
stack->entries = stack_size / process->ptr_size;
|
||||||
@ -497,6 +523,7 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
|||||||
|
|
||||||
memcpy(stack->addrs, addrs, stack_size);
|
memcpy(stack->addrs, addrs, stack_size);
|
||||||
|
|
||||||
|
this->refcnt = 0;
|
||||||
this->n_allocations = 0;
|
this->n_allocations = 0;
|
||||||
this->n_mismatched = 0;
|
this->n_mismatched = 0;
|
||||||
this->total_allocations = 0;
|
this->total_allocations = 0;
|
||||||
@ -505,6 +532,8 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
|||||||
this->bytes_leaked = 0;
|
this->bytes_leaked = 0;
|
||||||
this->stack = stack;
|
this->stack = stack;
|
||||||
|
|
||||||
|
stack_get(this);
|
||||||
|
|
||||||
stack_resolv(process, stack);
|
stack_resolv(process, stack);
|
||||||
|
|
||||||
/* Add new node and rebalance tree. */
|
/* Add new node and rebalance tree. */
|
||||||
@ -516,7 +545,7 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_dump_stack(struct process *process, struct rb_stack *this, int lflag)
|
static void dump_stack(struct rb_stack *this, int lflag, unsigned long (*get_ulong)(void *), uint8_t ptr_size)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
void *addrs;
|
void *addrs;
|
||||||
@ -526,7 +555,7 @@ static void process_dump_stack(struct process *process, struct rb_stack *this, i
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for(addrs = stack->addrs, i = 0; i < stack->entries; ++i) {
|
for(addrs = stack->addrs, i = 0; i < stack->entries; ++i) {
|
||||||
if (dump_printf(" [0x%lx]", process->get_ulong(addrs)))
|
if (dump_printf(" [0x%lx]", get_ulong(addrs)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!stack->syms[i]) {
|
if (!stack->syms[i]) {
|
||||||
@ -548,7 +577,7 @@ static void process_dump_stack(struct process *process, struct rb_stack *this, i
|
|||||||
if (dump_printf("\n") == -1)
|
if (dump_printf("\n") == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addrs += process->ptr_size;
|
addrs += ptr_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -625,6 +654,8 @@ static void process_rb_delete_block(struct process *process, struct rb_block *bl
|
|||||||
|
|
||||||
block->stack_node->n_allocations--;
|
block->stack_node->n_allocations--;
|
||||||
|
|
||||||
|
stack_put(block->stack_node);
|
||||||
|
|
||||||
free(block);
|
free(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,7 +676,7 @@ static int process_rb_insert_block(struct process *process, unsigned long addr,
|
|||||||
parent = *new;
|
parent = *new;
|
||||||
|
|
||||||
if (addr <= this->addr && addr + n > this->addr) {
|
if (addr <= this->addr && addr + n > this->addr) {
|
||||||
if (options.kill || options.verbose > 2) {
|
if (unlikely(options.kill || options.verbose > 2)) {
|
||||||
process_dump_collision(process, this, addr, size, operation);
|
process_dump_collision(process, this, addr, size, operation);
|
||||||
|
|
||||||
if (options.kill)
|
if (options.kill)
|
||||||
@ -671,7 +702,8 @@ static int process_rb_insert_block(struct process *process, unsigned long addr,
|
|||||||
block->stack_node->n_allocations++;
|
block->stack_node->n_allocations++;
|
||||||
block->stack_node->total_allocations++;
|
block->stack_node->total_allocations++;
|
||||||
block->stack_node->bytes_used += size;
|
block->stack_node->bytes_used += size;
|
||||||
block->stack_node->stack->refcnt++;
|
|
||||||
|
stack_get(block->stack_node);
|
||||||
|
|
||||||
/* Add new node and rebalance tree. */
|
/* Add new node and rebalance tree. */
|
||||||
rb_link_node(&block->node, parent, new);
|
rb_link_node(&block->node, parent, new);
|
||||||
@ -705,7 +737,7 @@ static struct map *_process_add_map(struct process *process, unsigned long addr,
|
|||||||
|
|
||||||
list_add_tail(&map->list, &process->map_list);
|
list_add_tail(&map->list, &process->map_list);
|
||||||
|
|
||||||
/* fixit: it is possible that stack_add() can produce false matches */
|
/* fixit: it is now possible that stack_add() produce false matches */
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@ -774,26 +806,38 @@ static void process_init(struct process *process, unsigned int swap_endian, unsi
|
|||||||
process->filename = NULL;
|
process->filename = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void realloc_del(struct realloc_entry *re)
|
||||||
|
{
|
||||||
|
stack_put(re->stack);
|
||||||
|
list_del(&re->list);
|
||||||
|
free(re);
|
||||||
|
}
|
||||||
|
|
||||||
void process_reset_allocations(struct process *process)
|
void process_reset_allocations(struct process *process)
|
||||||
{
|
{
|
||||||
struct rb_block *rbb, *rbb_next;
|
struct rb_block *rbb, *rbb_next;
|
||||||
struct rb_stack *rbs, *rbs_next;
|
struct list_head *it, *next;
|
||||||
|
|
||||||
rbtree_postorder_for_each_entry_safe(rbb, rbb_next, &process->block_table, node) {
|
rbtree_postorder_for_each_entry_safe(rbb, rbb_next, &process->block_table, node) {
|
||||||
process->n_allocations--;
|
--process->n_allocations;
|
||||||
|
--rbb->stack_node->n_allocations;
|
||||||
|
stack_put(rbb->stack_node);
|
||||||
free(rbb);
|
free(rbb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (process->n_allocations)
|
||||||
|
fatal("invalid allocation count!\n");
|
||||||
|
|
||||||
process->block_table = RB_ROOT;
|
process->block_table = RB_ROOT;
|
||||||
|
|
||||||
rbtree_postorder_for_each_entry_safe(rbs, rbs_next, &process->stack_table, node) {
|
list_for_each_safe(it, next, &process->realloc_list) {
|
||||||
stack_put(rbs->stack);
|
struct realloc_entry *re = container_of(it, struct realloc_entry, list);
|
||||||
free(rbs);
|
|
||||||
|
realloc_del(re);
|
||||||
}
|
}
|
||||||
process->stack_table = RB_ROOT;
|
|
||||||
|
|
||||||
process->total_allocations = 0;
|
process->total_allocations = 0;
|
||||||
process->bytes_used = 0;
|
process->bytes_used = 0;
|
||||||
process->stack_trees = 0;
|
|
||||||
process->leaks = 0;
|
process->leaks = 0;
|
||||||
process->leaked_bytes = 0;
|
process->leaked_bytes = 0;
|
||||||
process->tsc = 0;
|
process->tsc = 0;
|
||||||
@ -801,10 +845,24 @@ void process_reset_allocations(struct process *process)
|
|||||||
|
|
||||||
void process_reset(struct process *process)
|
void process_reset(struct process *process)
|
||||||
{
|
{
|
||||||
|
struct rb_stack *rbs, *rbs_next;
|
||||||
struct list_head *it, *next;
|
struct list_head *it, *next;
|
||||||
|
|
||||||
process_reset_allocations(process);
|
process_reset_allocations(process);
|
||||||
|
|
||||||
|
rbtree_postorder_for_each_entry_safe(rbs, rbs_next, &process->stack_table, node) {
|
||||||
|
if (rbs->refcnt != 1)
|
||||||
|
fatal("unexpected stack tree ref count!\n");
|
||||||
|
|
||||||
|
stack_put(rbs);
|
||||||
|
--process->stack_trees;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process->stack_trees)
|
||||||
|
fatal("invalid stack tree count!\n");
|
||||||
|
|
||||||
|
process->stack_table = RB_ROOT;
|
||||||
|
|
||||||
list_for_each_safe(it, next, &process->map_list) {
|
list_for_each_safe(it, next, &process->map_list) {
|
||||||
struct map *map = container_of(it, struct map, list);
|
struct map *map = container_of(it, struct map, list);
|
||||||
|
|
||||||
@ -944,29 +1002,36 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
|||||||
struct rb_stack **arr;
|
struct rb_stack **arr;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
void *data;
|
void *data;
|
||||||
|
unsigned long stack_trees = process->stack_trees;
|
||||||
|
unsigned long (*get_ulong)(void *) = process->get_ulong;
|
||||||
|
uint8_t ptr_size = process->ptr_size;
|
||||||
|
|
||||||
if (dump_init(file) == -1)
|
if (dump_init(file) == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
arr = malloc(sizeof(struct rb_stack *) * stack_trees);
|
||||||
|
if (!arr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(i = 0, data = rb_first(&process->stack_table); data; data = rb_next(data)) {
|
||||||
|
struct rb_stack *stack_node = container_of(data, struct rb_stack, node);
|
||||||
|
|
||||||
|
arr[i++] = stack_get(stack_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack_trees != i)
|
||||||
|
fatal("invalid stack tree count!\n");
|
||||||
|
|
||||||
dump_printf("Process dump %d %s\n", process->pid, process->filename ? process->filename : "<unknown>");
|
dump_printf("Process dump %d %s\n", process->pid, process->filename ? process->filename : "<unknown>");
|
||||||
|
|
||||||
if (!process->stack_trees)
|
if (!stack_trees)
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
arr = malloc(sizeof(struct rb_stack *) * process->stack_trees);
|
qsort(arr, stack_trees, sizeof(struct rb_stack *), (void *)sortby);
|
||||||
if (!arr)
|
|
||||||
goto skip;
|
|
||||||
|
|
||||||
for(i = 0, data = rb_first(&process->stack_table); data; data = rb_next(data))
|
|
||||||
arr[i++] = container_of(data, struct rb_stack, node);
|
|
||||||
|
|
||||||
assert(i == process->stack_trees);
|
|
||||||
|
|
||||||
qsort(arr, process->stack_trees, sizeof(struct rb_stack *), (void *)sortby);
|
|
||||||
|
|
||||||
if (file == stderr) {
|
if (file == stderr) {
|
||||||
unsigned long n = process->stack_trees / 2;
|
unsigned long n = stack_trees / 2;
|
||||||
unsigned long l = process->stack_trees - 1;
|
unsigned long l = stack_trees - 1;
|
||||||
|
|
||||||
for(i = 0; i < n; ++i) {
|
for(i = 0; i < n; ++i) {
|
||||||
struct rb_stack *tmp = arr[i];
|
struct rb_stack *tmp = arr[i];
|
||||||
@ -976,7 +1041,7 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(i = 0; i < process->stack_trees; ++i) {
|
for(i = 0; i < stack_trees; ++i) {
|
||||||
struct rb_stack *stack = arr[i];
|
struct rb_stack *stack = arr[i];
|
||||||
|
|
||||||
if (!skipfunc(stack)) {
|
if (!skipfunc(stack)) {
|
||||||
@ -1011,11 +1076,15 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
|||||||
if (dump_printf(" tsc: %llu\n", stack->tsc) == -1)
|
if (dump_printf(" tsc: %llu\n", stack->tsc) == -1)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
process_dump_stack(process, stack, lflag);
|
dump_stack(stack, lflag, get_ulong, ptr_size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
free(arr);
|
|
||||||
|
for(i = 0; i < stack_trees; ++i)
|
||||||
|
stack_put(arr[i]);
|
||||||
|
|
||||||
skip:
|
skip:
|
||||||
|
free(arr);
|
||||||
dump_flush();
|
dump_flush();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1112,7 +1181,7 @@ void *process_scan(struct process *process, void *leaks, uint32_t payload_len)
|
|||||||
for(i = 0; i < n; ++i) {
|
for(i = 0; i < n; ++i) {
|
||||||
struct rb_block *block = process_rb_search(&process->block_table, process->get_ulong(leaks));
|
struct rb_block *block = process_rb_search(&process->block_table, process->get_ulong(leaks));
|
||||||
|
|
||||||
if (!(block->flags & BLOCK_LEAKED)) {
|
if (block && !(block->flags & BLOCK_LEAKED)) {
|
||||||
block->flags |= BLOCK_LEAKED;
|
block->flags |= BLOCK_LEAKED;
|
||||||
|
|
||||||
block->stack_node->leaks++;
|
block->stack_node->leaks++;
|
||||||
@ -1189,7 +1258,7 @@ void process_munmap(struct process *process, struct mt_msg *mt_msg, void *payloa
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (!is_mmap(block->stack_node->stack->operation)) {
|
if (!is_mmap(block->stack_node->stack->operation)) {
|
||||||
if (options.kill || options.verbose > 2) {
|
if (unlikely(options.kill || options.verbose > 2)) {
|
||||||
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
||||||
|
|
||||||
if (options.kill)
|
if (options.kill)
|
||||||
@ -1255,7 +1324,6 @@ static int is_sane(struct rb_block *block, enum mt_operation op)
|
|||||||
switch(block->stack_node->stack->operation) {
|
switch(block->stack_node->stack->operation) {
|
||||||
case MT_MALLOC:
|
case MT_MALLOC:
|
||||||
case MT_REALLOC:
|
case MT_REALLOC:
|
||||||
case MT_REALLOC_FAILED:
|
|
||||||
case MT_MEMALIGN:
|
case MT_MEMALIGN:
|
||||||
case MT_POSIX_MEMALIGN:
|
case MT_POSIX_MEMALIGN:
|
||||||
case MT_ALIGNED_ALLOC:
|
case MT_ALIGNED_ALLOC:
|
||||||
@ -1285,6 +1353,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
struct rb_block *block = NULL;
|
struct rb_block *block = NULL;
|
||||||
uint32_t payload_len = mt_msg->payload_len;
|
uint32_t payload_len = mt_msg->payload_len;
|
||||||
unsigned long ptr;
|
unsigned long ptr;
|
||||||
|
unsigned long pid;
|
||||||
void *stack_data;
|
void *stack_data;
|
||||||
unsigned long stack_size;
|
unsigned long stack_size;
|
||||||
|
|
||||||
@ -1295,6 +1364,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
struct mt_alloc_payload_64 *mt_alloc = payload;
|
struct mt_alloc_payload_64 *mt_alloc = payload;
|
||||||
|
|
||||||
ptr = process->get_ulong(&mt_alloc->ptr);
|
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||||
|
pid = process->get_ulong(&mt_alloc->size);
|
||||||
|
|
||||||
stack_data = payload + sizeof(*mt_alloc);
|
stack_data = payload + sizeof(*mt_alloc);
|
||||||
stack_size = (payload_len - sizeof(*mt_alloc));
|
stack_size = (payload_len - sizeof(*mt_alloc));
|
||||||
@ -1303,6 +1373,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
struct mt_alloc_payload_32 *mt_alloc = payload;
|
struct mt_alloc_payload_32 *mt_alloc = payload;
|
||||||
|
|
||||||
ptr = process->get_ulong(&mt_alloc->ptr);
|
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||||
|
pid = process->get_ulong(&mt_alloc->size);
|
||||||
|
|
||||||
stack_data = payload + sizeof(*mt_alloc);
|
stack_data = payload + sizeof(*mt_alloc);
|
||||||
stack_size = (payload_len - sizeof(*mt_alloc));
|
stack_size = (payload_len - sizeof(*mt_alloc));
|
||||||
@ -1313,7 +1384,7 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
block = process_rb_search(&process->block_table, ptr);
|
block = process_rb_search(&process->block_table, ptr);
|
||||||
if (block) {
|
if (block) {
|
||||||
if (is_mmap(block->stack_node->stack->operation)) {
|
if (is_mmap(block->stack_node->stack->operation)) {
|
||||||
if (options.kill || options.verbose > 2) {
|
if (unlikely(options.kill || options.verbose > 2)) {
|
||||||
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
fprintf(stderr, ">>> block missmatch pid:%d MAP<>MALLOC %#lx\n", process->pid, ptr);
|
||||||
|
|
||||||
if (options.kill)
|
if (options.kill)
|
||||||
@ -1328,12 +1399,27 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
stack->tsc = process->tsc++;
|
stack->tsc = process->tsc++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mt_msg->operation == MT_REALLOC_ENTER) {
|
||||||
|
struct realloc_entry *re = malloc(sizeof(*re));
|
||||||
|
|
||||||
|
re->addr = block->addr;
|
||||||
|
re->size = block->size;
|
||||||
|
re->flags = block->flags;
|
||||||
|
re->operation = block->stack_node->stack->operation;
|
||||||
|
re->pid = pid;
|
||||||
|
re->stack = block->stack_node;
|
||||||
|
|
||||||
|
stack_get(re->stack);
|
||||||
|
|
||||||
|
list_add_tail(&re->list, &process->realloc_list);
|
||||||
|
}
|
||||||
|
|
||||||
process_rb_delete_block(process, block);
|
process_rb_delete_block(process, block);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (!process->attached) {
|
if (!process->attached) {
|
||||||
if (options.kill || options.verbose > 2) {
|
if (unlikely(options.kill || options.verbose > 2)) {
|
||||||
fprintf(stderr, ">>> block %#lx not found pid:%d tid:%d\n", ptr, process->pid, mt_msg->tid);
|
fprintf(stderr, ">>> block %#lx not found pid:%d\n", ptr, process->pid);
|
||||||
|
|
||||||
if (options.kill)
|
if (options.kill)
|
||||||
abort();
|
abort();
|
||||||
@ -1342,6 +1428,46 @@ void process_free(struct process *process, struct mt_msg *mt_msg, void *payload)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void process_realloc_done(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||||
|
{
|
||||||
|
unsigned long ptr;
|
||||||
|
unsigned long pid;
|
||||||
|
struct list_head *it;
|
||||||
|
|
||||||
|
if (!process->tracing)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (process->is_64bit) {
|
||||||
|
struct mt_alloc_payload_64 *mt_alloc = payload;
|
||||||
|
|
||||||
|
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||||
|
pid = process->get_ulong(&mt_alloc->size);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct mt_alloc_payload_32 *mt_alloc = payload;
|
||||||
|
|
||||||
|
ptr = process->get_ulong(&mt_alloc->ptr);
|
||||||
|
pid = process->get_ulong(&mt_alloc->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug(DEBUG_FUNCTION, "ptr=%#lx ", ptr);
|
||||||
|
|
||||||
|
list_for_each(it, &process->realloc_list) {
|
||||||
|
struct realloc_entry *re = container_of(it, struct realloc_entry, list);
|
||||||
|
|
||||||
|
if (re->pid == pid) {
|
||||||
|
if (!ptr)
|
||||||
|
process_rb_insert_block(process, re->addr, re->size, re->stack, re->flags, re->operation);
|
||||||
|
|
||||||
|
realloc_del(re);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void process_alloc(struct process *process, struct mt_msg *mt_msg, void *payload)
|
void process_alloc(struct process *process, struct mt_msg *mt_msg, void *payload)
|
||||||
{
|
{
|
||||||
struct rb_block *block = NULL;
|
struct rb_block *block = NULL;
|
||||||
@ -1379,7 +1505,7 @@ void process_alloc(struct process *process, struct mt_msg *mt_msg, void *payload
|
|||||||
|
|
||||||
block = process_rb_search_range(&process->block_table, ptr, size);
|
block = process_rb_search_range(&process->block_table, ptr, size);
|
||||||
if (block) {
|
if (block) {
|
||||||
if (options.kill || options.verbose > 2) {
|
if (unlikely(options.kill || options.verbose > 2)) {
|
||||||
process_dump_collision(process, block, ptr, size, mt_msg->operation);
|
process_dump_collision(process, block, ptr, size, mt_msg->operation);
|
||||||
|
|
||||||
if (options.kill)
|
if (options.kill)
|
||||||
@ -1405,7 +1531,7 @@ void process_reinit(struct process *process, unsigned int swap_endian, unsigned
|
|||||||
process_init(process, swap_endian, is_64bit, attached);
|
process_init(process, swap_endian, is_64bit, attached);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct process *process_new(pid_t pid, unsigned int swap_endian, unsigned int tracing)
|
struct process *process_new(unsigned int pid, unsigned int swap_endian, unsigned int tracing)
|
||||||
{
|
{
|
||||||
struct process *process = malloc(sizeof(*process));
|
struct process *process = malloc(sizeof(*process));
|
||||||
|
|
||||||
@ -1416,6 +1542,7 @@ struct process *process_new(pid_t pid, unsigned int swap_endian, unsigned int tr
|
|||||||
process->block_table = RB_ROOT;
|
process->block_table = RB_ROOT;
|
||||||
process->stack_table = RB_ROOT;
|
process->stack_table = RB_ROOT;
|
||||||
INIT_LIST_HEAD(&process->map_list);
|
INIT_LIST_HEAD(&process->map_list);
|
||||||
|
INIT_LIST_HEAD(&process->realloc_list);
|
||||||
|
|
||||||
process_init(process, swap_endian, 0, 0);
|
process_init(process, swap_endian, 0, 0);
|
||||||
|
|
||||||
@ -1537,7 +1664,6 @@ void process_status(struct process *process)
|
|||||||
" number of open allocations: %lu\n"
|
" number of open allocations: %lu\n"
|
||||||
" total number of allocations: %lu\n"
|
" total number of allocations: %lu\n"
|
||||||
" average allocation: %f bytes\n"
|
" average allocation: %f bytes\n"
|
||||||
" number of allocators: %lu\n"
|
|
||||||
" number of leaks: %lu\n"
|
" number of leaks: %lu\n"
|
||||||
" number of leaked bytes: %llu\n"
|
" number of leaked bytes: %llu\n"
|
||||||
" status: %s\n",
|
" status: %s\n",
|
||||||
@ -1546,7 +1672,6 @@ void process_status(struct process *process)
|
|||||||
process->n_allocations,
|
process->n_allocations,
|
||||||
process->total_allocations,
|
process->total_allocations,
|
||||||
process->n_allocations ? (double)process->bytes_used / process->n_allocations : 0.0,
|
process->n_allocations ? (double)process->bytes_used / process->n_allocations : 0.0,
|
||||||
process->stack_trees,
|
|
||||||
process->leaks,
|
process->leaks,
|
||||||
process->leaked_bytes,
|
process->leaked_bytes,
|
||||||
process_get_status(process)
|
process_get_status(process)
|
||||||
|
|||||||
@ -53,7 +53,7 @@ struct lib {
|
|||||||
|
|
||||||
struct process {
|
struct process {
|
||||||
enum process_status status;
|
enum process_status status;
|
||||||
pid_t pid;
|
unsigned int pid;
|
||||||
char *filename;
|
char *filename;
|
||||||
unsigned long bytes_used;
|
unsigned long bytes_used;
|
||||||
unsigned long n_allocations;
|
unsigned long n_allocations;
|
||||||
@ -64,6 +64,7 @@ struct process {
|
|||||||
struct rb_root block_table;
|
struct rb_root block_table;
|
||||||
struct rb_root stack_table;
|
struct rb_root stack_table;
|
||||||
struct list_head map_list;
|
struct list_head map_list;
|
||||||
|
struct list_head realloc_list;
|
||||||
unsigned long long tsc;
|
unsigned long long tsc;
|
||||||
unsigned int tracing:1;
|
unsigned int tracing:1;
|
||||||
unsigned int swap_endian:1;
|
unsigned int swap_endian:1;
|
||||||
@ -77,7 +78,7 @@ struct process {
|
|||||||
uint8_t ptr_size;
|
uint8_t ptr_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct process *process_new(pid_t pid, unsigned int swap_endian, unsigned int tracing);
|
struct process *process_new(unsigned int pid, unsigned int swap_endian, unsigned int tracing);
|
||||||
void process_reset(struct process *process);
|
void process_reset(struct process *process);
|
||||||
void process_reset_allocations(struct process *process);
|
void process_reset_allocations(struct process *process);
|
||||||
void process_reinit(struct process *process, unsigned int swap_endian, unsigned int is_64bit, unsigned int attached);
|
void process_reinit(struct process *process, unsigned int swap_endian, unsigned int is_64bit, unsigned int attached);
|
||||||
@ -98,6 +99,7 @@ void process_munmap(struct process *process, struct mt_msg *msg, void *payload);
|
|||||||
void process_add_map(struct process *process, void *payload, uint32_t payload_len);
|
void process_add_map(struct process *process, void *payload, uint32_t payload_len);
|
||||||
void process_del_map(struct process *process, void *payload, uint32_t payload_len);
|
void process_del_map(struct process *process, void *payload, uint32_t payload_len);
|
||||||
void process_detach(struct process *process);
|
void process_detach(struct process *process);
|
||||||
|
void process_realloc_done(struct process *process, struct mt_msg *mt_msg, void *payload);
|
||||||
|
|
||||||
unsigned long process_leaks_scan(struct process *process, int mode);
|
unsigned long process_leaks_scan(struct process *process, int mode);
|
||||||
|
|
||||||
|
|||||||
@ -503,7 +503,9 @@ static int do_show_info(struct cmd_opt *cmd, struct cmd_opt *opt, int argc, cons
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client_request_info();
|
||||||
client_show_info();
|
client_show_info();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
common.c
6
common.c
@ -78,18 +78,18 @@ unsigned long find_block(unsigned long (*get_val)(void *data, unsigned long inde
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
middle = (first + last) >> 1;
|
middle = (first + last) >> 1;
|
||||||
|
|
||||||
val = get_val(arr, middle);
|
val = get_val(arr, middle);
|
||||||
|
|
||||||
if (addr < val)
|
if (addr < val)
|
||||||
last = middle;
|
last = middle;
|
||||||
else if (addr > val)
|
else
|
||||||
|
if (addr > val)
|
||||||
first = middle + 1;
|
first = middle + 1;
|
||||||
else
|
else
|
||||||
return middle;
|
return middle;
|
||||||
|
|
||||||
} while (first < last);
|
} while (first < last);
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
8
common.h
8
common.h
@ -58,6 +58,14 @@
|
|||||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
(type *)( (char *)__mptr - offsetof(type,member) );})
|
||||||
|
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
#define likely(x) __builtin_expect(!!(x), 1)
|
||||||
|
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||||
|
#else
|
||||||
|
#define likely(x) (x)
|
||||||
|
#define unlikely(x) (x)
|
||||||
|
#endif
|
||||||
|
|
||||||
#define fatal(fmt...) _fatal(__FILE__,__PRETTY_FUNCTION__,__LINE__ , ##fmt),abort()
|
#define fatal(fmt...) _fatal(__FILE__,__PRETTY_FUNCTION__,__LINE__ , ##fmt),abort()
|
||||||
|
|
||||||
void _fatal(const char *file, const char *func, int line, const char *format, ...) __attribute__ ((format (printf, 4, 5)));;
|
void _fatal(const char *file, const char *func, int line, const char *format, ...) __attribute__ ((format (printf, 4, 5)));;
|
||||||
|
|||||||
@ -18,6 +18,9 @@
|
|||||||
/* Define to 1 if you have the <bfd.h> header file. */
|
/* Define to 1 if you have the <bfd.h> header file. */
|
||||||
#undef HAVE_BFD_H
|
#undef HAVE_BFD_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `clock_gettime' function. */
|
||||||
|
#undef HAVE_CLOCK_GETTIME
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
#undef HAVE_DLFCN_H
|
#undef HAVE_DLFCN_H
|
||||||
|
|
||||||
@ -60,6 +63,9 @@
|
|||||||
/* Define to 1 if you have the `readline' library (-lreadline). */
|
/* Define to 1 if you have the `readline' library (-lreadline). */
|
||||||
#undef HAVE_LIBREADLINE
|
#undef HAVE_LIBREADLINE
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `rt' library (-lrt). */
|
||||||
|
#undef HAVE_LIBRT
|
||||||
|
|
||||||
/* Define to 1 if you have the `selinux' library (-lselinux). */
|
/* Define to 1 if you have the `selinux' library (-lselinux). */
|
||||||
#undef HAVE_LIBSELINUX
|
#undef HAVE_LIBSELINUX
|
||||||
|
|
||||||
|
|||||||
69
configure
vendored
69
configure
vendored
@ -1,6 +1,6 @@
|
|||||||
#! /bin/sh
|
#! /bin/sh
|
||||||
# Guess values for system-dependent variables and create Makefiles.
|
# Guess values for system-dependent variables and create Makefiles.
|
||||||
# Generated by GNU Autoconf 2.69 for mtrace-ng 0.4.
|
# Generated by GNU Autoconf 2.69 for mtrace-ng 0.5.
|
||||||
#
|
#
|
||||||
# Report bugs to <stefani@seibold.net>.
|
# Report bugs to <stefani@seibold.net>.
|
||||||
#
|
#
|
||||||
@ -590,8 +590,8 @@ MAKEFLAGS=
|
|||||||
# Identity of this package.
|
# Identity of this package.
|
||||||
PACKAGE_NAME='mtrace-ng'
|
PACKAGE_NAME='mtrace-ng'
|
||||||
PACKAGE_TARNAME='mtrace-ng'
|
PACKAGE_TARNAME='mtrace-ng'
|
||||||
PACKAGE_VERSION='0.4'
|
PACKAGE_VERSION='0.5'
|
||||||
PACKAGE_STRING='mtrace-ng 0.4'
|
PACKAGE_STRING='mtrace-ng 0.5'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1329,7 +1329,7 @@ if test "$ac_init_help" = "long"; then
|
|||||||
# Omit some internal or obsolete options to make the list less imposing.
|
# Omit some internal or obsolete options to make the list less imposing.
|
||||||
# This message is too long to be a string in the A/UX 3.1 sh.
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
||||||
cat <<_ACEOF
|
cat <<_ACEOF
|
||||||
\`configure' configures mtrace-ng 0.4 to adapt to many kinds of systems.
|
\`configure' configures mtrace-ng 0.5 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1399,7 +1399,7 @@ fi
|
|||||||
|
|
||||||
if test -n "$ac_init_help"; then
|
if test -n "$ac_init_help"; then
|
||||||
case $ac_init_help in
|
case $ac_init_help in
|
||||||
short | recursive ) echo "Configuration of mtrace-ng 0.4:";;
|
short | recursive ) echo "Configuration of mtrace-ng 0.5:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1518,7 +1518,7 @@ fi
|
|||||||
test -n "$ac_init_help" && exit $ac_status
|
test -n "$ac_init_help" && exit $ac_status
|
||||||
if $ac_init_version; then
|
if $ac_init_version; then
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
mtrace-ng configure 0.4
|
mtrace-ng configure 0.5
|
||||||
generated by GNU Autoconf 2.69
|
generated by GNU Autoconf 2.69
|
||||||
|
|
||||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
@ -2124,7 +2124,7 @@ cat >config.log <<_ACEOF
|
|||||||
This file contains any messages produced by compilers while
|
This file contains any messages produced by compilers while
|
||||||
running configure, to aid debugging if configure makes a mistake.
|
running configure, to aid debugging if configure makes a mistake.
|
||||||
|
|
||||||
It was created by mtrace-ng $as_me 0.4, which was
|
It was created by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12006,7 +12006,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace-ng'
|
PACKAGE='mtrace-ng'
|
||||||
VERSION='0.4'
|
VERSION='0.5'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -13238,6 +13238,7 @@ for ac_func in \
|
|||||||
atexit \
|
atexit \
|
||||||
getcwd \
|
getcwd \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
|
clock_gettime \
|
||||||
memset \
|
memset \
|
||||||
mkdir \
|
mkdir \
|
||||||
rmdir \
|
rmdir \
|
||||||
@ -13260,6 +13261,54 @@ fi
|
|||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime in -lrt" >&5
|
||||||
|
$as_echo_n "checking for clock_gettime in -lrt... " >&6; }
|
||||||
|
if ${ac_cv_lib_rt_clock_gettime+:} false; then :
|
||||||
|
$as_echo_n "(cached) " >&6
|
||||||
|
else
|
||||||
|
ac_check_lib_save_LIBS=$LIBS
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
|
||||||
|
/* end confdefs.h. */
|
||||||
|
|
||||||
|
/* Override any GCC internal prototype to avoid an error.
|
||||||
|
Use char because int might match the return type of a GCC
|
||||||
|
builtin and then its argument prototype would still apply. */
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
#endif
|
||||||
|
char clock_gettime ();
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return clock_gettime ();
|
||||||
|
;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
_ACEOF
|
||||||
|
if ac_fn_c_try_link "$LINENO"; then :
|
||||||
|
ac_cv_lib_rt_clock_gettime=yes
|
||||||
|
else
|
||||||
|
ac_cv_lib_rt_clock_gettime=no
|
||||||
|
fi
|
||||||
|
rm -f core conftest.err conftest.$ac_objext \
|
||||||
|
conftest$ac_exeext conftest.$ac_ext
|
||||||
|
LIBS=$ac_check_lib_save_LIBS
|
||||||
|
fi
|
||||||
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_clock_gettime" >&5
|
||||||
|
$as_echo "$ac_cv_lib_rt_clock_gettime" >&6; }
|
||||||
|
if test "x$ac_cv_lib_rt_clock_gettime" = xyes; then :
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define HAVE_LIBRT 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
LIBS="-lrt $LIBS"
|
||||||
|
|
||||||
|
else
|
||||||
|
as_fn_error $? "*** librt not found on your system" "$LINENO" 5
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Debugging
|
# Debugging
|
||||||
@ -13844,7 +13893,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
|||||||
# report actual input values of CONFIG_FILES etc. instead of their
|
# report actual input values of CONFIG_FILES etc. instead of their
|
||||||
# values after options handling.
|
# values after options handling.
|
||||||
ac_log="
|
ac_log="
|
||||||
This file was extended by mtrace-ng $as_me 0.4, which was
|
This file was extended by mtrace-ng $as_me 0.5, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
CONFIG_FILES = $CONFIG_FILES
|
CONFIG_FILES = $CONFIG_FILES
|
||||||
@ -13910,7 +13959,7 @@ _ACEOF
|
|||||||
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
||||||
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
||||||
ac_cs_version="\\
|
ac_cs_version="\\
|
||||||
mtrace-ng config.status 0.4
|
mtrace-ng config.status 0.5
|
||||||
configured by $0, generated by GNU Autoconf 2.69,
|
configured by $0, generated by GNU Autoconf 2.69,
|
||||||
with options \\"\$ac_cs_config\\"
|
with options \\"\$ac_cs_config\\"
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,7 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
AC_PREREQ(2.65)
|
AC_PREREQ(2.65)
|
||||||
|
|
||||||
AC_INIT([mtrace-ng],[0.4],[stefani@seibold.net])
|
AC_INIT([mtrace-ng],[0.5],[stefani@seibold.net])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
AC_CONFIG_SRCDIR(main.c)
|
AC_CONFIG_SRCDIR(main.c)
|
||||||
AC_CONFIG_MACRO_DIR([config/m4])
|
AC_CONFIG_MACRO_DIR([config/m4])
|
||||||
@ -227,6 +227,7 @@ AC_CHECK_FUNCS([ \
|
|||||||
atexit \
|
atexit \
|
||||||
getcwd \
|
getcwd \
|
||||||
gettimeofday \
|
gettimeofday \
|
||||||
|
clock_gettime \
|
||||||
memset \
|
memset \
|
||||||
mkdir \
|
mkdir \
|
||||||
rmdir \
|
rmdir \
|
||||||
@ -238,6 +239,9 @@ AC_CHECK_FUNCS([ \
|
|||||||
process_vm_readv \
|
process_vm_readv \
|
||||||
])
|
])
|
||||||
|
|
||||||
|
AC_CHECK_LIB([rt], [clock_gettime],,
|
||||||
|
[AC_MSG_ERROR([*** librt not found on your system])]
|
||||||
|
)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Debugging
|
# Debugging
|
||||||
|
|||||||
320
dwarf.c
320
dwarf.c
@ -317,88 +317,80 @@ static const uint8_t dwarf_operands[256] = {
|
|||||||
[DW_OP_call_ref] = OPND1(OFFSET)
|
[DW_OP_call_ref] = OPND1(OFFSET)
|
||||||
};
|
};
|
||||||
|
|
||||||
static int dwarf_access_mem(struct dwarf_addr_space *as, arch_addr_t addr, void *valp, size_t size)
|
static inline __attribute__((always_inline)) int dwarf_access_mem(struct dwarf_addr_space *as, arch_addr_t addr, void *valp, size_t size)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
|
|
||||||
if (!addr) {
|
if (unlikely(!addr)) {
|
||||||
debug(DEBUG_DWARF, "invalid null memory access");
|
debug(DEBUG_DWARF, "invalid null memory access");
|
||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!valp)
|
if (unlikely(!valp))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (!as) {
|
if (unlikely(!as)) {
|
||||||
memcpy(valp, (void *)addr, size);
|
memcpy(valp, (void *)addr, size);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (as->addr && as->addr <= addr && addr + size - as->addr <= sizeof(as->val)) {
|
if (unlikely(copy_from_proc(c->task, addr, valp, size) != (int)size)) {
|
||||||
memcpy(valp, &as->val_bytes[addr - as->addr], size);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (copy_from_proc(c->task, addr, &as->val, sizeof(as->val)) != sizeof(as->val)) {
|
|
||||||
debug(DEBUG_DWARF, "cannot access memory %#lx of pid %d", addr, c->task->pid);
|
debug(DEBUG_DWARF, "cannot access memory %#lx of pid %d", addr, c->task->pid);
|
||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
as->addr = addr;
|
|
||||||
memcpy(valp, as->val_bytes, size);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dwarf_read8(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
static inline __attribute__((always_inline)) int dwarf_read8(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dwarf_access_mem(as, *addr, valp, 1);
|
ret = dwarf_access_mem(as, *addr, valp, 1);
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*addr += 1;
|
*addr += 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dwarf_read16(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
static inline __attribute__((always_inline)) int dwarf_read16(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dwarf_access_mem(as, *addr, valp, 2);
|
ret = dwarf_access_mem(as, *addr, valp, 2);
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*addr += 2;
|
*addr += 2;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dwarf_read32(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
static inline __attribute__((always_inline)) int dwarf_read32(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dwarf_access_mem(as, *addr, valp, 4);
|
ret = dwarf_access_mem(as, *addr, valp, 4);
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*addr += 4;
|
*addr += 4;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dwarf_read64(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
static inline __attribute__((always_inline)) int dwarf_read64(struct dwarf_addr_space *as, arch_addr_t *addr, void *valp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dwarf_access_mem(as, *addr, valp, 8);
|
ret = dwarf_access_mem(as, *addr, valp, 8);
|
||||||
if (ret)
|
if (unlikely(ret))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
*addr += 8;
|
*addr += 8;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int dwarf_readw(struct dwarf_addr_space *as, arch_addr_t *addr, arch_addr_t *valp, int is_64bit)
|
static int dwarf_readw(struct dwarf_addr_space *as, arch_addr_t *addr, arch_addr_t *valp, int is_64bit)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@ -428,7 +420,7 @@ static int dwarf_read_uleb128(struct dwarf_addr_space *as, arch_addr_t *addr, ar
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((ret = dwarf_read8(as, addr, &byte)) < 0)
|
if (unlikely((ret = dwarf_read8(as, addr, &byte)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
val |= ((arch_addr_t) byte & 0x7f) << shift;
|
val |= ((arch_addr_t) byte & 0x7f) << shift;
|
||||||
@ -448,7 +440,7 @@ static int dwarf_read_sleb128(struct dwarf_addr_space *as, arch_addr_t *addr, ar
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if ((ret = dwarf_read8(as, addr, &byte)) < 0)
|
if (unlikely((ret = dwarf_read8(as, addr, &byte)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
val |= ((arch_addr_t) byte & 0x7f) << shift;
|
val |= ((arch_addr_t) byte & 0x7f) << shift;
|
||||||
@ -518,7 +510,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
|
|
||||||
*addr = (initial_addr + size - 1) & -size;
|
*addr = (initial_addr + size - 1) & -size;
|
||||||
|
|
||||||
if ((ret = dwarf_readw(as, addr, tmp_ptr, is_64bit)) < 0)
|
if (unlikely((ret = dwarf_readw(as, addr, tmp_ptr, is_64bit)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
*valp = tmp.addr;
|
*valp = tmp.addr;
|
||||||
return 0;
|
return 0;
|
||||||
@ -526,45 +518,45 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
|
|
||||||
switch (encoding & DW_EH_PE_FORMAT_MASK) {
|
switch (encoding & DW_EH_PE_FORMAT_MASK) {
|
||||||
case DW_EH_PE_ptr:
|
case DW_EH_PE_ptr:
|
||||||
if ((ret = dwarf_readw(as, addr, tmp_ptr, is_64bit)) < 0)
|
if (unlikely((ret = dwarf_readw(as, addr, tmp_ptr, is_64bit)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.addr;
|
val = tmp.addr;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_uleb128:
|
case DW_EH_PE_uleb128:
|
||||||
if ((ret = dwarf_read_uleb128(as, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(as, addr, &val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_udata2:
|
case DW_EH_PE_udata2:
|
||||||
if ((ret = dwarf_read16(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read16(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.uval16;
|
val = tmp.uval16;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_udata4:
|
case DW_EH_PE_udata4:
|
||||||
if ((ret = dwarf_read32(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read32(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.uval32;
|
val = tmp.uval32;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_udata8:
|
case DW_EH_PE_udata8:
|
||||||
if ((ret = dwarf_read64(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read64(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.uval64;
|
val = tmp.uval64;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_sleb128:
|
case DW_EH_PE_sleb128:
|
||||||
if ((ret = dwarf_read_sleb128(as, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_sleb128(as, addr, &val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_sdata2:
|
case DW_EH_PE_sdata2:
|
||||||
if ((ret = dwarf_read16(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read16(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.sval16;
|
val = tmp.sval16;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_sdata4:
|
case DW_EH_PE_sdata4:
|
||||||
if ((ret = dwarf_read32(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read32(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.sval32;
|
val = tmp.sval32;
|
||||||
break;
|
break;
|
||||||
case DW_EH_PE_sdata8:
|
case DW_EH_PE_sdata8:
|
||||||
if ((ret = dwarf_read64(as, addr, tmp_ptr)) < 0)
|
if (unlikely((ret = dwarf_read64(as, addr, tmp_ptr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
val = tmp.sval64;
|
val = tmp.sval64;
|
||||||
break;
|
break;
|
||||||
@ -610,7 +602,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
arch_addr_t indirect_addr = val;
|
arch_addr_t indirect_addr = val;
|
||||||
|
|
||||||
if (tmp_ptr) {
|
if (tmp_ptr) {
|
||||||
if ((ret = dwarf_readw(indirect_as, &indirect_addr, &val, is_64bit)) < 0)
|
if (unlikely((ret = dwarf_readw(indirect_as, &indirect_addr, &val, is_64bit)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -652,7 +644,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
|
|
||||||
dci->lsda_encoding = DW_EH_PE_omit;
|
dci->lsda_encoding = DW_EH_PE_omit;
|
||||||
|
|
||||||
if ((ret = dwarf_read32(NULL, &addr, &u32val)) < 0)
|
if (unlikely((ret = dwarf_read32(NULL, &addr, &u32val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (u32val != 0xffffffff) {
|
if (u32val != 0xffffffff) {
|
||||||
@ -662,7 +654,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
len = u32val;
|
len = u32val;
|
||||||
cie_end_addr = addr + len;
|
cie_end_addr = addr + len;
|
||||||
|
|
||||||
if ((ret = dwarf_read32(NULL, &addr, &cie_id)) < 0)
|
if (unlikely((ret = dwarf_read32(NULL, &addr, &cie_id)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (cie_id) {
|
if (cie_id) {
|
||||||
@ -674,13 +666,13 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
/* the CIE is in the 64-bit DWARF format */
|
/* the CIE is in the 64-bit DWARF format */
|
||||||
uint64_t cie_id;
|
uint64_t cie_id;
|
||||||
|
|
||||||
if ((ret = dwarf_read64(NULL, &addr, &u64val)) < 0)
|
if (unlikely((ret = dwarf_read64(NULL, &addr, &u64val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
len = u64val;
|
len = u64val;
|
||||||
cie_end_addr = addr + len;
|
cie_end_addr = addr + len;
|
||||||
|
|
||||||
if ((ret = dwarf_read64(NULL, &addr, &cie_id)) < 0)
|
if (unlikely((ret = dwarf_read64(NULL, &addr, &cie_id)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (cie_id) {
|
if (cie_id) {
|
||||||
@ -690,7 +682,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
}
|
}
|
||||||
dci->cie_instr_end = cie_end_addr;
|
dci->cie_instr_end = cie_end_addr;
|
||||||
|
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &version)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &version)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (version != DWARF_CIE_VERSION && version != DWARF_CIE_VERSION_GCC) {
|
if (version != DWARF_CIE_VERSION && version != DWARF_CIE_VERSION_GCC) {
|
||||||
@ -701,7 +693,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
/* read and parse the augmentation string: */
|
/* read and parse the augmentation string: */
|
||||||
memset(augstr, 0, sizeof(augstr));
|
memset(augstr, 0, sizeof(augstr));
|
||||||
for (i = 0;;) {
|
for (i = 0;;) {
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &ch)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &ch)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (!ch)
|
if (!ch)
|
||||||
@ -711,19 +703,19 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
augstr[i++] = ch;
|
augstr[i++] = ch;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, &addr, &dci->code_align)) < 0 || (ret = dwarf_read_sleb128(NULL, &addr, &dci->data_align)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, &addr, &dci->code_align)) < 0 || (ret = dwarf_read_sleb128(NULL, &addr, &dci->data_align)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* Read the return-address column either as a u8 or as a uleb128. */
|
/* Read the return-address column either as a u8 or as a uleb128. */
|
||||||
if (version == 1) {
|
if (version == 1) {
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &ch)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &ch)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
dci->ret_addr_column = dwarf_to_regnum(ch);
|
dci->ret_addr_column = dwarf_to_regnum(ch);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
arch_addr_t val;
|
arch_addr_t val;
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, &addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, &addr, &val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
dci->ret_addr_column = dwarf_to_regnum(val);
|
dci->ret_addr_column = dwarf_to_regnum(val);
|
||||||
}
|
}
|
||||||
@ -731,7 +723,7 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
i = 0;
|
i = 0;
|
||||||
if (augstr[0] == 'z') {
|
if (augstr[0] == 'z') {
|
||||||
dci->sized_augmentation = 1;
|
dci->sized_augmentation = 1;
|
||||||
if ((ret = dwarf_read_uleb128(NULL, &addr, &aug_size)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, &addr, &aug_size)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@ -740,13 +732,13 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
switch (augstr[i]) {
|
switch (augstr[i]) {
|
||||||
case 'L':
|
case 'L':
|
||||||
/* read the LSDA pointer-encoding format. */
|
/* read the LSDA pointer-encoding format. */
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &ch)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &ch)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
dci->lsda_encoding = ch;
|
dci->lsda_encoding = ch;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
/* read the FDE pointer-encoding format. */
|
/* read the FDE pointer-encoding format. */
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &fde_encoding)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &fde_encoding)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
@ -754,9 +746,9 @@ static int parse_cie(struct dwarf_addr_space *as, arch_addr_t addr, struct dwarf
|
|||||||
uint8_t handler_encoding;
|
uint8_t handler_encoding;
|
||||||
|
|
||||||
/* read the personality-routine pointer-encoding format. */
|
/* read the personality-routine pointer-encoding format. */
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &handler_encoding)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &handler_encoding)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(as, &addr, handler_encoding, NULL, 0)) < 0)
|
if (unlikely((ret = dwarf_read_encoded_pointer_local(as, &addr, handler_encoding, NULL, 0)) < 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'S':
|
case 'S':
|
||||||
@ -791,7 +783,7 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
|||||||
struct dwarf_cie_info *dci = &as->cursor.dci;
|
struct dwarf_cie_info *dci = &as->cursor.dci;
|
||||||
arch_addr_t addr = (arch_addr_t)addrp;
|
arch_addr_t addr = (arch_addr_t)addrp;
|
||||||
|
|
||||||
if ((ret = dwarf_read32(NULL, &addr, &u32val)) < 0)
|
if (unlikely((ret = dwarf_read32(NULL, &addr, &u32val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (u32val != 0xffffffff) {
|
if (u32val != 0xffffffff) {
|
||||||
@ -809,7 +801,7 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
|||||||
fde_end_addr = addr + u32val;
|
fde_end_addr = addr + u32val;
|
||||||
cie_offset_addr = addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_read32(NULL, &addr, &cie_offset32)) < 0)
|
if (unlikely((ret = dwarf_read32(NULL, &addr, &cie_offset32)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cie_offset = cie_offset32;
|
cie_offset = cie_offset32;
|
||||||
@ -819,13 +811,13 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
|||||||
|
|
||||||
/* the FDE is in the 64-bit DWARF format */
|
/* the FDE is in the 64-bit DWARF format */
|
||||||
|
|
||||||
if ((ret = dwarf_read64(NULL, &addr, &u64val)) < 0)
|
if (unlikely((ret = dwarf_read64(NULL, &addr, &u64val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
fde_end_addr = addr + u64val;
|
fde_end_addr = addr + u64val;
|
||||||
cie_offset_addr = addr;
|
cie_offset_addr = addr;
|
||||||
|
|
||||||
if ((ret = dwarf_read64(NULL, &addr, &cie_offset64)) < 0)
|
if (unlikely((ret = dwarf_read64(NULL, &addr, &cie_offset64)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
cie_offset = cie_offset64;
|
cie_offset = cie_offset64;
|
||||||
@ -846,31 +838,32 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
|||||||
if ((ret = parse_cie(as, cie_addr, dci)) < 0)
|
if ((ret = parse_cie(as, cie_addr, dci)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->fde_encoding, &dci->start_ip, 0)) < 0)
|
if (unlikely((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->fde_encoding, &dci->start_ip, 0)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* IP-range has same encoding as FDE pointers, except that it's
|
/* IP-range has same encoding as FDE pointers, except that it's
|
||||||
always an absolute value: */
|
always an absolute value: */
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->fde_encoding & DW_EH_PE_FORMAT_MASK, &dci->ip_range, 0)) < 0)
|
if (unlikely((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->fde_encoding & DW_EH_PE_FORMAT_MASK, &dci->ip_range, 0)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (dci->sized_augmentation) {
|
if (dci->sized_augmentation) {
|
||||||
arch_addr_t aug_size;
|
arch_addr_t aug_size;
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, &addr, &aug_size)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, &addr, &aug_size)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
dci->fde_instr_start = addr + aug_size;
|
dci->fde_instr_start = addr + aug_size;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dci->fde_instr_start = addr;
|
dci->fde_instr_start = addr;
|
||||||
|
|
||||||
dci->fde_instr_end = fde_end_addr;
|
dci->fde_instr_end = fde_end_addr;
|
||||||
|
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->lsda_encoding, NULL, dci->start_ip)) < 0)
|
if (unlikely((ret = dwarf_read_encoded_pointer_local(as, &addr, dci->lsda_encoding, NULL, dci->start_ip)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (dci->have_abi_marker) {
|
if (dci->have_abi_marker) {
|
||||||
if ((ret = dwarf_read16(NULL, &addr, &dci->abi)) < 0 || (ret = dwarf_read16(NULL, &addr, &dci->tag)) < 0)
|
if (unlikely((ret = dwarf_read16(NULL, &addr, &dci->abi)) < 0 || (ret = dwarf_read16(NULL, &addr, &dci->tag)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -885,34 +878,18 @@ static inline int lib_addr_match(struct libref *libref, arch_addr_t ip)
|
|||||||
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip)
|
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct task *leader;
|
|
||||||
struct list_head *it;
|
|
||||||
|
|
||||||
if (c->use_prev_instr)
|
if (c->use_prev_instr)
|
||||||
ip -= 1;
|
ip -= 1;
|
||||||
|
|
||||||
if (as->cursor.libref) {
|
if (likely(c->libref)) {
|
||||||
if (lib_addr_match(as->cursor.libref, ip))
|
if (lib_addr_match(c->libref, ip))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
leader = c->task->leader;
|
c->libref = addr2libref(c->task->leader, ip);
|
||||||
|
if (!c->libref)
|
||||||
as->cursor.libref = NULL;
|
|
||||||
|
|
||||||
list_for_each(it, &leader->libraries_list) {
|
|
||||||
struct libref *libref = container_of(it, struct library, list)->libref;
|
|
||||||
|
|
||||||
if (lib_addr_match(libref, ip)) {
|
|
||||||
as->cursor.libref = libref;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!as->cursor.libref) {
|
|
||||||
debug(DEBUG_DWARF, "no mapping found for IP %#lx", ip);
|
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -953,7 +930,7 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
|||||||
struct libref *libref = as->cursor.libref;
|
struct libref *libref = as->cursor.libref;
|
||||||
|
|
||||||
e = lookup(table_data, table_len, ip - libref->load_addr - libref->seg_offset);
|
e = lookup(table_data, table_len, ip - libref->load_addr - libref->seg_offset);
|
||||||
if (!e) {
|
if (unlikely(!e)) {
|
||||||
/* IP is inside this table's range, but there is no explicit unwind info. */
|
/* IP is inside this table's range, but there is no explicit unwind info. */
|
||||||
debug(DEBUG_DWARF, "no unwind info found for IP %#lx", ip);
|
debug(DEBUG_DWARF, "no unwind info found for IP %#lx", ip);
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
@ -961,7 +938,7 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
|||||||
|
|
||||||
fde_addr = libref->image_addr - libref->load_offset + e->fde_offset + libref->seg_offset;
|
fde_addr = libref->image_addr - libref->load_offset + e->fde_offset + libref->seg_offset;
|
||||||
|
|
||||||
if ((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0)
|
if (unlikely((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
dci->start_ip -= ARCH_ADDR_T(libref->image_addr) - libref->load_addr;
|
dci->start_ip -= ARCH_ADDR_T(libref->image_addr) - libref->load_addr;
|
||||||
@ -969,7 +946,7 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
|||||||
if (!as->is_64bit)
|
if (!as->is_64bit)
|
||||||
dci->start_ip &= 0xffffffff;
|
dci->start_ip &= 0xffffffff;
|
||||||
|
|
||||||
if (ip < dci->start_ip || ip >= dci->start_ip + dci->ip_range) {
|
if (unlikely(ip < dci->start_ip || ip >= dci->start_ip + dci->ip_range)) {
|
||||||
debug(DEBUG_DWARF, "IP %#lx out of range %#lx-%#lx", ip, dci->start_ip, dci->start_ip + dci->ip_range);
|
debug(DEBUG_DWARF, "IP %#lx out of range %#lx-%#lx", ip, dci->start_ip, dci->start_ip + dci->ip_range);
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
}
|
}
|
||||||
@ -983,7 +960,7 @@ static int dwarf_access_reg(struct dwarf_addr_space *as, unsigned int reg, arch_
|
|||||||
|
|
||||||
int map = dwarf_arch_map_reg(as, reg);
|
int map = dwarf_arch_map_reg(as, reg);
|
||||||
|
|
||||||
if (map < 0) {
|
if (unlikely(map < 0)) {
|
||||||
debug(DEBUG_DWARF, "could not map register %u", reg);
|
debug(DEBUG_DWARF, "could not map register %u", reg);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
@ -1021,7 +998,7 @@ static int dwarf_get_reg(struct dwarf_addr_space *as, unsigned int reg, arch_add
|
|||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
|
|
||||||
if (reg >= as->num_regs)
|
if (unlikely(reg >= as->num_regs))
|
||||||
return err_inval_reg_num((unsigned int)*valp);
|
return err_inval_reg_num((unsigned int)*valp);
|
||||||
|
|
||||||
if (as->ip_reg == reg) {
|
if (as->ip_reg == reg) {
|
||||||
@ -1037,17 +1014,17 @@ static int dwarf_get_reg(struct dwarf_addr_space *as, unsigned int reg, arch_add
|
|||||||
return dwarf_get(as, c->loc[reg], valp);
|
return dwarf_get(as, c->loc[reg], valp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int read_regnum(unsigned int num_regs, arch_addr_t *addr, arch_addr_t *valp)
|
static int read_regnum(unsigned int num_regs, arch_addr_t *addr, arch_addr_t *valp)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
arch_addr_t val;
|
arch_addr_t val;
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
val = dwarf_to_regnum(val);
|
val = dwarf_to_regnum(val);
|
||||||
|
|
||||||
if (val >= num_regs)
|
if (unlikely(val >= num_regs))
|
||||||
return err_inval_reg_num(val);
|
return err_inval_reg_num(val);
|
||||||
|
|
||||||
*valp = val;
|
*valp = val;
|
||||||
@ -1086,7 +1063,7 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
/* Process everything up to and including the current 'ip',
|
/* Process everything up to and including the current 'ip',
|
||||||
including all the DW_CFA_advance_loc instructions. */
|
including all the DW_CFA_advance_loc instructions. */
|
||||||
while (curr_ip <= ip && *addr < end_addr) {
|
while (curr_ip <= ip && *addr < end_addr) {
|
||||||
if ((ret = dwarf_read8(NULL, addr, &op)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, addr, &op)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
if (op & DWARF_CFA_OPCODE_MASK) {
|
if (op & DWARF_CFA_OPCODE_MASK) {
|
||||||
@ -1098,17 +1075,17 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
curr_ip += operand * dci->code_align;
|
curr_ip += operand * dci->code_align;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_advance_loc1:
|
case DW_CFA_advance_loc1:
|
||||||
if ((ret = dwarf_read8(NULL, addr, &u8)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, addr, &u8)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u8 * dci->code_align;
|
curr_ip += u8 * dci->code_align;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_advance_loc2:
|
case DW_CFA_advance_loc2:
|
||||||
if ((ret = dwarf_read16(NULL, addr, &u16)) < 0)
|
if (unlikely((ret = dwarf_read16(NULL, addr, &u16)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u16 * dci->code_align;
|
curr_ip += u16 * dci->code_align;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_advance_loc4:
|
case DW_CFA_advance_loc4:
|
||||||
if ((ret = dwarf_read32(NULL, addr, &u32)) < 0)
|
if (unlikely((ret = dwarf_read32(NULL, addr, &u32)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
curr_ip += u32 * dci->code_align;
|
curr_ip += u32 * dci->code_align;
|
||||||
break;
|
break;
|
||||||
@ -1118,30 +1095,30 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
goto fail;
|
goto fail;
|
||||||
case DW_CFA_offset:
|
case DW_CFA_offset:
|
||||||
regnum = dwarf_to_regnum(operand);
|
regnum = dwarf_to_regnum(operand);
|
||||||
if (regnum >= num_regs) {
|
if (unlikely(regnum >= num_regs)) {
|
||||||
debug(DEBUG_DWARF, "Invalid register number %u in DW_cfa_OFFSET", (unsigned int)regnum);
|
debug(DEBUG_DWARF, "Invalid register number %u in DW_cfa_OFFSET", (unsigned int)regnum);
|
||||||
ret = -DWARF_EBADREG;
|
ret = -DWARF_EBADREG;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_offset_extended:
|
case DW_CFA_offset_extended:
|
||||||
if (((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely(((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_offset_extended_sf:
|
case DW_CFA_offset_extended_sf:
|
||||||
if (((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely(((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
||||||
|| ((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0))
|
|| ((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, val * dci->data_align);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_restore:
|
case DW_CFA_restore:
|
||||||
regnum = dwarf_to_regnum(operand);
|
regnum = dwarf_to_regnum(operand);
|
||||||
if (regnum >= num_regs) {
|
if (unlikely(regnum >= num_regs)) {
|
||||||
debug(DEBUG_DWARF, "Invalid register number %u in DW_CFA_restore", (unsigned int)regnum);
|
debug(DEBUG_DWARF, "Invalid register number %u in DW_CFA_restore", (unsigned int)regnum);
|
||||||
ret = -DWARF_EINVAL;
|
ret = -DWARF_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1149,9 +1126,9 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
rs_current->reg[regnum] = rs_initial->reg[regnum];
|
rs_current->reg[regnum] = rs_initial->reg[regnum];
|
||||||
break;
|
break;
|
||||||
case DW_CFA_restore_extended:
|
case DW_CFA_restore_extended:
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, ®num)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
if (regnum >= num_regs) {
|
if (unlikely(regnum >= num_regs)) {
|
||||||
debug(DEBUG_DWARF, "Invalid register number %u in " "DW_CFA_restore_extended", (unsigned int)regnum);
|
debug(DEBUG_DWARF, "Invalid register number %u in " "DW_CFA_restore_extended", (unsigned int)regnum);
|
||||||
ret = -DWARF_EINVAL;
|
ret = -DWARF_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1161,26 +1138,26 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
case DW_CFA_nop:
|
case DW_CFA_nop:
|
||||||
break;
|
break;
|
||||||
case DW_CFA_set_loc:
|
case DW_CFA_set_loc:
|
||||||
if ((ret = dwarf_read_encoded_pointer_local(as, addr, dci->fde_encoding, &curr_ip, c->dci.start_ip)) < 0)
|
if (unlikely((ret = dwarf_read_encoded_pointer_local(as, addr, dci->fde_encoding, &curr_ip, c->dci.start_ip)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_undefined:
|
case DW_CFA_undefined:
|
||||||
if ((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_UNDEF, 0);
|
set_reg(rs_current, regnum, DWARF_WHERE_UNDEF, 0);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_same_value:
|
case DW_CFA_same_value:
|
||||||
if ((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_SAME, 0);
|
set_reg(rs_current, regnum, DWARF_WHERE_SAME, 0);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_register:
|
case DW_CFA_register:
|
||||||
if ((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
n = dwarf_to_regnum(val);
|
n = dwarf_to_regnum(val);
|
||||||
if (n >= num_regs) {
|
if (unlikely(n >= num_regs)) {
|
||||||
debug(DEBUG_DWARF, "Invalid register number value %u in DW_CFA_REGISTER", (unsigned int)val);
|
debug(DEBUG_DWARF, "Invalid register number value %u in DW_CFA_REGISTER", (unsigned int)val);
|
||||||
ret = -DWARF_EBADREG;
|
ret = -DWARF_EBADREG;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1194,7 +1171,7 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
rs_stack = rs_tmp;
|
rs_stack = rs_tmp;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_restore_state:
|
case DW_CFA_restore_state:
|
||||||
if (!rs_stack) {
|
if (unlikely(!rs_stack)) {
|
||||||
debug(DEBUG_DWARF, "register-state stack underflow");
|
debug(DEBUG_DWARF, "register-state stack underflow");
|
||||||
ret = -DWARF_EINVAL;
|
ret = -DWARF_EINVAL;
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1205,31 +1182,31 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
free(rs_tmp);
|
free(rs_tmp);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa:
|
case DW_CFA_def_cfa:
|
||||||
if (((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if ((unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
||||||
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val); /* NOT factored! */
|
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val); /* NOT factored! */
|
||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa_sf:
|
case DW_CFA_def_cfa_sf:
|
||||||
if (((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely(((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
||||||
|| ((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0))
|
|| ((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
||||||
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val * dci->data_align); /* factored! */
|
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val * dci->data_align); /* factored! */
|
||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa_register:
|
case DW_CFA_def_cfa_register:
|
||||||
if ((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_REG, regnum);
|
||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa_offset:
|
case DW_CFA_def_cfa_offset:
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val); /* NOT factored! */
|
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val); /* NOT factored! */
|
||||||
break;
|
break;
|
||||||
case DW_CFA_def_cfa_offset_sf:
|
case DW_CFA_def_cfa_offset_sf:
|
||||||
if ((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_sleb128(NULL, addr, &val)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val * dci->data_align); /* factored! */
|
set_reg(rs_current, DWARF_CFA_OFF_COLUMN(as), 0, val * dci->data_align); /* factored! */
|
||||||
break;
|
break;
|
||||||
@ -1237,19 +1214,19 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
/* Save the address of the DW_FORM_block for later evaluation. */
|
/* Save the address of the DW_FORM_block for later evaluation. */
|
||||||
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_EXPR, *addr);
|
set_reg(rs_current, DWARF_CFA_REG_COLUMN(as), DWARF_WHERE_EXPR, *addr);
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
*addr += n;
|
*addr += n;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_expression:
|
case DW_CFA_expression:
|
||||||
if ((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely((ret = read_regnum(num_regs, addr, ®num)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
/* Save the address of the DW_FORM_block for later evaluation. */
|
/* Save the address of the DW_FORM_block for later evaluation. */
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_EXPR, *addr);
|
set_reg(rs_current, regnum, DWARF_WHERE_EXPR, *addr);
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
*addr += n;
|
*addr += n;
|
||||||
@ -1261,21 +1238,21 @@ static int run_cfi_program(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
/* Save the address of the DW_FORM_block for later evaluation. */
|
/* Save the address of the DW_FORM_block for later evaluation. */
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_VAL_EXPR, *addr);
|
set_reg(rs_current, regnum, DWARF_WHERE_VAL_EXPR, *addr);
|
||||||
|
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &n)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
*addr += n;
|
*addr += n;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_GNU_args_size:
|
case DW_CFA_GNU_args_size:
|
||||||
if ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
break;
|
break;
|
||||||
case DW_CFA_GNU_negative_offset_extended:
|
case DW_CFA_GNU_negative_offset_extended:
|
||||||
/* A comment in GCC says that this is obsoleted by
|
/* A comment in GCC says that this is obsoleted by
|
||||||
DW_CFA_offset_extended_sf, but that it's used by older
|
DW_CFA_offset_extended_sf, but that it's used by older
|
||||||
PowerPC code. */
|
PowerPC code. */
|
||||||
if (((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
if (unlikely(((ret = read_regnum(num_regs, addr, ®num)) < 0)
|
||||||
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0))
|
|| ((ret = dwarf_read_uleb128(NULL, addr, &val)) < 0)))
|
||||||
goto fail;
|
goto fail;
|
||||||
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
|
set_reg(rs_current, regnum, DWARF_WHERE_CFAREL, -(val * dci->data_align));
|
||||||
break;
|
break;
|
||||||
@ -1309,7 +1286,7 @@ static int parse_fde(struct dwarf_addr_space *as, arch_addr_t ip, struct dwarf_r
|
|||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct dwarf_reg_state *rs_initial;
|
struct dwarf_reg_state *rs_initial;
|
||||||
|
|
||||||
if (dci->ret_addr_column >= as->num_regs) {
|
if (unlikely(dci->ret_addr_column >= as->num_regs)) {
|
||||||
debug(DEBUG_DWARF, "Invalid return address column %lu", dci->ret_addr_column);
|
debug(DEBUG_DWARF, "Invalid return address column %lu", dci->ret_addr_column);
|
||||||
return -DWARF_EBADREG;
|
return -DWARF_EBADREG;
|
||||||
}
|
}
|
||||||
@ -1367,25 +1344,25 @@ static arch_addr_t read_operand(struct dwarf_addr_space *as, arch_addr_t *addr,
|
|||||||
switch (operand_type) {
|
switch (operand_type) {
|
||||||
case VAL8:
|
case VAL8:
|
||||||
ret = dwarf_read8(NULL, addr, &tmp.u8);
|
ret = dwarf_read8(NULL, addr, &tmp.u8);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
*valp = tmp.u8;
|
*valp = tmp.u8;
|
||||||
break;
|
break;
|
||||||
case VAL16:
|
case VAL16:
|
||||||
ret = dwarf_read16(NULL, addr, &tmp.u16);
|
ret = dwarf_read16(NULL, addr, &tmp.u16);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
*valp = tmp.u16;
|
*valp = tmp.u16;
|
||||||
break;
|
break;
|
||||||
case VAL32:
|
case VAL32:
|
||||||
ret = dwarf_read32(NULL, addr, &tmp.u32);
|
ret = dwarf_read32(NULL, addr, &tmp.u32);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
*valp = tmp.u32;
|
*valp = tmp.u32;
|
||||||
break;
|
break;
|
||||||
case VAL64:
|
case VAL64:
|
||||||
ret = dwarf_read64(NULL, addr, &tmp.u64);
|
ret = dwarf_read64(NULL, addr, &tmp.u64);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
*valp = tmp.u64;
|
*valp = tmp.u64;
|
||||||
break;
|
break;
|
||||||
@ -1418,7 +1395,7 @@ static int dwarf_eval_expr(struct dwarf_addr_space *as, arch_addr_t addr, struct
|
|||||||
|
|
||||||
#define pop() \
|
#define pop() \
|
||||||
({ \
|
({ \
|
||||||
if ((tos - 1) >= MAX_EXPR_STACK_SIZE) \
|
if (unlikely((tos - 1) >= MAX_EXPR_STACK_SIZE)) \
|
||||||
{ \
|
{ \
|
||||||
debug(DEBUG_DWARF, "Stack underflow"); \
|
debug(DEBUG_DWARF, "Stack underflow"); \
|
||||||
return -DWARF_EINVAL; \
|
return -DWARF_EINVAL; \
|
||||||
@ -1429,7 +1406,7 @@ static int dwarf_eval_expr(struct dwarf_addr_space *as, arch_addr_t addr, struct
|
|||||||
#define push(x) \
|
#define push(x) \
|
||||||
do { \
|
do { \
|
||||||
arch_addr_t _x = (x); \
|
arch_addr_t _x = (x); \
|
||||||
if (tos >= MAX_EXPR_STACK_SIZE) \
|
if (unlikely(tos >= MAX_EXPR_STACK_SIZE)) \
|
||||||
{ \
|
{ \
|
||||||
debug(DEBUG_DWARF, "Stack overflow"); \
|
debug(DEBUG_DWARF, "Stack overflow"); \
|
||||||
return -DWARF_EINVAL; \
|
return -DWARF_EINVAL; \
|
||||||
@ -1440,7 +1417,7 @@ do { \
|
|||||||
#define pick(n) \
|
#define pick(n) \
|
||||||
({ \
|
({ \
|
||||||
unsigned int _index = tos - 1 - (n); \
|
unsigned int _index = tos - 1 - (n); \
|
||||||
if (_index >= MAX_EXPR_STACK_SIZE) \
|
if (unlikely(_index >= MAX_EXPR_STACK_SIZE)) \
|
||||||
{ \
|
{ \
|
||||||
debug(DEBUG_DWARF, "Out-of-stack pick"); \
|
debug(DEBUG_DWARF, "Out-of-stack pick"); \
|
||||||
return -DWARF_EINVAL; \
|
return -DWARF_EINVAL; \
|
||||||
@ -1449,7 +1426,7 @@ do { \
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* read the length of the expression: */
|
/* read the length of the expression: */
|
||||||
if ((ret = dwarf_read_uleb128(NULL, &addr, &len)) < 0)
|
if (unlikely((ret = dwarf_read_uleb128(NULL, &addr, &len)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
end_addr = addr + len;
|
end_addr = addr + len;
|
||||||
@ -1457,7 +1434,7 @@ do { \
|
|||||||
push(c->cfa); /* push current CFA as required by DWARF spec */
|
push(c->cfa); /* push current CFA as required by DWARF spec */
|
||||||
|
|
||||||
while (addr < end_addr) {
|
while (addr < end_addr) {
|
||||||
if ((ret = dwarf_read8(NULL, &addr, &opcode)) < 0)
|
if (unlikely((ret = dwarf_read8(NULL, &addr, &opcode)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
operands_signature = dwarf_operands[opcode];
|
operands_signature = dwarf_operands[opcode];
|
||||||
@ -1475,12 +1452,12 @@ do { \
|
|||||||
push(opcode - DW_OP_lit0);
|
push(opcode - DW_OP_lit0);
|
||||||
break;
|
break;
|
||||||
case DW_OP_breg0 ... DW_OP_breg31:
|
case DW_OP_breg0 ... DW_OP_breg31:
|
||||||
if ((ret = dwarf_get_reg(as, dwarf_to_regnum(opcode - DW_OP_breg0), &tmp1)) < 0)
|
if (unlikely((ret = dwarf_get_reg(as, dwarf_to_regnum(opcode - DW_OP_breg0), &tmp1)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
push(tmp1 + operand1);
|
push(tmp1 + operand1);
|
||||||
break;
|
break;
|
||||||
case DW_OP_bregx:
|
case DW_OP_bregx:
|
||||||
if ((ret = dwarf_get_reg(as, dwarf_to_regnum(operand1), &tmp1)) < 0)
|
if (unlikely((ret = dwarf_get_reg(as, dwarf_to_regnum(operand1), &tmp1)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
push(tmp1 + operand2);
|
push(tmp1 + operand2);
|
||||||
break;
|
break;
|
||||||
@ -1519,7 +1496,7 @@ do { \
|
|||||||
break;
|
break;
|
||||||
case DW_OP_deref:
|
case DW_OP_deref:
|
||||||
tmp1 = pop();
|
tmp1 = pop();
|
||||||
if ((ret = dwarf_readw(as, &tmp1, &tmp2, as->is_64bit)) < 0)
|
if (unlikely((ret = dwarf_readw(as, &tmp1, &tmp2, as->is_64bit)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
push(tmp2);
|
push(tmp2);
|
||||||
break;
|
break;
|
||||||
@ -1530,18 +1507,18 @@ do { \
|
|||||||
debug(DEBUG_DWARF, "Unexpected DW_OP_deref_size size %d", (int)operand1);
|
debug(DEBUG_DWARF, "Unexpected DW_OP_deref_size size %d", (int)operand1);
|
||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
case 1:
|
case 1:
|
||||||
if ((ret = dwarf_read8(as, &tmp1, &u8)) < 0)
|
if (unlikely((ret = dwarf_read8(as, &tmp1, &u8)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
tmp2 = u8;
|
tmp2 = u8;
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
if ((ret = dwarf_read16(as, &tmp1, &u16)) < 0)
|
if (unlikely((ret = dwarf_read16(as, &tmp1, &u16)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
tmp2 = u16;
|
tmp2 = u16;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
if ((ret = dwarf_read32(as, &tmp1, &u32)) < 0)
|
if (unlikely((ret = dwarf_read32(as, &tmp1, &u32)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
tmp2 = u32;
|
tmp2 = u32;
|
||||||
if (operand1 == 3) {
|
if (operand1 == 3) {
|
||||||
@ -1556,7 +1533,7 @@ do { \
|
|||||||
case 6:
|
case 6:
|
||||||
case 7:
|
case 7:
|
||||||
case 8:
|
case 8:
|
||||||
if ((ret = dwarf_read64(as, &tmp1, &u64)) < 0)
|
if (unlikely((ret = dwarf_read64(as, &tmp1, &u64)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
tmp2 = u64;
|
tmp2 = u64;
|
||||||
if (operand1 != 8) {
|
if (operand1 != 8) {
|
||||||
@ -1759,7 +1736,7 @@ static int apply_reg_state(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
cfa = c->cfa;
|
cfa = c->cfa;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ((ret = dwarf_get_reg(as, rs->reg[DWARF_CFA_REG_COLUMN(as)].val, &cfa)) < 0)
|
if (unlikely((ret = dwarf_get_reg(as, rs->reg[DWARF_CFA_REG_COLUMN(as)].val, &cfa)) < 0))
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
cfa += rs->reg[DWARF_CFA_OFF_COLUMN(as)].val;
|
cfa += rs->reg[DWARF_CFA_OFF_COLUMN(as)].val;
|
||||||
@ -1772,7 +1749,7 @@ static int apply_reg_state(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* the returned location better be a memory location... */
|
/* the returned location better be a memory location... */
|
||||||
if (DWARF_IS_REG_LOC(cfa_loc))
|
if (unlikely(DWARF_IS_REG_LOC(cfa_loc)))
|
||||||
return -DWARF_EBADFRAME;
|
return -DWARF_EBADFRAME;
|
||||||
cfa = DWARF_GET_LOC(cfa_loc);
|
cfa = DWARF_GET_LOC(cfa_loc);
|
||||||
}
|
}
|
||||||
@ -1811,7 +1788,7 @@ static int apply_reg_state(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ret = dwarf_get(as, c->loc[c->ret_addr_column], &ip);
|
ret = dwarf_get(as, c->loc[c->ret_addr_column], &ip);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
return ret;
|
return ret;
|
||||||
c->ip = ip;
|
c->ip = ip;
|
||||||
}
|
}
|
||||||
@ -1853,9 +1830,6 @@ int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task)
|
|||||||
c->libref = NULL;
|
c->libref = NULL;
|
||||||
c->task = task;
|
c->task = task;
|
||||||
|
|
||||||
as->addr = 0;
|
|
||||||
as->val = 0;
|
|
||||||
|
|
||||||
memset(&c->dci, 0, sizeof(c->dci));
|
memset(&c->dci, 0, sizeof(c->dci));
|
||||||
|
|
||||||
ret = dwarf_arch_init_unwind(as);
|
ret = dwarf_arch_init_unwind(as);
|
||||||
@ -1875,8 +1849,6 @@ void *dwarf_init(int is_64bit)
|
|||||||
memset(as, 0, sizeof(*as));
|
memset(as, 0, sizeof(*as));
|
||||||
|
|
||||||
as->is_64bit = is_64bit;
|
as->is_64bit = is_64bit;
|
||||||
as->addr = 0;
|
|
||||||
as->val = 0;
|
|
||||||
|
|
||||||
ret = dwarf_arch_init(as);
|
ret = dwarf_arch_init(as);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
@ -1912,17 +1884,21 @@ int dwarf_step(struct dwarf_addr_space *as)
|
|||||||
int ret;
|
int ret;
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct dwarf_reg_state *rs_current;
|
struct dwarf_reg_state *rs_current;
|
||||||
arch_addr_t ip, cfa;
|
arch_addr_t ip;
|
||||||
|
#ifdef GUESS_CALLER
|
||||||
|
arch_addr_t cfa = c->cfa;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!c->valid)
|
if (!c->valid)
|
||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
|
|
||||||
ip = c->ip;
|
ip = c->ip;
|
||||||
cfa = c->cfa;
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
ret = dwarf_locate_map(as, ip);
|
ret = dwarf_locate_map(as, ip);
|
||||||
if (ret < 0)
|
if (unlikely(ret < 0))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* The 'ip' can point either to the previous or next instruction
|
/* The 'ip' can point either to the previous or next instruction
|
||||||
depending on what type of frame we have: normal call or a place
|
depending on what type of frame we have: normal call or a place
|
||||||
@ -1976,13 +1952,9 @@ fail:
|
|||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
#ifdef GUESS_CALLER
|
#ifdef GUESS_CALLER
|
||||||
ssize_t n;
|
unsigned char buf[512];
|
||||||
unsigned char buf[4096];
|
unsigned int off;
|
||||||
|
|
||||||
n = copy_from_proc(c->task, cfa, &buf, ARRAY_SIZE(buf));
|
|
||||||
if (n > 0) {
|
|
||||||
arch_addr_t (*getval)(unsigned char *buf);
|
arch_addr_t (*getval)(unsigned char *buf);
|
||||||
ssize_t i;
|
|
||||||
ssize_t addr_size = DWARF_ADDR_SIZE(as);
|
ssize_t addr_size = DWARF_ADDR_SIZE(as);
|
||||||
|
|
||||||
if (addr_size == 8)
|
if (addr_size == 8)
|
||||||
@ -1990,21 +1962,29 @@ fail:
|
|||||||
else
|
else
|
||||||
getval = get32val;
|
getval = get32val;
|
||||||
|
|
||||||
|
for(off = 0; off <= 4096; off += ARRAY_SIZE(buf)) {
|
||||||
|
size_t i, n;
|
||||||
|
|
||||||
|
n = copy_from_proc(c->task, cfa, &buf, ARRAY_SIZE(buf));
|
||||||
|
|
||||||
for(i = 0; i + addr_size <= n ; i += addr_size) {
|
for(i = 0; i + addr_size <= n ; i += addr_size) {
|
||||||
ip = getval(&buf[i]);
|
ip = getval(&buf[i]);
|
||||||
|
|
||||||
#if 0
|
if (unlikely(!dwarf_locate_map(as, ip) && dwarf_arch_check_call(as, ip))) {
|
||||||
if (c->ip - ip < 16384)
|
|
||||||
continue;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!dwarf_locate_map(as, ip) && dwarf_arch_check_call(as, ip)) {
|
|
||||||
c->cfa = cfa + i + addr_size;
|
c->cfa = cfa + i + addr_size;
|
||||||
c->ip = ip;
|
c->ip = ip;
|
||||||
|
|
||||||
|
c->ret_addr_column = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < as->num_regs; ++i)
|
||||||
|
c->loc[i] = DWARF_NULL_LOC;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(n < (ssize_t)ARRAY_SIZE(buf)))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
debug(DEBUG_DWARF, "error %d", ret);
|
debug(DEBUG_DWARF, "error %d", ret);
|
||||||
@ -2015,16 +1995,6 @@ fail:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as)
|
|
||||||
{
|
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
|
||||||
|
|
||||||
if (!c->valid)
|
|
||||||
return ARCH_ADDR_T(0);
|
|
||||||
|
|
||||||
return c->ip;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr)
|
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr)
|
||||||
{
|
{
|
||||||
arch_addr_t addr, fde_count;
|
arch_addr_t addr, fde_count;
|
||||||
@ -2063,13 +2033,3 @@ int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwar
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dwarf_location_type(struct dwarf_addr_space *as)
|
|
||||||
{
|
|
||||||
struct libref *libref = as->cursor.libref;
|
|
||||||
|
|
||||||
if (!libref)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return libref->type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
31
dwarf.h
31
dwarf.h
@ -27,7 +27,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
|
#include "common.h"
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
#include "library.h"
|
||||||
#include "mtelf.h"
|
#include "mtelf.h"
|
||||||
|
|
||||||
#define DWARF_LOC(r, t) ((struct dwarf_loc){ .val = (r), .type = (t) })
|
#define DWARF_LOC(r, t) ((struct dwarf_loc){ .val = (r), .type = (t) })
|
||||||
@ -96,11 +98,6 @@ struct dwarf_cursor {
|
|||||||
|
|
||||||
struct dwarf_addr_space {
|
struct dwarf_addr_space {
|
||||||
unsigned int is_64bit:1;
|
unsigned int is_64bit:1;
|
||||||
arch_addr_t addr;
|
|
||||||
union {
|
|
||||||
long val;
|
|
||||||
unsigned char val_bytes[sizeof(long)];
|
|
||||||
};
|
|
||||||
struct dwarf_cursor cursor;
|
struct dwarf_cursor cursor;
|
||||||
unsigned int ip_reg;
|
unsigned int ip_reg;
|
||||||
unsigned int ret_reg;
|
unsigned int ret_reg;
|
||||||
@ -113,7 +110,6 @@ void *dwarf_init(int is_64bit);
|
|||||||
void dwarf_destroy(struct dwarf_addr_space *as);
|
void dwarf_destroy(struct dwarf_addr_space *as);
|
||||||
int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task);
|
int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task);
|
||||||
int dwarf_step(struct dwarf_addr_space *as);
|
int dwarf_step(struct dwarf_addr_space *as);
|
||||||
arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as);
|
|
||||||
|
|
||||||
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
|
int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
|
||||||
|
|
||||||
@ -121,8 +117,6 @@ int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *va
|
|||||||
|
|
||||||
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr);
|
int dwarf_get_unwind_table(struct task *task, struct libref *libref, struct dwarf_eh_frame_hdr *hdr);
|
||||||
|
|
||||||
int dwarf_location_type(struct dwarf_addr_space *as);
|
|
||||||
|
|
||||||
int dwarf_arch_init(struct dwarf_addr_space *as);
|
int dwarf_arch_init(struct dwarf_addr_space *as);
|
||||||
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
|
int dwarf_arch_init_unwind(struct dwarf_addr_space *as);
|
||||||
int dwarf_arch_step(struct dwarf_addr_space *as);
|
int dwarf_arch_step(struct dwarf_addr_space *as);
|
||||||
@ -132,11 +126,30 @@ int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip);
|
|||||||
#ifdef DWARF_TO_REGNUM
|
#ifdef DWARF_TO_REGNUM
|
||||||
unsigned int dwarf_to_regnum(unsigned int reg);
|
unsigned int dwarf_to_regnum(unsigned int reg);
|
||||||
#else
|
#else
|
||||||
static inline unsigned int dwarf_to_regnum(unsigned int reg)
|
static inline __attribute__((const)) unsigned int dwarf_to_regnum(unsigned int reg)
|
||||||
{
|
{
|
||||||
return reg;
|
return reg;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as)
|
||||||
|
{
|
||||||
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
|
|
||||||
|
if (unlikely(!c->valid))
|
||||||
|
return ARCH_ADDR_T(0);
|
||||||
|
|
||||||
|
return c->ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int dwarf_location_type(struct dwarf_addr_space *as)
|
||||||
|
{
|
||||||
|
struct libref *libref = as->cursor.libref;
|
||||||
|
|
||||||
|
if (!libref)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return libref->type;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
60
event.c
60
event.c
@ -45,10 +45,12 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "main.h"
|
||||||
#include "mtrace.h"
|
#include "mtrace.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
static LIST_HEAD(event_head);
|
static LIST_HEAD(event_head);
|
||||||
@ -114,7 +116,7 @@ static void handle_clone(struct task *task, enum event_type type)
|
|||||||
|
|
||||||
debug(DEBUG_FUNCTION, "pid=%d, newpid=%d", task->pid, newpid);
|
debug(DEBUG_FUNCTION, "pid=%d, newpid=%d", task->pid, newpid);
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
show_clone(task, type);
|
show_clone(task, type);
|
||||||
|
|
||||||
continue_task(task, 0);
|
continue_task(task, 0);
|
||||||
@ -152,7 +154,7 @@ fail:
|
|||||||
|
|
||||||
static void handle_signal(struct task *task)
|
static void handle_signal(struct task *task)
|
||||||
{
|
{
|
||||||
if (options.verbose > 1) {
|
if (unlikely(options.verbose > 1)) {
|
||||||
if (task->event.e_un.signum && (task->event.e_un.signum != SIGSTOP || !task->was_stopped))
|
if (task->event.e_un.signum && (task->event.e_un.signum != SIGSTOP || !task->was_stopped))
|
||||||
fprintf(stderr, "+++ process pid=%d signal %d: %s +++\n", task->pid, task->event.e_un.signum, strsignal(task->event.e_un.signum));
|
fprintf(stderr, "+++ process pid=%d signal %d: %s +++\n", task->pid, task->event.e_un.signum, strsignal(task->event.e_un.signum));
|
||||||
}
|
}
|
||||||
@ -162,7 +164,7 @@ static void handle_signal(struct task *task)
|
|||||||
|
|
||||||
static void show_exit(struct task *task)
|
static void show_exit(struct task *task)
|
||||||
{
|
{
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "+++ process pid=%d exited (status=%d) +++\n", task->pid, task->event.e_un.ret_val);
|
fprintf(stderr, "+++ process pid=%d exited (status=%d) +++\n", task->pid, task->event.e_un.ret_val);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -170,7 +172,7 @@ static void show_exit(struct task *task)
|
|||||||
static void handle_about_exit(struct task *task)
|
static void handle_about_exit(struct task *task)
|
||||||
{
|
{
|
||||||
if (task->leader == task) {
|
if (task->leader == task) {
|
||||||
if (report_about_exit(task) != -1) {
|
if (!options.logfile && report_about_exit(task) != -1) {
|
||||||
task->about_exit = 1;
|
task->about_exit = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -193,7 +195,7 @@ static void handle_exit(struct task *task)
|
|||||||
|
|
||||||
static void handle_exit_signal(struct task *task)
|
static void handle_exit_signal(struct task *task)
|
||||||
{
|
{
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "+++ process pid=%d killed by signal %s (%d) +++\n", task->pid, strsignal(task->event.e_un.signum), task->event.e_un.signum);
|
fprintf(stderr, "+++ process pid=%d killed by signal %s (%d) +++\n", task->pid, strsignal(task->event.e_un.signum), task->event.e_un.signum);
|
||||||
|
|
||||||
if (task->leader == task) {
|
if (task->leader == task) {
|
||||||
@ -217,7 +219,7 @@ static void handle_exec(struct task *task)
|
|||||||
goto untrace;
|
goto untrace;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "+++ process pid=%d exec (%s) +++\n", task->pid, library_execname(task));
|
fprintf(stderr, "+++ process pid=%d exec (%s) +++\n", task->pid, library_execname(task));
|
||||||
|
|
||||||
continue_task(task, 0);
|
continue_task(task, 0);
|
||||||
@ -230,11 +232,19 @@ untrace:
|
|||||||
|
|
||||||
static int handle_call_after(struct task *task, struct breakpoint *bp)
|
static int handle_call_after(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
if (!task->breakpoint)
|
if (!task->breakpoint)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
task->libsym->func->report_out(task, task->libsym);
|
task->libsym->func->report_out(task, task->libsym);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &report_out_time);
|
||||||
|
|
||||||
task->breakpoint = NULL;
|
task->breakpoint = NULL;
|
||||||
task->libsym = NULL;
|
task->libsym = NULL;
|
||||||
|
|
||||||
@ -244,20 +254,33 @@ static int handle_call_after(struct task *task, struct breakpoint *bp)
|
|||||||
static void handle_breakpoint(struct task *task)
|
static void handle_breakpoint(struct task *task)
|
||||||
{
|
{
|
||||||
struct breakpoint *bp = task->event.e_un.breakpoint;
|
struct breakpoint *bp = task->event.e_un.breakpoint;
|
||||||
|
unsigned int hw = bp->hw;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&task->halt_time, hw ? &hw_bp_time : &sw_bp_time);
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 1
|
#if HW_BREAKPOINTS > 1
|
||||||
if (bp->type >= BP_HW) {
|
if (bp->type >= BP_HW) {
|
||||||
if (++bp->hwcnt >= (BP_REORDER_THRESHOLD << bp->hw))
|
if (unlikely(++bp->hwcnt >= (BP_REORDER_THRESHOLD << hw))) {
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
reorder_hw_bp(task);
|
reorder_hw_bp(task);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &reorder_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
++bp->count;
|
++bp->count;
|
||||||
|
|
||||||
if (bp->deleted) {
|
if (unlikely(bp->deleted)) {
|
||||||
struct breakpoint *nbp = breakpoint_find(task, bp->addr);
|
struct breakpoint *nbp = breakpoint_find(task, bp->addr);
|
||||||
|
|
||||||
if (!nbp)
|
if (!nbp)
|
||||||
@ -267,26 +290,26 @@ static void handle_breakpoint(struct task *task)
|
|||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->skip_bp == bp) {
|
if (unlikely(task->skip_bp == bp)) {
|
||||||
breakpoint_put(task->skip_bp);
|
breakpoint_put(task->skip_bp);
|
||||||
task->skip_bp = NULL;
|
task->skip_bp = NULL;
|
||||||
skip_breakpoint(task, bp);
|
skip_breakpoint(task, bp);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (breakpoint_on_hit(task, bp)) {
|
if (unlikely(breakpoint_on_hit(task, bp))) {
|
||||||
continue_task(task, 0);
|
continue_task(task, 0);
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp->libsym && !task->breakpoint) {
|
if (likely(bp->libsym && !task->breakpoint)) {
|
||||||
struct library_symbol *libsym = bp->libsym;
|
struct library_symbol *libsym = bp->libsym;
|
||||||
|
|
||||||
save_param_context(task);
|
save_param_context(task);
|
||||||
|
|
||||||
if (libsym->func->report_out) {
|
if (libsym->func->report_out) {
|
||||||
task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, BP_HW_SCRATCH);
|
task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, BP_HW_SCRATCH);
|
||||||
if (task->breakpoint) {
|
if (likely(task->breakpoint)) {
|
||||||
task->libsym = libsym;
|
task->libsym = libsym;
|
||||||
task->breakpoint->on_hit = handle_call_after;
|
task->breakpoint->on_hit = handle_call_after;
|
||||||
|
|
||||||
@ -294,8 +317,17 @@ static void handle_breakpoint(struct task *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (libsym->func->report_in)
|
if (libsym->func->report_in) {
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
libsym->func->report_in(task, libsym);
|
libsym->func->report_in(task, libsym);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &report_in_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task->stopped)
|
if (task->stopped)
|
||||||
|
|||||||
60
library.c
60
library.c
@ -120,15 +120,18 @@ void library_delete(struct task *task, struct library *lib)
|
|||||||
|
|
||||||
struct list_head *it, *next;
|
struct list_head *it, *next;
|
||||||
struct libref *libref = lib->libref;
|
struct libref *libref = lib->libref;
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
list_for_each_safe(it, next, &libref->sym_list) {
|
list_for_each_safe(it, next, &libref->sym_list) {
|
||||||
struct breakpoint *bp = breakpoint_find(task, container_of(it, struct library_symbol, list)->addr);
|
struct breakpoint *bp = breakpoint_find(leader, container_of(it, struct library_symbol, list)->addr);
|
||||||
|
|
||||||
if (bp)
|
if (bp)
|
||||||
breakpoint_delete(task, bp);
|
breakpoint_delete(leader, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&lib->list);
|
list_del(&lib->list);
|
||||||
|
rb_erase(&lib->rb_node, &leader->libraries_tree);
|
||||||
|
|
||||||
free(lib);
|
free(lib);
|
||||||
|
|
||||||
libref_put(libref);
|
libref_put(libref);
|
||||||
@ -170,7 +173,7 @@ void library_delete_list(struct task *leader, struct list_head *list)
|
|||||||
|
|
||||||
debug(DEBUG_FUNCTION, "%s@%#lx", libref->filename, libref->base);
|
debug(DEBUG_FUNCTION, "%s@%#lx", libref->filename, libref->base);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (unlikely(options.verbose > 1))
|
||||||
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
|
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
|
||||||
|
|
||||||
library_delete(leader, lib);
|
library_delete(leader, lib);
|
||||||
@ -208,6 +211,52 @@ static void library_each_symbol(struct libref *libref, void (*cb)(struct library
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int lib_addr_match(struct libref *libref, arch_addr_t addr)
|
||||||
|
{
|
||||||
|
return addr >= libref->load_addr && addr < libref->load_addr + libref->load_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct libref *addr2libref(struct task *leader, arch_addr_t addr)
|
||||||
|
{
|
||||||
|
struct rb_node **new = &(leader->libraries_tree.rb_node);
|
||||||
|
|
||||||
|
/* Figure out where to put new node */
|
||||||
|
while (*new) {
|
||||||
|
struct libref *this = container_of(*new, struct library, rb_node)->libref;
|
||||||
|
|
||||||
|
if (lib_addr_match(this, addr))
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (this->load_addr < addr)
|
||||||
|
new = &((*new)->rb_left);
|
||||||
|
else
|
||||||
|
new = &((*new)->rb_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void insert_lib(struct task *leader, struct library *lib)
|
||||||
|
{
|
||||||
|
struct rb_node **new = &(leader->libraries_tree.rb_node), *parent = NULL;
|
||||||
|
|
||||||
|
/* Figure out where to put new node */
|
||||||
|
while (*new) {
|
||||||
|
struct library *this = container_of(*new, struct library, rb_node);
|
||||||
|
|
||||||
|
parent = *new;
|
||||||
|
|
||||||
|
if (this->libref->load_addr < lib->libref->load_addr)
|
||||||
|
new = &((*new)->rb_left);
|
||||||
|
else
|
||||||
|
new = &((*new)->rb_right);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add new node and rebalance tree. */
|
||||||
|
rb_link_node(&lib->rb_node, parent, new);
|
||||||
|
rb_insert_color(&lib->rb_node, &leader->libraries_tree);
|
||||||
|
}
|
||||||
|
|
||||||
static struct library *_library_add(struct task *leader, struct libref *libref)
|
static struct library *_library_add(struct task *leader, struct libref *libref)
|
||||||
{
|
{
|
||||||
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", libref->filename, libref->base, leader->pid);
|
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", libref->filename, libref->base, leader->pid);
|
||||||
@ -225,7 +274,9 @@ static struct library *_library_add(struct task *leader, struct libref *libref)
|
|||||||
|
|
||||||
list_add_tail(&lib->list, &leader->libraries_list);
|
list_add_tail(&lib->list, &leader->libraries_list);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
insert_lib(leader, lib);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
|
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, libref->filename, libref->base, libref->load_addr, libref->load_addr + libref->load_size);
|
||||||
|
|
||||||
return lib;
|
return lib;
|
||||||
@ -263,6 +314,7 @@ int library_clone_all(struct task *clone, struct task *leader)
|
|||||||
void library_setup(struct task *leader)
|
void library_setup(struct task *leader)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&leader->libraries_list);
|
INIT_LIST_HEAD(&leader->libraries_list);
|
||||||
|
leader->libraries_tree = RB_ROOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *library_execname(struct task *leader)
|
const char *library_execname(struct task *leader)
|
||||||
|
|||||||
@ -30,6 +30,7 @@
|
|||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "mtelf.h"
|
#include "mtelf.h"
|
||||||
|
#include "rbtree.h"
|
||||||
|
|
||||||
#define LIBTYPE_LIB 0
|
#define LIBTYPE_LIB 0
|
||||||
#define LIBTYPE_MAIN 1
|
#define LIBTYPE_MAIN 1
|
||||||
@ -89,6 +90,9 @@ struct library {
|
|||||||
/* link list of libraries associated with the task */
|
/* link list of libraries associated with the task */
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
|
|
||||||
|
/* red/black tree of libraries associated with the task */
|
||||||
|
struct rb_node rb_node;
|
||||||
|
|
||||||
/* pointer to the real library refernce */
|
/* pointer to the real library refernce */
|
||||||
struct libref *libref;
|
struct libref *libref;
|
||||||
};
|
};
|
||||||
@ -132,5 +136,8 @@ void libref_delete(struct libref *libref);
|
|||||||
/* Set library filename. Frees the old name if necessary. */
|
/* Set library filename. Frees the old name if necessary. */
|
||||||
void libref_set_filename(struct libref *libref, const char *new_name);
|
void libref_set_filename(struct libref *libref, const char *new_name);
|
||||||
|
|
||||||
|
/* find library by address */
|
||||||
|
struct libref *addr2libref(struct task *leader, arch_addr_t addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
26
main.c
26
main.c
@ -50,6 +50,15 @@
|
|||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
struct mt_timer stop_time;
|
||||||
|
struct mt_timer sw_bp_time;
|
||||||
|
struct mt_timer hw_bp_time;
|
||||||
|
struct mt_timer backtrace_time;
|
||||||
|
struct mt_timer reorder_time;
|
||||||
|
struct mt_timer report_in_time;
|
||||||
|
struct mt_timer report_out_time;
|
||||||
|
struct mt_timer skip_bp_time;
|
||||||
|
|
||||||
static int do_exit;
|
static int do_exit;
|
||||||
|
|
||||||
void mtrace_request_exit(void)
|
void mtrace_request_exit(void)
|
||||||
@ -57,7 +66,7 @@ void mtrace_request_exit(void)
|
|||||||
if (do_exit)
|
if (do_exit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "+++ request exit +++\n");
|
fprintf(stderr, "+++ request exit +++\n");
|
||||||
|
|
||||||
do_exit = 1;
|
do_exit = 1;
|
||||||
@ -69,10 +78,10 @@ static void detach_process(struct task *leader)
|
|||||||
if (!leader)
|
if (!leader)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
report_detach(leader);
|
|
||||||
|
|
||||||
pid_t pid = leader->pid;
|
pid_t pid = leader->pid;
|
||||||
|
|
||||||
|
report_detach(leader);
|
||||||
|
|
||||||
while(server_handle_command() != -1) {
|
while(server_handle_command() != -1) {
|
||||||
struct task *task = pid2task(pid);
|
struct task *task = pid2task(pid);
|
||||||
|
|
||||||
@ -99,16 +108,13 @@ static void mtrace_init(char **cmd)
|
|||||||
{
|
{
|
||||||
struct opt_p_t *opt_p_tmp;
|
struct opt_p_t *opt_p_tmp;
|
||||||
|
|
||||||
if (os_init())
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
|
||||||
if (options.command) {
|
if (options.command) {
|
||||||
struct task *task = task_create(options.command, cmd);
|
struct task *task = task_create(options.command, cmd);
|
||||||
|
|
||||||
if (!task)
|
if (!task)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "+++ process pid=%d created (%s) +++\n", task->pid, library_execname(task));
|
fprintf(stderr, "+++ process pid=%d created (%s) +++\n", task->pid, library_execname(task));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,6 +140,8 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char **cmd = process_options(argc, argv);
|
char **cmd = process_options(argc, argv);
|
||||||
|
|
||||||
|
init_pid_hash();
|
||||||
|
|
||||||
if (options.trace) {
|
if (options.trace) {
|
||||||
if (options.logfile) {
|
if (options.logfile) {
|
||||||
if (server_logfile() == -1)
|
if (server_logfile() == -1)
|
||||||
@ -175,10 +183,14 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (os_init())
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
|
||||||
mtrace_init(cmd);
|
mtrace_init(cmd);
|
||||||
mtrace_main();
|
mtrace_main();
|
||||||
mtrace_exit();
|
mtrace_exit();
|
||||||
|
|
||||||
|
report_info(0);
|
||||||
report_disconnect();
|
report_disconnect();
|
||||||
|
|
||||||
#if !DISABLE_CLIENT
|
#if !DISABLE_CLIENT
|
||||||
|
|||||||
11
main.h
11
main.h
@ -23,7 +23,18 @@
|
|||||||
#ifndef _INC_MAIN_H
|
#ifndef _INC_MAIN_H
|
||||||
#define _INC_MAIN_H
|
#define _INC_MAIN_H
|
||||||
|
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
void mtrace_request_exit(void);
|
void mtrace_request_exit(void);
|
||||||
|
|
||||||
|
struct mt_timer stop_time;
|
||||||
|
struct mt_timer sw_bp_time;
|
||||||
|
struct mt_timer hw_bp_time;
|
||||||
|
struct mt_timer backtrace_time;
|
||||||
|
struct mt_timer reorder_time;
|
||||||
|
struct mt_timer report_in_time;
|
||||||
|
struct mt_timer report_out_time;
|
||||||
|
struct mt_timer skip_bp_time;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
41
memtrace.h
41
memtrace.h
@ -31,15 +31,15 @@
|
|||||||
#define IS64BIT 0
|
#define IS64BIT 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MEMTRACE_SI_VERSION 5
|
#define MEMTRACE_SI_VERSION 6
|
||||||
|
|
||||||
#define MEMTRACE_SI_FORK 1
|
#define MEMTRACE_SI_FORK 1
|
||||||
#define MEMTRACE_SI_EXEC 2
|
#define MEMTRACE_SI_EXEC 2
|
||||||
#define MEMTRACE_SI_VERBOSE 4
|
#define MEMTRACE_SI_VERBOSE 4
|
||||||
|
|
||||||
enum mt_operation {
|
enum mt_operation {
|
||||||
|
MT_INFO = 0,
|
||||||
MT_DISCONNECT,
|
MT_DISCONNECT,
|
||||||
MT_INFO,
|
|
||||||
MT_ADD_MAP,
|
MT_ADD_MAP,
|
||||||
MT_DEL_MAP,
|
MT_DEL_MAP,
|
||||||
MT_ATTACH,
|
MT_ATTACH,
|
||||||
@ -50,7 +50,7 @@ enum mt_operation {
|
|||||||
MT_NOFOLLOW,
|
MT_NOFOLLOW,
|
||||||
MT_MALLOC,
|
MT_MALLOC,
|
||||||
MT_REALLOC_ENTER,
|
MT_REALLOC_ENTER,
|
||||||
MT_REALLOC_FAILED,
|
MT_REALLOC_DONE,
|
||||||
MT_REALLOC,
|
MT_REALLOC,
|
||||||
MT_FREE,
|
MT_FREE,
|
||||||
MT_MMAP,
|
MT_MMAP,
|
||||||
@ -71,47 +71,62 @@ enum mt_operation {
|
|||||||
MT_DELETE_ARRAY,
|
MT_DELETE_ARRAY,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_msg {
|
struct __attribute__((packed)) mt_msg {
|
||||||
uint16_t operation;
|
uint16_t operation;
|
||||||
uint32_t pid;
|
uint16_t pid;
|
||||||
uint32_t tid;
|
|
||||||
uint32_t payload_len;
|
uint32_t payload_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_attached_payload {
|
struct __attribute__((packed)) mt_attached_payload {
|
||||||
uint8_t attached;
|
uint8_t attached;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_alloc_payload_64 {
|
struct __attribute__((packed)) mt_alloc_payload_64 {
|
||||||
uint64_t ptr;
|
uint64_t ptr;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
uint64_t data[0];
|
uint64_t data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_alloc_payload_32 {
|
struct __attribute__((packed)) mt_alloc_payload_32 {
|
||||||
uint32_t ptr;
|
uint32_t ptr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t data[0];
|
uint32_t data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_pid_payload {
|
struct __attribute__((packed)) mt_pid_payload {
|
||||||
uint32_t pid;
|
uint32_t pid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_scan_payload {
|
struct __attribute__((packed)) mt_scan_payload {
|
||||||
uint32_t ptr_size;
|
uint32_t ptr_size;
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
char data[0];
|
char data[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct memtrace_info {
|
struct __attribute__((packed)) memtrace_timer_info {
|
||||||
|
uint32_t max;
|
||||||
|
uint32_t count;
|
||||||
|
uint64_t culminate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((packed)) memtrace_info {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
uint8_t mode;
|
uint8_t mode;
|
||||||
uint8_t do_trace;
|
uint8_t do_trace;
|
||||||
uint8_t stack_depth;
|
uint8_t stack_depth;
|
||||||
|
uint8_t verbose;
|
||||||
|
uint8_t unused[3];
|
||||||
|
struct memtrace_timer_info stop_time;
|
||||||
|
struct memtrace_timer_info sw_bp_time;
|
||||||
|
struct memtrace_timer_info hw_bp_time;
|
||||||
|
struct memtrace_timer_info backtrace_time;
|
||||||
|
struct memtrace_timer_info reorder_time;
|
||||||
|
struct memtrace_timer_info report_in_time;
|
||||||
|
struct memtrace_timer_info report_out_time;
|
||||||
|
struct memtrace_timer_info skip_bp_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct mt_map_payload {
|
struct __attribute__((packed)) mt_map_payload {
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint64_t offset;
|
uint64_t offset;
|
||||||
uint64_t size;
|
uint64_t size;
|
||||||
|
|||||||
7
mtelf.c
7
mtelf.c
@ -191,7 +191,7 @@ static int populate_this_symtab(struct mt_elf *mte, struct libref *libref, Elf_D
|
|||||||
if (libsym->func->level > func->level)
|
if (libsym->func->level > func->level)
|
||||||
libsym->func = func;
|
libsym->func = func;
|
||||||
}
|
}
|
||||||
if (options.verbose > 1)
|
if (unlikely(options.verbose > 1))
|
||||||
fprintf(stderr, "breakpoint for %s:%s at %#lx\n", libref->filename, func->demangled_name, addr);
|
fprintf(stderr, "breakpoint for %s:%s at %#lx\n", libref->filename, func->demangled_name, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,6 +220,7 @@ static int populate_symtab(struct mt_elf *mte, struct libref *libref)
|
|||||||
static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
|
static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
|
||||||
{
|
{
|
||||||
void *addr;
|
void *addr;
|
||||||
|
volatile char *p;
|
||||||
|
|
||||||
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
|
addr = mmap(NULL, mte->txt_hdr.p_filesz, PROT_READ, MAP_PRIVATE, mte->fd, mte->txt_hdr.p_offset);
|
||||||
if (addr == MAP_FAILED) {
|
if (addr == MAP_FAILED) {
|
||||||
@ -229,6 +230,10 @@ static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
|
|||||||
|
|
||||||
*image_addr = addr;
|
*image_addr = addr;
|
||||||
|
|
||||||
|
/* prefetch */
|
||||||
|
for(p = addr; (void *)p <= addr + mte->txt_hdr.p_filesz; p += PAGE_SIZE)
|
||||||
|
*p;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
#ifndef _INC_OPTIONS_H
|
#ifndef _INC_OPTIONS_H
|
||||||
#define _INC_OPTIONS_H
|
#define _INC_OPTIONS_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|||||||
242
report.c
242
report.c
@ -34,14 +34,16 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "main.h"
|
||||||
#include "memtrace.h"
|
#include "memtrace.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "timer.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
static int report_alloc64(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, unsigned int depth, struct library_symbol *libsym)
|
static void report_alloc64(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, unsigned int depth, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
struct mt_alloc_payload_64 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint64_t));
|
struct mt_alloc_payload_64 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint64_t));
|
||||||
@ -53,20 +55,20 @@ static int report_alloc64(struct task *task, enum mt_operation op, unsigned long
|
|||||||
if (libsym)
|
if (libsym)
|
||||||
alloc->data[i++] = libsym->addr;
|
alloc->data[i++] = libsym->addr;
|
||||||
|
|
||||||
if (backtrace_init_unwind(task) >= 0) {
|
if (likely(backtrace_init_unwind(task) >= 0)) {
|
||||||
while(i < depth) {
|
while(i < depth) {
|
||||||
if (backtrace_location_type(task) != LIBTYPE_LOADER) {
|
if (likely(backtrace_location_type(task) != LIBTYPE_LOADER)) {
|
||||||
alloc->data[i] = (uint64_t)backtrace_get_ip(task);
|
alloc->data[i] = (uint64_t)backtrace_get_ip(task);
|
||||||
|
|
||||||
if (!i || alloc->data[i - 1] != alloc->data[i]) {
|
if (likely(!i || alloc->data[i - 1] != alloc->data[i])) {
|
||||||
if (!alloc->data[i])
|
if (unlikely(!alloc->data[i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backtrace_step(task) < 0)
|
if (unlikely(backtrace_step(task) < 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,10 +76,10 @@ static int report_alloc64(struct task *task, enum mt_operation op, unsigned long
|
|||||||
|
|
||||||
skip_breakpoint(task, task->event.e_un.breakpoint);
|
skip_breakpoint(task, task->event.e_un.breakpoint);
|
||||||
|
|
||||||
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint64_t));
|
server_send_msg(op, task->leader->pid, alloc, sizeof(*alloc) + i * sizeof(uint64_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_alloc32(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth, struct library_symbol *libsym)
|
static void report_alloc32(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
struct mt_alloc_payload_32 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint32_t));
|
struct mt_alloc_payload_32 *alloc = alloca(sizeof(*alloc) + depth * sizeof(uint32_t));
|
||||||
@ -89,20 +91,20 @@ static int report_alloc32(struct task *task, enum mt_operation op, unsigned long
|
|||||||
if (libsym)
|
if (libsym)
|
||||||
alloc->data[i++] = libsym->addr;
|
alloc->data[i++] = libsym->addr;
|
||||||
|
|
||||||
if (backtrace_init_unwind(task) >= 0) {
|
if (likely(backtrace_init_unwind(task) >= 0)) {
|
||||||
while(i < depth) {
|
while(i < depth) {
|
||||||
if (backtrace_location_type(task) != LIBTYPE_LOADER) {
|
if (likely(backtrace_location_type(task) != LIBTYPE_LOADER)) {
|
||||||
alloc->data[i] = (uint32_t)backtrace_get_ip(task);
|
alloc->data[i] = (uint32_t)backtrace_get_ip(task);
|
||||||
|
|
||||||
if (!i || alloc->data[i - 1] != alloc->data[i]) {
|
if (likely(!i || alloc->data[i - 1] != alloc->data[i])) {
|
||||||
if (!alloc->data[i])
|
if (unlikely(!alloc->data[i]))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (backtrace_step(task) < 0)
|
if (unlikely(backtrace_step(task) < 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -110,142 +112,132 @@ static int report_alloc32(struct task *task, enum mt_operation op, unsigned long
|
|||||||
|
|
||||||
skip_breakpoint(task, task->event.e_un.breakpoint);
|
skip_breakpoint(task, task->event.e_un.breakpoint);
|
||||||
|
|
||||||
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint32_t));
|
server_send_msg(op, task->leader->pid, alloc, sizeof(*alloc) + i * sizeof(uint32_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_alloc(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth, struct library_symbol *libsym)
|
static void report_alloc(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "%d [%d]: %#lx %lu", op, task->pid, ptr, size);
|
debug(DEBUG_FUNCTION, "%d [%d]: %#lx %lu", op, task->pid, ptr, size);
|
||||||
|
|
||||||
if (task_is_64bit(task))
|
if (task_is_64bit(task))
|
||||||
return report_alloc64(task, op, ptr, size, depth, libsym);
|
report_alloc64(task, op, ptr, size, depth, libsym);
|
||||||
else
|
else
|
||||||
return report_alloc32(task, op, ptr, size, depth, libsym);
|
report_alloc32(task, op, ptr, size, depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _null(struct task *task, struct library_symbol *libsym)
|
static void _null(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_alloc_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
static void _report_alloc_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 0);
|
unsigned long size = fetch_param(task, 0);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, op, ret, size, options.bt_depth, libsym);
|
report_alloc(task, op, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_malloc(struct task *task, struct library_symbol *libsym)
|
static void _report_malloc(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_alloc_op(task, libsym, MT_MALLOC);
|
_report_alloc_op(task, libsym, MT_MALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_new(struct task *task, struct library_symbol *libsym)
|
static void _report_new(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_alloc_op(task, libsym, options.sanity ? MT_NEW : MT_MALLOC);
|
_report_alloc_op(task, libsym, options.sanity ? MT_NEW : MT_MALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_new_array(struct task *task, struct library_symbol *libsym)
|
static void _report_new_array(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_alloc_op(task, libsym, options.sanity ? MT_NEW_ARRAY : MT_MALLOC);
|
_report_alloc_op(task, libsym, options.sanity ? MT_NEW_ARRAY : MT_MALLOC);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_free_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
static void _report_free_op(struct task *task, struct library_symbol *libsym, enum mt_operation op)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long addr = fetch_param(task, 0);
|
unsigned long addr = fetch_param(task, 0);
|
||||||
|
|
||||||
return report_alloc(task, op, addr, 0, options.sanity ? options.bt_depth : 0, NULL);
|
report_alloc(task, op, addr, 0, options.sanity ? options.bt_depth : 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_free(struct task *task, struct library_symbol *libsym)
|
static void report_free(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_free_op(task, libsym, MT_FREE);
|
_report_free_op(task, libsym, MT_FREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_delete(struct task *task, struct library_symbol *libsym)
|
static void report_delete(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_free_op(task, libsym, options.sanity ? MT_DELETE : MT_FREE);
|
_report_free_op(task, libsym, options.sanity ? MT_DELETE : MT_FREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_delete_array(struct task *task, struct library_symbol *libsym)
|
static void report_delete_array(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
return _report_free_op(task, libsym, options.sanity ? MT_DELETE_ARRAY : MT_FREE);
|
_report_free_op(task, libsym, options.sanity ? MT_DELETE_ARRAY : MT_FREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_realloc(struct task *task, struct library_symbol *libsym)
|
static void _report_realloc(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long addr = fetch_param(task, 0);
|
|
||||||
unsigned long size = fetch_param(task, 1);
|
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
if (ret)
|
if (ret) {
|
||||||
return report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym);
|
|
||||||
else
|
|
||||||
return report_alloc(task, MT_REALLOC_FAILED, addr, 1, options.bt_depth, libsym);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int report_realloc(struct task *task, struct library_symbol *libsym)
|
|
||||||
{
|
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long addr = fetch_param(task, 0);
|
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
|
|
||||||
return report_alloc(task, MT_REALLOC_ENTER, addr, size, options.bt_depth, libsym);
|
report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_calloc(struct task *task, struct library_symbol *libsym)
|
if (task_is_64bit(task)) {
|
||||||
{
|
struct mt_alloc_payload_64 *alloc = alloca(sizeof(*alloc));
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
|
alloc->ptr = (uint64_t)ret;
|
||||||
|
alloc->size = (uint64_t)task->pid;
|
||||||
|
|
||||||
|
server_send_msg(MT_REALLOC_DONE, task->leader->pid, alloc, sizeof(*alloc));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
struct mt_alloc_payload_32 *alloc = alloca(sizeof(*alloc));
|
||||||
|
|
||||||
|
alloc->ptr = (uint32_t)ret;
|
||||||
|
alloc->size = (uint32_t)task->pid;
|
||||||
|
|
||||||
|
server_send_msg(MT_REALLOC_DONE, task->leader->pid, alloc, sizeof(*alloc));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void report_realloc(struct task *task, struct library_symbol *libsym)
|
||||||
|
{
|
||||||
|
unsigned long addr = fetch_param(task, 0);
|
||||||
|
|
||||||
|
report_alloc(task, MT_REALLOC_ENTER, addr, task->pid, options.sanity ? options.bt_depth : 0, libsym);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _report_calloc(struct task *task, struct library_symbol *libsym)
|
||||||
|
{
|
||||||
unsigned long size = fetch_param(task, 0) * fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 0) * fetch_param(task, 1);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_MALLOC, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_MALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mmap(struct task *task, struct library_symbol *libsym)
|
static void _report_mmap(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
if ((void *)ret == MAP_FAILED)
|
if ((void *)ret == MAP_FAILED)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
|
|
||||||
return report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mmap64(struct task *task, struct library_symbol *libsym)
|
static void _report_mmap64(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
if ((void *)ret == MAP_FAILED)
|
if ((void *)ret == MAP_FAILED)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
union {
|
union {
|
||||||
uint64_t l;
|
uint64_t l;
|
||||||
@ -264,40 +256,31 @@ static int _report_mmap64(struct task *task, struct library_symbol *libsym)
|
|||||||
else
|
else
|
||||||
size.l = fetch_param(task, 1);
|
size.l = fetch_param(task, 1);
|
||||||
|
|
||||||
return report_alloc(task, MT_MMAP64, ret, size.l, options.bt_depth, libsym);
|
report_alloc(task, MT_MMAP64, ret, size.l, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_munmap(struct task *task, struct library_symbol *libsym)
|
static void report_munmap(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long addr = fetch_param(task, 0);
|
unsigned long addr = fetch_param(task, 0);
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
|
|
||||||
return report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_memalign(struct task *task, struct library_symbol *libsym)
|
static void _report_memalign(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_MEMALIGN, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_MEMALIGN, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_posix_memalign(struct task *task, struct library_symbol *libsym)
|
static void _report_posix_memalign(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 2);
|
unsigned long size = fetch_param(task, 2);
|
||||||
unsigned long ptr = fetch_param(task, 0);
|
unsigned long ptr = fetch_param(task, 0);
|
||||||
@ -313,56 +296,47 @@ static int _report_posix_memalign(struct task *task, struct library_symbol *libs
|
|||||||
new_ptr = tmp;
|
new_ptr = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return report_alloc(task, MT_POSIX_MEMALIGN, new_ptr, size, options.bt_depth, libsym);
|
report_alloc(task, MT_POSIX_MEMALIGN, new_ptr, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_aligned_alloc(struct task *task, struct library_symbol *libsym)
|
static void _report_aligned_alloc(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_ALIGNED_ALLOC, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_ALIGNED_ALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_valloc(struct task *task, struct library_symbol *libsym)
|
static void _report_valloc(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 0);
|
unsigned long size = fetch_param(task, 0);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_VALLOC, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_VALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_pvalloc(struct task *task, struct library_symbol *libsym)
|
static void _report_pvalloc(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
if (!server_connected())
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
unsigned long size = fetch_param(task, 0);
|
unsigned long size = fetch_param(task, 0);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_PVALLOC, ret, size, options.bt_depth, libsym);
|
return report_alloc(task, MT_PVALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_mremap(struct task *task, struct library_symbol *libsym)
|
static void report_mremap(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
unsigned long addr = fetch_param(task, 0);
|
unsigned long addr = fetch_param(task, 0);
|
||||||
unsigned long size = fetch_param(task, 1);
|
unsigned long size = fetch_param(task, 1);
|
||||||
|
|
||||||
return report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mremap(struct task *task, struct library_symbol *libsym)
|
static void _report_mremap(struct task *task, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
unsigned long size = fetch_param(task, 2);
|
unsigned long size = fetch_param(task, 2);
|
||||||
unsigned long ret = fetch_retval(task);
|
unsigned long ret = fetch_retval(task);
|
||||||
|
|
||||||
return report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct function flist[] = {
|
static const struct function flist[] = {
|
||||||
@ -416,13 +390,14 @@ int _report_map(struct task *task, struct library *lib, enum mt_operation op)
|
|||||||
struct libref *libref = lib->libref;
|
struct libref *libref = lib->libref;
|
||||||
size_t len = strlen(libref->filename) + 1;
|
size_t len = strlen(libref->filename) + 1;
|
||||||
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
|
struct mt_map_payload *payload = alloca(sizeof(struct mt_map_payload) + len);
|
||||||
|
|
||||||
payload->addr = libref->load_addr;
|
payload->addr = libref->load_addr;
|
||||||
payload->offset = libref->load_offset;
|
payload->offset = libref->load_offset;
|
||||||
payload->size = libref->load_size;
|
payload->size = libref->load_size;
|
||||||
|
|
||||||
memcpy(payload->filename, libref->filename, len);
|
memcpy(payload->filename, libref->filename, len);
|
||||||
|
|
||||||
return server_send_msg(op, task->pid, 0, payload, sizeof(struct mt_map_payload) + len);
|
return server_send_msg(op, task->pid, payload, sizeof(struct mt_map_payload) + len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_add_map(struct task *task, struct library *lib)
|
int report_add_map(struct task *task, struct library *lib)
|
||||||
@ -441,6 +416,13 @@ int report_del_map(struct task *task, struct library *lib)
|
|||||||
return _report_map(task, lib, MT_DEL_MAP);
|
return _report_map(task, lib, MT_DEL_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void store_timer_info(struct memtrace_timer_info *info, struct mt_timer *timer)
|
||||||
|
{
|
||||||
|
info->max = timer->max;
|
||||||
|
info->count = timer->count;
|
||||||
|
info->culminate = timer->culminate;
|
||||||
|
}
|
||||||
|
|
||||||
int report_info(int do_trace)
|
int report_info(int do_trace)
|
||||||
{
|
{
|
||||||
struct memtrace_info mt_info;
|
struct memtrace_info mt_info;
|
||||||
@ -452,6 +434,16 @@ int report_info(int do_trace)
|
|||||||
mt_info.mode = 0;
|
mt_info.mode = 0;
|
||||||
mt_info.do_trace = do_trace ? 1 : 0;
|
mt_info.do_trace = do_trace ? 1 : 0;
|
||||||
mt_info.stack_depth = options.bt_depth;
|
mt_info.stack_depth = options.bt_depth;
|
||||||
|
mt_info.verbose = options.verbose;
|
||||||
|
|
||||||
|
store_timer_info(&mt_info.stop_time, &stop_time);
|
||||||
|
store_timer_info(&mt_info.sw_bp_time, &sw_bp_time);
|
||||||
|
store_timer_info(&mt_info.hw_bp_time, &hw_bp_time);
|
||||||
|
store_timer_info(&mt_info.backtrace_time, &backtrace_time);
|
||||||
|
store_timer_info(&mt_info.reorder_time, &reorder_time);
|
||||||
|
store_timer_info(&mt_info.report_in_time, &report_in_time);
|
||||||
|
store_timer_info(&mt_info.report_out_time, &report_out_time);
|
||||||
|
store_timer_info(&mt_info.skip_bp_time, &skip_bp_time);
|
||||||
|
|
||||||
if (options.verbose)
|
if (options.verbose)
|
||||||
mt_info.mode |= MEMTRACE_SI_VERBOSE;
|
mt_info.mode |= MEMTRACE_SI_VERBOSE;
|
||||||
@ -462,7 +454,7 @@ int report_info(int do_trace)
|
|||||||
if (options.follow)
|
if (options.follow)
|
||||||
mt_info.mode |= MEMTRACE_SI_FORK;
|
mt_info.mode |= MEMTRACE_SI_FORK;
|
||||||
|
|
||||||
return server_send_msg(MT_INFO, 0, 0, &mt_info, sizeof(mt_info));
|
return server_send_msg(MT_INFO, 0, &mt_info, sizeof(mt_info));
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_scan(pid_t pid, const void *data, unsigned int data_len)
|
int report_scan(pid_t pid, const void *data, unsigned int data_len)
|
||||||
@ -470,7 +462,7 @@ int report_scan(pid_t pid, const void *data, unsigned int data_len)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_SCAN, pid, 0, data, data_len);
|
return server_send_msg(MT_SCAN, pid, data, data_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_attach(struct task *task)
|
int report_attach(struct task *task)
|
||||||
@ -480,7 +472,7 @@ int report_attach(struct task *task)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(task_is_64bit(task) ? MT_ATTACH64 : MT_ATTACH, task->pid, 0, &state, sizeof(state));
|
return server_send_msg(task_is_64bit(task) ? MT_ATTACH64 : MT_ATTACH, task->pid, &state, sizeof(state));
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_fork(struct task *task, struct task *ptask)
|
int report_fork(struct task *task, struct task *ptask)
|
||||||
@ -490,7 +482,7 @@ int report_fork(struct task *task, struct task *ptask)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_FORK, task->pid, 0, &fork_pid, sizeof(fork_pid));
|
return server_send_msg(MT_FORK, task->pid, &fork_pid, sizeof(fork_pid));
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_exit(struct task *task)
|
int report_exit(struct task *task)
|
||||||
@ -498,7 +490,7 @@ int report_exit(struct task *task)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_EXIT, task->pid, 0, NULL, 0);
|
return server_send_msg(MT_EXIT, task->pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_about_exit(struct task *task)
|
int report_about_exit(struct task *task)
|
||||||
@ -506,7 +498,7 @@ int report_about_exit(struct task *task)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_ABOUT_EXIT, task->pid, 0, NULL, 0);
|
return server_send_msg(MT_ABOUT_EXIT, task->pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_nofollow(struct task *task)
|
int report_nofollow(struct task *task)
|
||||||
@ -514,7 +506,7 @@ int report_nofollow(struct task *task)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_NOFOLLOW, task->pid, 0, NULL, 0);
|
return server_send_msg(MT_NOFOLLOW, task->pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_detach(struct task *task)
|
int report_detach(struct task *task)
|
||||||
@ -522,7 +514,7 @@ int report_detach(struct task *task)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_DETACH, task->pid, 0, NULL, 0);
|
return server_send_msg(MT_DETACH, task->pid, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int report_disconnect(void)
|
int report_disconnect(void)
|
||||||
@ -530,7 +522,7 @@ int report_disconnect(void)
|
|||||||
if (!server_connected())
|
if (!server_connected())
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return server_send_msg(MT_DISCONNECT, 0, 0, NULL, 0);
|
return server_send_msg(MT_DISCONNECT, 0, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void report_process(struct task *leader)
|
static void report_process(struct task *leader)
|
||||||
|
|||||||
4
report.h
4
report.h
@ -33,9 +33,9 @@ struct function {
|
|||||||
/* level for aliased symbol */
|
/* level for aliased symbol */
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
/* report when function is entered */
|
/* report when function is entered */
|
||||||
int (*report_in)(struct task *task, struct library_symbol *libsym);
|
void (*report_in)(struct task *task, struct library_symbol *libsym);
|
||||||
/* report when function is exited */
|
/* report when function is exited */
|
||||||
int (*report_out)(struct task *task, struct library_symbol *libsym);
|
void (*report_out)(struct task *task, struct library_symbol *libsym);
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct function *flist_matches_symbol(const char *sym_name);
|
const struct function *flist_matches_symbol(const char *sym_name);
|
||||||
|
|||||||
12
server.c
12
server.c
@ -159,7 +159,7 @@ int server_handle_command(void)
|
|||||||
|
|
||||||
if (ret != sizeof(cmd)) {
|
if (ret != sizeof(cmd)) {
|
||||||
if (ret > 0) {
|
if (ret > 0) {
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
fprintf(stderr, "cmd read wrong size %d\n", ret);
|
fprintf(stderr, "cmd read wrong size %d\n", ret);
|
||||||
}
|
}
|
||||||
server_close();
|
server_close();
|
||||||
@ -177,6 +177,9 @@ int server_handle_command(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!cmd.pid) {
|
if (!cmd.pid) {
|
||||||
|
if (cmd.operation == MT_INFO)
|
||||||
|
report_info(1);
|
||||||
|
else
|
||||||
server_close();
|
server_close();
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
@ -277,7 +280,7 @@ int server_start(void)
|
|||||||
fatal("accept (%s)", strerror(errno));
|
fatal("accept (%s)", strerror(errno));
|
||||||
|
|
||||||
fprintf(stderr, "connected!\n");
|
fprintf(stderr, "connected!\n");
|
||||||
server_mode = MODE_ACCEPTED;
|
|
||||||
report_info(1);
|
report_info(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -341,7 +344,7 @@ int server_start_pair(void)
|
|||||||
return sv[1];
|
return sv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len)
|
int server_send_msg(enum mt_operation op, uint32_t pid, const void *payload, unsigned int payload_len)
|
||||||
{
|
{
|
||||||
if (options.logfile) {
|
if (options.logfile) {
|
||||||
struct iovec io[2];
|
struct iovec io[2];
|
||||||
@ -350,7 +353,6 @@ int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void
|
|||||||
|
|
||||||
mt_msg.operation = op;
|
mt_msg.operation = op;
|
||||||
mt_msg.pid = pid;
|
mt_msg.pid = pid;
|
||||||
mt_msg.tid = tid;
|
|
||||||
mt_msg.payload_len = payload_len;
|
mt_msg.payload_len = payload_len;
|
||||||
|
|
||||||
io[0].iov_base = &mt_msg;
|
io[0].iov_base = &mt_msg;
|
||||||
@ -367,7 +369,7 @@ int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return sock_send_msg(server_fd, op, pid, tid, payload, payload_len);
|
return sock_send_msg(server_fd, op, pid, payload, payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_stop(void)
|
int server_stop(void)
|
||||||
|
|||||||
2
server.h
2
server.h
@ -29,7 +29,7 @@
|
|||||||
|
|
||||||
int server_start(void);
|
int server_start(void);
|
||||||
int server_start_pair(void);
|
int server_start_pair(void);
|
||||||
int server_send_msg(enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len);
|
int server_send_msg(enum mt_operation op, uint32_t pid, const void *payload, unsigned int payload_len);
|
||||||
int server_handle_command(void);
|
int server_handle_command(void);
|
||||||
int server_connected(void);
|
int server_connected(void);
|
||||||
int server_stop(void);
|
int server_stop(void);
|
||||||
|
|||||||
@ -25,7 +25,6 @@ noinst_LTLIBRARIES = \
|
|||||||
../libos.la
|
../libos.la
|
||||||
|
|
||||||
___libos_la_SOURCES = \
|
___libos_la_SOURCES = \
|
||||||
backtrace.c \
|
|
||||||
ioevent.c \
|
ioevent.c \
|
||||||
trace.c \
|
trace.c \
|
||||||
os.c \
|
os.c \
|
||||||
|
|||||||
@ -125,8 +125,8 @@ CONFIG_CLEAN_FILES =
|
|||||||
CONFIG_CLEAN_VPATH_FILES =
|
CONFIG_CLEAN_VPATH_FILES =
|
||||||
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
LTLIBRARIES = $(noinst_LTLIBRARIES)
|
||||||
___libos_la_DEPENDENCIES = libcpu.la
|
___libos_la_DEPENDENCIES = libcpu.la
|
||||||
am____libos_la_OBJECTS = backtrace.lo ioevent.lo trace.lo os.lo \
|
am____libos_la_OBJECTS = ioevent.lo trace.lo os.lo proc.lo socket.lo \
|
||||||
proc.lo socket.lo thread.lo
|
thread.lo
|
||||||
___libos_la_OBJECTS = $(am____libos_la_OBJECTS)
|
___libos_la_OBJECTS = $(am____libos_la_OBJECTS)
|
||||||
AM_V_lt = $(am__v_lt_@AM_V@)
|
AM_V_lt = $(am__v_lt_@AM_V@)
|
||||||
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
|
||||||
@ -368,7 +368,6 @@ noinst_LTLIBRARIES = \
|
|||||||
../libos.la
|
../libos.la
|
||||||
|
|
||||||
___libos_la_SOURCES = \
|
___libos_la_SOURCES = \
|
||||||
backtrace.c \
|
|
||||||
ioevent.c \
|
ioevent.c \
|
||||||
trace.c \
|
trace.c \
|
||||||
os.c \
|
os.c \
|
||||||
@ -441,7 +440,6 @@ mostlyclean-compile:
|
|||||||
distclean-compile:
|
distclean-compile:
|
||||||
-rm -f *.tab.c
|
-rm -f *.tab.c
|
||||||
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/backtrace.Plo@am__quote@
|
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioevent.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ioevent.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os.Plo@am__quote@
|
||||||
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of mtrace-ng.
|
|
||||||
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
|
|
||||||
*
|
|
||||||
* This work was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich/Germany.
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License as
|
|
||||||
* published by the Free Software Foundation; either version 2 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program 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
|
|
||||||
* General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
||||||
* 02110-1301 USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "backtrace.h"
|
|
||||||
#include "dwarf.h"
|
|
||||||
#include "task.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
int backtrace_init(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader == task);
|
|
||||||
assert(task->backtrace == NULL);
|
|
||||||
|
|
||||||
task->backtrace = dwarf_init(task->is_64bit);
|
|
||||||
|
|
||||||
return task->backtrace != NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void backtrace_destroy(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader == task);
|
|
||||||
|
|
||||||
if (task->backtrace) {
|
|
||||||
dwarf_destroy(task->backtrace);
|
|
||||||
|
|
||||||
task->backtrace = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int backtrace_init_unwind(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader);
|
|
||||||
assert(task->leader->backtrace);
|
|
||||||
|
|
||||||
return dwarf_init_unwind(task->leader->backtrace, task);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long backtrace_get_ip(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader);
|
|
||||||
assert(task->leader->backtrace);
|
|
||||||
|
|
||||||
return dwarf_get_ip(task->leader->backtrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
int backtrace_step(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader);
|
|
||||||
assert(task->leader->backtrace);
|
|
||||||
|
|
||||||
return dwarf_step(task->leader->backtrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
int backtrace_location_type(struct task *task)
|
|
||||||
{
|
|
||||||
assert(task->leader);
|
|
||||||
assert(task->leader->backtrace);
|
|
||||||
|
|
||||||
return dwarf_location_type(task->leader->backtrace);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ struct io_watch_event *io_watch_event;
|
|||||||
static unsigned int io_watch_size;
|
static unsigned int io_watch_size;
|
||||||
static unsigned int io_watch_elems;
|
static unsigned int io_watch_elems;
|
||||||
|
|
||||||
static inline void io_watch_set(unsigned int idx, int fd, int (*func)(void))
|
static inline void io_watch_set(unsigned int idx, int fd, ioevent_func func)
|
||||||
{
|
{
|
||||||
io_watch_event[idx].func = func;
|
io_watch_event[idx].func = func;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ static inline void io_watch_set(unsigned int idx, int fd, int (*func)(void))
|
|||||||
io_watch_poll[idx].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
io_watch_poll[idx].events = POLLIN | POLLPRI | POLLERR | POLLHUP | POLLNVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ioevent_add_input(int fd, int (*func)(void))
|
int ioevent_add_input(int fd, ioevent_func func)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
@ -113,6 +113,21 @@ int ioevent_watch(int timeout)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ioevent_func ioevent_set_input_func(int fd, ioevent_func func)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for(i = 0; i < io_watch_elems; ++i) {
|
||||||
|
if (io_watch_poll[i].fd == fd) {
|
||||||
|
int (*old)(void) = io_watch_event[i].func;
|
||||||
|
|
||||||
|
io_watch_event[i].func = func;
|
||||||
|
|
||||||
|
return old;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
int ioevent_wait_input(int fd, int timeout)
|
int ioevent_wait_input(int fd, int timeout)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -23,10 +23,13 @@
|
|||||||
#ifndef _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
|
#ifndef _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
|
||||||
#define _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
|
#define _INC_SYSDEPS_LINUX_GNU_IOEVENT_H
|
||||||
|
|
||||||
int ioevent_add_input(int fd, int (*func)(void));
|
typedef int (*ioevent_func)(void);
|
||||||
|
|
||||||
|
int ioevent_add_input(int fd, ioevent_func func);
|
||||||
int ioevent_del_input(int fd);
|
int ioevent_del_input(int fd);
|
||||||
int ioevent_watch(int timeout);
|
int ioevent_watch(int timeout);
|
||||||
int ioevent_wait_input(int fd, int timeout);
|
int ioevent_wait_input(int fd, int timeout);
|
||||||
|
ioevent_func ioevent_set_input_func(int fd, ioevent_func func);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
#include "breakpoint.h"
|
#include "breakpoint.h"
|
||||||
@ -178,8 +179,8 @@ static struct map *get_writeable_mappings(struct task *task)
|
|||||||
char filename[PATH_MAX + 2];
|
char filename[PATH_MAX + 2];
|
||||||
char nl;
|
char nl;
|
||||||
FILE *in;
|
FILE *in;
|
||||||
unsigned int maps_size = 0;
|
unsigned int maps_size;
|
||||||
struct map *maps = NULL;
|
struct map *maps;
|
||||||
unsigned int map = 0;
|
unsigned int map = 0;
|
||||||
|
|
||||||
snprintf(filename, sizeof(filename)-1, "/proc/%d/maps", task->pid);
|
snprintf(filename, sizeof(filename)-1, "/proc/%d/maps", task->pid);
|
||||||
@ -393,6 +394,8 @@ int os_init(void)
|
|||||||
const int siglist[] = { SIGSEGV, SIGABRT, SIGTRAP, SIGILL, SIGFPE };
|
const int siglist[] = { SIGSEGV, SIGABRT, SIGTRAP, SIGILL, SIGFPE };
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
prctl(PR_SET_TIMERSLACK, 1, 0, 0, 0);
|
||||||
|
|
||||||
for(i = 0; i < ARRAY_SIZE(siglist); i++) {
|
for(i = 0; i < ARRAY_SIZE(siglist); i++) {
|
||||||
act.sa_flags = SA_ONESHOT | SA_SIGINFO;
|
act.sa_flags = SA_ONESHOT | SA_SIGINFO;
|
||||||
act.sa_sigaction = report_fault;
|
act.sa_sigaction = report_fault;
|
||||||
|
|||||||
@ -490,15 +490,16 @@ static int load_debug_struct(struct task *task, arch_addr_t debug_addr, struct l
|
|||||||
static int rdebug_bp_on_hit(struct task *task, struct breakpoint *bp)
|
static int rdebug_bp_on_hit(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
struct lt_r_debug_64 rdbg;
|
struct lt_r_debug_64 rdbg;
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "pid=%d", task->pid);
|
debug(DEBUG_FUNCTION, "pid=%d", task->pid);
|
||||||
|
|
||||||
if (load_debug_struct(task, task->os.debug_addr, &rdbg) < 0)
|
if (load_debug_struct(task, leader->os.debug_addr, &rdbg) < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (rdbg.r_state == RT_CONSISTENT) {
|
if (rdbg.r_state == RT_CONSISTENT) {
|
||||||
debug(DEBUG_FUNCTION, "Linkmap is now consistent");
|
debug(DEBUG_FUNCTION, "Linkmap is now consistent");
|
||||||
switch (task->os.debug_state) {
|
switch (leader->os.debug_state) {
|
||||||
case RT_ADD:
|
case RT_ADD:
|
||||||
linkmap_add(task, &rdbg);
|
linkmap_add(task, &rdbg);
|
||||||
break;
|
break;
|
||||||
@ -510,7 +511,7 @@ static int rdebug_bp_on_hit(struct task *task, struct breakpoint *bp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task->os.debug_state = rdbg.r_state;
|
leader->os.debug_state = rdbg.r_state;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,10 +520,11 @@ int linkmap_init(struct task *task, arch_addr_t dyn_addr)
|
|||||||
struct lt_r_debug_64 rdbg;
|
struct lt_r_debug_64 rdbg;
|
||||||
struct breakpoint *bp;
|
struct breakpoint *bp;
|
||||||
arch_addr_t debug_addr;
|
arch_addr_t debug_addr;
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "pid=%d, dyn_addr=%#lx", task->pid, dyn_addr);
|
debug(DEBUG_FUNCTION, "pid=%d, dyn_addr=%#lx", task->pid, dyn_addr);
|
||||||
|
|
||||||
if (task->os.debug_addr)
|
if (leader->os.debug_addr)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (process_find_dynamic_entry_addr(task, dyn_addr, DT_DEBUG, &debug_addr) == -1) {
|
if (process_find_dynamic_entry_addr(task, dyn_addr, DT_DEBUG, &debug_addr) == -1) {
|
||||||
@ -538,7 +540,7 @@ int linkmap_init(struct task *task, arch_addr_t dyn_addr)
|
|||||||
|
|
||||||
arch_addr_t addr = ARCH_ADDR_T(rdbg.r_brk);
|
arch_addr_t addr = ARCH_ADDR_T(rdbg.r_brk);
|
||||||
|
|
||||||
bp = breakpoint_new(task, addr, NULL, 0);
|
bp = breakpoint_new(task, addr, NULL, BP_SW);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -547,7 +549,7 @@ int linkmap_init(struct task *task, arch_addr_t dyn_addr)
|
|||||||
|
|
||||||
breakpoint_enable(task, bp);
|
breakpoint_enable(task, bp);
|
||||||
|
|
||||||
task->os.debug_addr = debug_addr;
|
leader->os.debug_addr = debug_addr;
|
||||||
|
|
||||||
if (rdbg.r_state == RT_CONSISTENT)
|
if (rdbg.r_state == RT_CONSISTENT)
|
||||||
linkmap_add(task, &rdbg);
|
linkmap_add(task, &rdbg);
|
||||||
@ -607,8 +609,10 @@ done:
|
|||||||
|
|
||||||
int os_task_init(struct task *task)
|
int os_task_init(struct task *task)
|
||||||
{
|
{
|
||||||
task->os.debug_addr = 0;
|
struct task *leader = task->leader;
|
||||||
task->os.debug_state = RT_ADD;
|
|
||||||
|
leader->os.debug_addr = 0;
|
||||||
|
leader->os.debug_state = RT_ADD;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -618,7 +622,9 @@ void os_task_destroy(struct task *task)
|
|||||||
|
|
||||||
int os_task_clone(struct task *retp, struct task *task)
|
int os_task_clone(struct task *retp, struct task *task)
|
||||||
{
|
{
|
||||||
retp->os = task->os;
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
|
retp->os = leader->os;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -32,6 +32,8 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
@ -64,7 +66,7 @@ ssize_t safe_read(int fd, void *dest, size_t n)
|
|||||||
return off + n;
|
return off + n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len)
|
int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, const void *payload, unsigned int payload_len)
|
||||||
{
|
{
|
||||||
struct mt_msg mt_msg;
|
struct mt_msg mt_msg;
|
||||||
struct iovec io[2];
|
struct iovec io[2];
|
||||||
@ -96,12 +98,10 @@ int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, uint32_t tid, cons
|
|||||||
|
|
||||||
if (op > 0xff) {
|
if (op > 0xff) {
|
||||||
mt_msg.pid = bswap_32(pid);
|
mt_msg.pid = bswap_32(pid);
|
||||||
mt_msg.tid = bswap_32(tid);
|
|
||||||
mt_msg.payload_len = bswap_32(payload_len);
|
mt_msg.payload_len = bswap_32(payload_len);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mt_msg.pid = pid;
|
mt_msg.pid = pid;
|
||||||
mt_msg.tid = tid;
|
|
||||||
mt_msg.payload_len = payload_len;
|
mt_msg.payload_len = payload_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,6 +215,8 @@ int bind_to(const char *node, const char *service)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
struct addrinfo *rp;
|
struct addrinfo *rp;
|
||||||
|
int size = 10 * 1024 * 1024;
|
||||||
|
static const int one = 1;
|
||||||
|
|
||||||
for (rp = sock_addr(node, service, AI_PASSIVE); rp != NULL; rp = rp->ai_next) {
|
for (rp = sock_addr(node, service, AI_PASSIVE); rp != NULL; rp = rp->ai_next) {
|
||||||
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
|
||||||
@ -232,6 +234,12 @@ int bind_to(const char *node, const char *service)
|
|||||||
|
|
||||||
if (!rp)
|
if (!rp)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (setsockopt(sfd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)) == -1)
|
||||||
|
fatal("TCP_NODELAY: %s\n", strerror(errno));
|
||||||
|
|
||||||
|
if (setsockopt(sfd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) == -1)
|
||||||
|
fatal("SO_SNDBUF: %s\n", strerror(errno));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sfd;
|
return sfd;
|
||||||
|
|||||||
@ -35,7 +35,7 @@
|
|||||||
ssize_t safe_read(int fd, void *dest, size_t n);
|
ssize_t safe_read(int fd, void *dest, size_t n);
|
||||||
int connect_to(const char *node, const char *service);
|
int connect_to(const char *node, const char *service);
|
||||||
int bind_to(const char *node, const char *service);
|
int bind_to(const char *node, const char *service);
|
||||||
int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, uint32_t tid, const void *payload, unsigned int payload_len);
|
int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, const void *payload, unsigned int payload_len);
|
||||||
int create_socket_pair(int sv[2]);
|
int create_socket_pair(int sv[2]);
|
||||||
int is_named(const char *node);
|
int is_named(const char *node);
|
||||||
|
|
||||||
|
|||||||
@ -48,8 +48,10 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "main.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static volatile pid_t wakeup_pid = -1;
|
static volatile pid_t wakeup_pid = -1;
|
||||||
@ -92,7 +94,7 @@ static int _trace_wait(struct task *task, int signum)
|
|||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY(waitpid(task->pid, &status, __WALL)) != task->pid) {
|
if (unlikely(TEMP_FAILURE_RETRY(waitpid(task->pid, &status, __WALL)) != task->pid)) {
|
||||||
fprintf(stderr, "%s pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
fprintf(stderr, "%s pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -117,7 +119,7 @@ static int child_event(struct task *task, enum event_type ev)
|
|||||||
{
|
{
|
||||||
unsigned long data;
|
unsigned long data;
|
||||||
|
|
||||||
if (ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1) {
|
if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1)) {
|
||||||
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -127,7 +129,7 @@ static int child_event(struct task *task, enum event_type ev)
|
|||||||
if (!pid2task(pid)) {
|
if (!pid2task(pid)) {
|
||||||
struct task *child = task_new(pid);
|
struct task *child = task_new(pid);
|
||||||
|
|
||||||
if (!child)
|
if (unlikely(!child))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (_trace_wait(child, SIGSTOP)) {
|
if (_trace_wait(child, SIGSTOP)) {
|
||||||
@ -190,7 +192,7 @@ static int _process_event(struct task *task, int status)
|
|||||||
{
|
{
|
||||||
unsigned long data;
|
unsigned long data;
|
||||||
|
|
||||||
if (ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1) {
|
if (unlikely(ptrace(PTRACE_GETEVENTMSG, task->pid, NULL, &data) == -1)) {
|
||||||
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
debug(DEBUG_EVENT, "PTRACE_GETEVENTMSG pid=%d %s", task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -221,6 +223,9 @@ static void process_event(struct task *task, int status)
|
|||||||
|
|
||||||
assert(leader != NULL);
|
assert(leader != NULL);
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&task->halt_time);
|
||||||
|
|
||||||
task->stopped = 1;
|
task->stopped = 1;
|
||||||
|
|
||||||
leader->threads_stopped++;
|
leader->threads_stopped++;
|
||||||
@ -236,10 +241,10 @@ static void process_event(struct task *task, int status)
|
|||||||
if (stop_signal == 0)
|
if (stop_signal == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (stop_signal != SIGTRAP)
|
if (unlikely(stop_signal != SIGTRAP))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fetch_context(task) == -1) {
|
if (unlikely(fetch_context(task) == -1)) {
|
||||||
task->event.type = EVENT_NONE;
|
task->event.type = EVENT_NONE;
|
||||||
continue_task(task, 0);
|
continue_task(task, 0);
|
||||||
return;
|
return;
|
||||||
@ -252,7 +257,7 @@ static void process_event(struct task *task, int status)
|
|||||||
|
|
||||||
for(i = 0; i < HW_BREAKPOINTS; ++i) {
|
for(i = 0; i < HW_BREAKPOINTS; ++i) {
|
||||||
if (task->hw_bp[i] && task->hw_bp[i]->addr == ip) {
|
if (task->hw_bp[i] && task->hw_bp[i]->addr == ip) {
|
||||||
if (get_hw_bp_state(task, i))
|
if (likely(get_hw_bp_state(task, i)))
|
||||||
bp = task->hw_bp[i];
|
bp = task->hw_bp[i];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -262,15 +267,12 @@ static void process_event(struct task *task, int status)
|
|||||||
if (bp) {
|
if (bp) {
|
||||||
assert(bp->type != BP_SW);
|
assert(bp->type != BP_SW);
|
||||||
assert(bp->hw_bp_slot == i);
|
assert(bp->hw_bp_slot == i);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
|
||||||
++leader->num_hw_bp;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
bp = breakpoint_find(leader, ip - DECR_PC_AFTER_BREAK);
|
bp = breakpoint_find(leader, ip - DECR_PC_AFTER_BREAK);
|
||||||
if (!bp) {
|
if (unlikely(!bp)) {
|
||||||
task->event.type = EVENT_NONE;
|
task->event.type = EVENT_NONE;
|
||||||
continue_task(task, 0);
|
continue_task(task, 0);
|
||||||
return;
|
return;
|
||||||
@ -280,9 +282,6 @@ static void process_event(struct task *task, int status)
|
|||||||
assert(bp->hw == 0);
|
assert(bp->hw == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (options.verbose > 1)
|
|
||||||
++leader->num_sw_bp;
|
|
||||||
|
|
||||||
set_instruction_pointer(task, bp->addr);
|
set_instruction_pointer(task, bp->addr);
|
||||||
}
|
}
|
||||||
#if 1
|
#if 1
|
||||||
@ -321,7 +320,7 @@ void trace_me(void)
|
|||||||
|
|
||||||
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
prctl(PR_SET_PDEATHSIG, SIGKILL);
|
||||||
|
|
||||||
if (ptrace(PTRACE_TRACEME, 0, 0, 0) == -1) {
|
if (unlikely(ptrace(PTRACE_TRACEME, 0, 0, 0) == -1)) {
|
||||||
fprintf(stderr, "PTRACE_TRACEME pid=%d %s\n", getpid(), strerror(errno));
|
fprintf(stderr, "PTRACE_TRACEME pid=%d %s\n", getpid(), strerror(errno));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -347,7 +346,7 @@ int untrace_task(struct task *task, int signum)
|
|||||||
if (!task->stopped)
|
if (!task->stopped)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (ptrace(PTRACE_SETOPTIONS, task->pid, 0, (void *)0) == -1) {
|
if (unlikely(ptrace(PTRACE_SETOPTIONS, task->pid, 0, (void *)0) == -1)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_SETOPTIONS pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_SETOPTIONS pid=%d %s\n", task->pid, strerror(errno));
|
||||||
ret = -1;
|
ret = -1;
|
||||||
@ -356,7 +355,7 @@ int untrace_task(struct task *task, int signum)
|
|||||||
|
|
||||||
signum = fix_signal(task, signum);
|
signum = fix_signal(task, signum);
|
||||||
|
|
||||||
if (ptrace(PTRACE_DETACH, task->pid, 0, signum) == -1) {
|
if (unlikely(ptrace(PTRACE_DETACH, task->pid, 0, signum) == -1)) {
|
||||||
if (task->traced) {
|
if (task->traced) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_DETACH pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_DETACH pid=%d %s\n", task->pid, strerror(errno));
|
||||||
@ -381,7 +380,7 @@ int trace_attach(struct task *task)
|
|||||||
|
|
||||||
assert(task->traced == 0);
|
assert(task->traced == 0);
|
||||||
|
|
||||||
if (ptrace(PTRACE_ATTACH, task->pid, 0, 0) == -1) {
|
if (unlikely(ptrace(PTRACE_ATTACH, task->pid, 0, 0) == -1)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_ATTACH pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_ATTACH pid=%d %s\n", task->pid, strerror(errno));
|
||||||
trace_fail_warning();
|
trace_fail_warning();
|
||||||
@ -402,7 +401,7 @@ int trace_set_options(struct task *task)
|
|||||||
|
|
||||||
debug(DEBUG_PROCESS, "pid=%d", task->pid);
|
debug(DEBUG_PROCESS, "pid=%d", task->pid);
|
||||||
|
|
||||||
if (ptrace(PTRACE_SETOPTIONS, task->pid, 0, (void *)options) == -1) {
|
if (unlikely(ptrace(PTRACE_SETOPTIONS, task->pid, 0, (void *)options) == -1)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_SETOPTIONS pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_SETOPTIONS pid=%d %s\n", task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -420,7 +419,7 @@ int continue_task(struct task *task, int signum)
|
|||||||
task->leader->threads_stopped--;
|
task->leader->threads_stopped--;
|
||||||
task->stopped = 0;
|
task->stopped = 0;
|
||||||
|
|
||||||
if (ptrace(PTRACE_CONT, task->pid, 0, fix_signal(task, signum)) == -1) {
|
if (unlikely(ptrace(PTRACE_CONT, task->pid, 0, fix_signal(task, signum)) == -1)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_CONT pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_CONT pid=%d %s\n", task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -445,10 +444,18 @@ void stop_threads(struct task *task)
|
|||||||
assert(task->leader != NULL);
|
assert(task->leader != NULL);
|
||||||
|
|
||||||
if (leader->threads != leader->threads_stopped) {
|
if (leader->threads != leader->threads_stopped) {
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
each_task(leader, &do_stop_cb, NULL);
|
each_task(leader, &do_stop_cb, NULL);
|
||||||
|
|
||||||
while (leader->threads != leader->threads_stopped)
|
while (leader->threads != leader->threads_stopped)
|
||||||
queue_event(wait_event());
|
queue_event(wait_event());
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &stop_time);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,10 +465,10 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task))
|
|||||||
int stop_signal;
|
int stop_signal;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (singlestep(task) == -1)
|
if (unlikely(singlestep(task) == -1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (TEMP_FAILURE_RETRY(waitpid(task->pid, &status, __WALL)) != task->pid) {
|
if (unlikely(TEMP_FAILURE_RETRY(waitpid(task->pid, &status, __WALL)) != task->pid)) {
|
||||||
fprintf(stderr, "%s waitpid pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
fprintf(stderr, "%s waitpid pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -471,10 +478,10 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task))
|
|||||||
if (stop_signal == -1)
|
if (stop_signal == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (stop_signal == SIGTRAP)
|
if (likely(stop_signal == SIGTRAP))
|
||||||
return 0; /* check if was a real breakpoint code there */
|
return 0; /* check if was a real breakpoint code there */
|
||||||
|
|
||||||
if (!stop_signal) {
|
if (likely(!stop_signal)) {
|
||||||
queue_event(task);
|
queue_event(task);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -489,7 +496,7 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task))
|
|||||||
#ifndef ARCH_SINGLESTEP
|
#ifndef ARCH_SINGLESTEP
|
||||||
static int ptrace_singlestep(struct task *task)
|
static int ptrace_singlestep(struct task *task)
|
||||||
{
|
{
|
||||||
if (ptrace(PTRACE_SINGLESTEP, task->pid, 0, 0) == -1) {
|
if (unlikely(ptrace(PTRACE_SINGLESTEP, task->pid, 0, 0) == -1)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "%s PTRACE_SINGLESTEP pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
fprintf(stderr, "%s PTRACE_SINGLESTEP pid=%d %s\n", __FUNCTION__, task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -510,7 +517,7 @@ struct task *wait_event(void)
|
|||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
pid = waitpid(-1, &status, __WALL);
|
pid = waitpid(-1, &status, __WALL);
|
||||||
if (pid == -1) {
|
if (unlikely(pid == -1)) {
|
||||||
if (errno != EINTR) {
|
if (errno != EINTR) {
|
||||||
if (errno == ECHILD)
|
if (errno == ECHILD)
|
||||||
debug(DEBUG_EVENT, "No more traced programs");
|
debug(DEBUG_EVENT, "No more traced programs");
|
||||||
@ -521,7 +528,7 @@ struct task *wait_event(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pthread_mutex_lock(&mutex);
|
pthread_mutex_lock(&mutex);
|
||||||
if (pid == wakeup_pid) {
|
if (unlikely(pid == wakeup_pid)) {
|
||||||
pid = 0;
|
pid = 0;
|
||||||
wakeup_pid = -1;
|
wakeup_pid = -1;
|
||||||
}
|
}
|
||||||
@ -531,10 +538,10 @@ struct task *wait_event(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
task = pid2task(pid);
|
task = pid2task(pid);
|
||||||
if (!task) {
|
if (unlikely(!task)) {
|
||||||
task = task_new(pid);
|
task = task_new(pid);
|
||||||
|
|
||||||
if (task)
|
if (likely(task))
|
||||||
trace_setup(task, status, SIGSTOP);
|
trace_setup(task, status, SIGSTOP);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -591,7 +598,7 @@ ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t le
|
|||||||
remote[0].iov_len = len;
|
remote[0].iov_len = len;
|
||||||
|
|
||||||
num_bytes = process_vm_readv(task->pid, local, 1, remote, 1, 0);
|
num_bytes = process_vm_readv(task->pid, local, 1, remote, 1, 0);
|
||||||
if (num_bytes != -1)
|
if (unlikely(num_bytes != -1))
|
||||||
return num_bytes;
|
return num_bytes;
|
||||||
|
|
||||||
if (errno != EFAULT) {
|
if (errno != EFAULT) {
|
||||||
@ -610,7 +617,7 @@ ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t le
|
|||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
||||||
if (a.a == -1 && errno) {
|
if (unlikely(a.a == -1 && errno)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
@ -650,7 +657,7 @@ ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_
|
|||||||
n = len;
|
n = len;
|
||||||
|
|
||||||
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
||||||
if (a.a == -1 && errno) {
|
if (unlikely(a.a == -1 && errno)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
@ -660,7 +667,7 @@ ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_
|
|||||||
memcpy(a.c, src, n);
|
memcpy(a.c, src, n);
|
||||||
|
|
||||||
a.a = ptrace(PTRACE_POKETEXT, task->pid, addr, a.a);
|
a.a = ptrace(PTRACE_POKETEXT, task->pid, addr, a.a);
|
||||||
if (a.a == -1) {
|
if (unlikely(a.a == -1)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
@ -690,7 +697,7 @@ ssize_t copy_from_to_proc(struct task *task, arch_addr_t addr, const void *src,
|
|||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
||||||
if (a.a == -1 && errno) {
|
if (unlikely(a.a == -1 && errno)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
@ -703,7 +710,7 @@ ssize_t copy_from_to_proc(struct task *task, arch_addr_t addr, const void *src,
|
|||||||
memcpy(a.c, src, n);
|
memcpy(a.c, src, n);
|
||||||
|
|
||||||
a.a = ptrace(PTRACE_POKETEXT, task->pid, addr, a.a);
|
a.a = ptrace(PTRACE_POKETEXT, task->pid, addr, a.a);
|
||||||
if (a.a == -1) {
|
if (unlikely(a.a == -1)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
@ -738,7 +745,7 @@ ssize_t copy_str_from_proc(struct task *task, arch_addr_t addr, char *dst, size_
|
|||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
a.a = ptrace(PTRACE_PEEKTEXT, task->pid, addr, 0);
|
||||||
if (a.a == -1 && errno) {
|
if (unlikely(a.a == -1 && errno)) {
|
||||||
if (num_bytes && errno == EIO)
|
if (num_bytes && errno == EIO)
|
||||||
break;
|
break;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -43,7 +43,7 @@ int get_hw_bp_state(struct task *task, unsigned int n)
|
|||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
ret = ptrace(PTRACE_PEEKUSER, task->pid, offsetof(struct user, u_debugreg[6]), 0);
|
ret = ptrace(PTRACE_PEEKUSER, task->pid, offsetof(struct user, u_debugreg[6]), 0);
|
||||||
if (ret == -1 && errno) {
|
if (unlikely(ret == -1 && errno)) {
|
||||||
if (errno != ESRCH)
|
if (errno != ESRCH)
|
||||||
fprintf(stderr, "PTRACE_PEEKUSER u_debugreg[6] pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_PEEKUSER u_debugreg[6] pid=%d %s\n", task->pid, strerror(errno));
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ static int _apply_hw_bp(struct task *task, uint32_t dr7)
|
|||||||
task->arch.dr7 = dr7;
|
task->arch.dr7 = dr7;
|
||||||
|
|
||||||
ret = ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct user, u_debugreg[7]), task->arch.dr7);
|
ret = ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct user, u_debugreg[7]), task->arch.dr7);
|
||||||
if (ret) {
|
if (unlikely(ret)) {
|
||||||
if (errno != ESRCH) {
|
if (errno != ESRCH) {
|
||||||
fprintf(stderr, "PTRACE_POKEUSER u_debugreg[7] pid=%d %s\n", task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_POKEUSER u_debugreg[7] pid=%d %s\n", task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -89,7 +89,7 @@ static int set_breakpoint_addr(struct task *task, arch_addr_t addr, unsigned int
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct user, u_debugreg[n]), addr);
|
ret = ptrace(PTRACE_POKEUSER, task->pid, offsetof(struct user, u_debugreg[n]), addr);
|
||||||
if (ret) {
|
if (unlikely(ret)) {
|
||||||
if (errno != ESRCH) {
|
if (errno != ESRCH) {
|
||||||
fprintf(stderr, "PTRACE_POKEUSER u_debugreg[%d] pid=%d %s\n", n, task->pid, strerror(errno));
|
fprintf(stderr, "PTRACE_POKEUSER u_debugreg[%d] pid=%d %s\n", n, task->pid, strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
@ -167,7 +167,7 @@ int set_hw_bp(struct task *task, unsigned int n, arch_addr_t addr)
|
|||||||
if (reset_hw_bp(task, n) == -1)
|
if (reset_hw_bp(task, n) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
#endif
|
#endif
|
||||||
if (set_breakpoint_addr(task, addr, n) == -1)
|
if (unlikely(set_breakpoint_addr(task, addr, n) == -1))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return set_breakpoint_mode(task,
|
return set_breakpoint_mode(task,
|
||||||
|
|||||||
@ -130,12 +130,12 @@ static const struct arch_reg arch_reg32 = {
|
|||||||
.bp = DWARF_X86_EBP,
|
.bp = DWARF_X86_EBP,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int is_signal_frame(struct dwarf_cursor *c)
|
static inline int is_signal_frame(struct dwarf_cursor *c)
|
||||||
{
|
{
|
||||||
return c->dci.signal_frame;
|
return c->dci.signal_frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int is_plt_entry(struct dwarf_addr_space *as)
|
static inline int is_plt_entry(struct dwarf_addr_space *as)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
@ -293,13 +293,13 @@ int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg)
|
|||||||
{
|
{
|
||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
if (as->is_64bit) {
|
if (as->is_64bit) {
|
||||||
if (reg >= ARRAY_SIZE(dwarf_to_regnum_map64))
|
if (unlikely(reg >= ARRAY_SIZE(dwarf_to_regnum_map64)))
|
||||||
return -DWARF_EBADREG;
|
return -DWARF_EBADREG;
|
||||||
|
|
||||||
return dwarf_to_regnum_map64[reg];
|
return dwarf_to_regnum_map64[reg];
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (reg >= ARRAY_SIZE(dwarf_to_regnum_map32))
|
if (unlikely(reg >= ARRAY_SIZE(dwarf_to_regnum_map32)))
|
||||||
return -DWARF_EBADREG;
|
return -DWARF_EBADREG;
|
||||||
|
|
||||||
return dwarf_to_regnum_map32[reg];
|
return dwarf_to_regnum_map32[reg];
|
||||||
@ -330,16 +330,16 @@ int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
|
|||||||
struct libref *libref = c->libref;
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
for(p = call_op; p->len; ++p) {
|
for(p = call_op; p->len; ++p) {
|
||||||
if (ip - ARCH_ADDR_T(libref->load_addr) >= p->off) {
|
if (likely(ip - ARCH_ADDR_T(libref->load_addr) >= p->off)) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
unsigned char *addr = libref->image_addr + ip - p->off - libref->load_addr;
|
unsigned char *addr = libref->image_addr + ip - p->off - libref->load_addr;
|
||||||
|
|
||||||
for(i = 0; i < call_op[i].len; ++i) {
|
for(i = 0; i < call_op[i].len; ++i) {
|
||||||
if ((addr[i] & p->mask[i]) != p->op[i])
|
if (unlikely((addr[i] & p->mask[i]) != p->op[i]))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i == p->len)
|
if (unlikely(i == p->len))
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
86
task.c
86
task.c
@ -48,7 +48,7 @@
|
|||||||
|
|
||||||
static LIST_HEAD(list_of_leaders);
|
static LIST_HEAD(list_of_leaders);
|
||||||
|
|
||||||
static struct rb_root pid_tree = RB_ROOT;
|
struct pid_hash *pid_hash[PID_HASH_SIZE];
|
||||||
|
|
||||||
#ifndef OS_HAVE_PROCESS_DATA
|
#ifndef OS_HAVE_PROCESS_DATA
|
||||||
static inline int os_task_init(struct task *task)
|
static inline int os_task_init(struct task *task)
|
||||||
@ -82,45 +82,42 @@ static inline int arch_task_clone(struct task *retp, struct task *task)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct task *pid2task(pid_t pid)
|
static inline void delete_pid(struct task *task)
|
||||||
{
|
{
|
||||||
struct rb_node **new = &(pid_tree.rb_node);
|
struct pid_hash *entry = pid_hash[PID_HASH(task->pid)];
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
/* Figure out where to put new node */
|
for(i = 0; i < entry->num; ++i) {
|
||||||
while (*new) {
|
struct task **p = &entry->tasks[i];
|
||||||
struct task *this = container_of(*new, struct task, pid_node);
|
|
||||||
|
|
||||||
if (this->pid == pid)
|
if ((*p)->pid == task->pid) {
|
||||||
return this;
|
entry->num--;
|
||||||
|
memmove(p, p + 1, (entry->num - i) * sizeof(entry->tasks[0]));
|
||||||
if (this->pid < pid)
|
break;
|
||||||
new = &((*new)->rb_left);
|
}
|
||||||
else
|
}
|
||||||
new = &((*new)->rb_right);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
static inline void insert_pid(struct task *task)
|
||||||
}
|
|
||||||
|
|
||||||
static void insert_pid(struct task *task)
|
|
||||||
{
|
{
|
||||||
struct rb_node **new = &(pid_tree.rb_node), *parent = NULL;
|
struct pid_hash *entry = pid_hash[PID_HASH(task->pid)];
|
||||||
|
|
||||||
/* Figure out where to put new node */
|
if (!entry->size) {
|
||||||
while (*new) {
|
entry = malloc(sizeof(*entry) + 8 * sizeof(entry->tasks[0]));
|
||||||
struct task *this = container_of(*new, struct task, pid_node);
|
entry->num = 0;
|
||||||
|
entry->size = 8;
|
||||||
|
|
||||||
parent = *new;
|
pid_hash[PID_HASH(task->pid)] = entry;
|
||||||
|
}
|
||||||
if (this->pid < task->pid)
|
|
||||||
new = &((*new)->rb_left);
|
|
||||||
else
|
else
|
||||||
new = &((*new)->rb_right);
|
if (entry->size == entry->num) {
|
||||||
|
entry->size += 8;
|
||||||
|
entry = realloc(entry, sizeof(*entry) + entry->size * sizeof(entry->tasks[0]));
|
||||||
|
|
||||||
|
pid_hash[PID_HASH(task->pid)] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new node and rebalance tree. */
|
entry->tasks[entry->num++] = task;
|
||||||
rb_link_node(&task->pid_node, parent, new);
|
|
||||||
rb_insert_color(&task->pid_node, &pid_tree);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int leader_setup(struct task *leader)
|
static int leader_setup(struct task *leader)
|
||||||
@ -214,7 +211,7 @@ static void task_destroy(struct task *task)
|
|||||||
arch_task_destroy(task);
|
arch_task_destroy(task);
|
||||||
os_task_destroy(task);
|
os_task_destroy(task);
|
||||||
detach_task(task);
|
detach_task(task);
|
||||||
rb_erase(&task->pid_node, &pid_tree);
|
delete_pid(task);
|
||||||
|
|
||||||
if (leader != task) {
|
if (leader != task) {
|
||||||
list_del(&task->task_list);
|
list_del(&task->task_list);
|
||||||
@ -516,7 +513,7 @@ void open_pid(pid_t pid)
|
|||||||
task->is_64bit = leader->is_64bit;
|
task->is_64bit = leader->is_64bit;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.verbose)
|
if (unlikely(options.verbose))
|
||||||
each_task(leader, &show_attached, NULL);
|
each_task(leader, &show_attached, NULL);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -575,9 +572,30 @@ int task_list_empty(void)
|
|||||||
|
|
||||||
void each_pid(void (*cb)(struct task *task))
|
void each_pid(void (*cb)(struct task *task))
|
||||||
{
|
{
|
||||||
struct task *task, *next;
|
unsigned int i;
|
||||||
|
|
||||||
rbtree_postorder_for_each_entry_safe(task, next, &pid_tree, pid_node)
|
for(i = 0; i < ARRAY_SIZE(pid_hash); ++i) {
|
||||||
(*cb)(task);
|
struct pid_hash *entry = pid_hash[i];
|
||||||
|
unsigned int n = entry->num;
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
struct task **p = alloca(n * sizeof(*p));
|
||||||
|
|
||||||
|
memcpy(p, entry->tasks, n * sizeof(*p));
|
||||||
|
|
||||||
|
do {
|
||||||
|
(*cb)(*p++);
|
||||||
|
} while(--n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_pid_hash(void)
|
||||||
|
{
|
||||||
|
static const struct pid_hash preset = { .size = 0, .num = 0 };
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for(i = 0; i < ARRAY_SIZE(pid_hash); ++i)
|
||||||
|
pid_hash[i] = (void *)&preset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
81
task.h
81
task.h
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
@ -38,36 +39,22 @@
|
|||||||
#include "report.h"
|
#include "report.h"
|
||||||
|
|
||||||
struct task {
|
struct task {
|
||||||
/* red/black tree node for fast pid -> struct task */
|
|
||||||
struct rb_node pid_node;
|
|
||||||
|
|
||||||
/* process id */
|
|
||||||
pid_t pid;
|
|
||||||
|
|
||||||
/* points to the leader thread of the POSIX.1 task */
|
|
||||||
struct task *leader;
|
|
||||||
|
|
||||||
/* current pendig event */
|
/* current pendig event */
|
||||||
struct event event;
|
struct event event;
|
||||||
|
|
||||||
unsigned int stopped:1;
|
|
||||||
unsigned int traced:1;
|
|
||||||
unsigned int was_stopped:1;
|
|
||||||
unsigned int is_64bit:1;
|
unsigned int is_64bit:1;
|
||||||
|
unsigned int traced:1;
|
||||||
unsigned int attached:1;
|
unsigned int attached:1;
|
||||||
unsigned int deleted:1;
|
unsigned int deleted:1;
|
||||||
unsigned int about_exit:1;
|
unsigned int about_exit:1;
|
||||||
|
unsigned int was_stopped:1;
|
||||||
|
unsigned int stopped:1;
|
||||||
|
|
||||||
struct breakpoint *breakpoint;
|
struct breakpoint *breakpoint;
|
||||||
struct library_symbol *libsym;
|
struct library_symbol *libsym;
|
||||||
struct context context; /* process context (registers, stack) */
|
struct context context; /* process context (registers, stack) */
|
||||||
struct context saved_context; /* context for fetch_param() */
|
struct context saved_context; /* context for fetch_param() */
|
||||||
|
|
||||||
/* os specific task data */
|
|
||||||
#ifdef OS_HAVE_PROCESS_DATA
|
|
||||||
struct os_task_data os;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* arch specific task data */
|
/* arch specific task data */
|
||||||
#ifdef TASK_HAVE_PROCESS_DATA
|
#ifdef TASK_HAVE_PROCESS_DATA
|
||||||
struct arch_task_data arch;
|
struct arch_task_data arch;
|
||||||
@ -76,12 +63,20 @@ struct task {
|
|||||||
/* pointer to a breakpoint which was interrupt by a signal during skip */
|
/* pointer to a breakpoint which was interrupt by a signal during skip */
|
||||||
struct breakpoint *skip_bp;
|
struct breakpoint *skip_bp;
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 0
|
||||||
|
/* array of active hw breakpoints */
|
||||||
|
struct breakpoint *hw_bp[HW_BREAKPOINTS];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* process id */
|
||||||
|
pid_t pid;
|
||||||
|
|
||||||
|
/* points to the leader thread */
|
||||||
|
struct task *leader;
|
||||||
|
|
||||||
/* set in leader: number of stopped threads including the leader */
|
/* set in leader: number of stopped threads including the leader */
|
||||||
unsigned int threads_stopped;
|
unsigned int threads_stopped;
|
||||||
|
|
||||||
unsigned long num_hw_bp;
|
|
||||||
unsigned long num_sw_bp;
|
|
||||||
|
|
||||||
/* set in leader: dictionary of breakpoints */
|
/* set in leader: dictionary of breakpoints */
|
||||||
struct dict *breakpoints;
|
struct dict *breakpoints;
|
||||||
|
|
||||||
@ -91,6 +86,9 @@ struct task {
|
|||||||
/* linked list of libraries, the first entry is the executable itself */
|
/* linked list of libraries, the first entry is the executable itself */
|
||||||
struct list_head libraries_list;
|
struct list_head libraries_list;
|
||||||
|
|
||||||
|
/* red black tree of libraries */
|
||||||
|
struct rb_root libraries_tree;
|
||||||
|
|
||||||
/* Thread chaining to leader */
|
/* Thread chaining to leader */
|
||||||
struct list_head task_list;
|
struct list_head task_list;
|
||||||
|
|
||||||
@ -100,6 +98,9 @@ struct task {
|
|||||||
/* struct task chaining. */
|
/* struct task chaining. */
|
||||||
struct list_head leader_list;
|
struct list_head leader_list;
|
||||||
|
|
||||||
|
/* halt time for debugging purpose */
|
||||||
|
struct timespec halt_time;
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 1
|
#if HW_BREAKPOINTS > 1
|
||||||
/* set in leader: list of hw breakpoints */
|
/* set in leader: list of hw breakpoints */
|
||||||
struct list_head hw_bp_list;
|
struct list_head hw_bp_list;
|
||||||
@ -108,9 +109,9 @@ struct task {
|
|||||||
unsigned long hw_bp_num;
|
unsigned long hw_bp_num;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 0
|
/* os specific task data */
|
||||||
/* array of active hw breakpoints */
|
#ifdef OS_HAVE_PROCESS_DATA
|
||||||
struct breakpoint *hw_bp[HW_BREAKPOINTS];
|
struct os_task_data os;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -122,8 +123,6 @@ struct task *task_create(const char *command, char **argv);
|
|||||||
|
|
||||||
void open_pid(pid_t pid);
|
void open_pid(pid_t pid);
|
||||||
|
|
||||||
struct task *pid2task(pid_t pid);
|
|
||||||
|
|
||||||
/* Clone the contents of a task */
|
/* Clone the contents of a task */
|
||||||
int task_clone(struct task *task, struct task *newtask);
|
int task_clone(struct task *task, struct task *newtask);
|
||||||
|
|
||||||
@ -157,5 +156,37 @@ static inline int task_is_64bit(struct task *task)
|
|||||||
return task->is_64bit;
|
return task->is_64bit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pid_hash {
|
||||||
|
unsigned int num;
|
||||||
|
unsigned int size;
|
||||||
|
struct task * tasks[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define PID_HASH(pid) ((pid) % ARRAY_SIZE(pid_hash))
|
||||||
|
#define PID_HASH_SIZE 256
|
||||||
|
|
||||||
|
extern struct pid_hash *pid_hash[PID_HASH_SIZE];
|
||||||
|
|
||||||
|
void init_pid_hash(void);
|
||||||
|
|
||||||
|
static inline struct task *pid2task(pid_t pid)
|
||||||
|
{
|
||||||
|
struct pid_hash *entry = pid_hash[PID_HASH(pid)];
|
||||||
|
struct task **p = entry->tasks;
|
||||||
|
unsigned int n = entry->num;
|
||||||
|
|
||||||
|
while(n) {
|
||||||
|
struct task *task = *p;
|
||||||
|
|
||||||
|
if (likely(task->pid == pid))
|
||||||
|
return task;
|
||||||
|
|
||||||
|
p++;
|
||||||
|
n--;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
62
timer.h
Normal file
62
timer.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of mtrace-ng.
|
||||||
|
* Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>
|
||||||
|
*
|
||||||
|
* This work was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich/Germany.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License as
|
||||||
|
* published by the Free Software Foundation; either version 2 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program 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
|
||||||
|
* General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
|
* 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _INC_TIMER_H
|
||||||
|
#define _INC_TIMER_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
struct mt_timer {
|
||||||
|
unsigned int max;
|
||||||
|
unsigned int count;
|
||||||
|
unsigned long long culminate;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int start_time(struct timespec *ts)
|
||||||
|
{
|
||||||
|
return clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int set_timer(struct timespec *start, struct mt_timer *p)
|
||||||
|
{
|
||||||
|
struct timespec now;
|
||||||
|
unsigned int usec;
|
||||||
|
|
||||||
|
if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &now) == -1)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
usec = (now.tv_sec - start->tv_sec) * 1000000L +
|
||||||
|
(now.tv_nsec - start->tv_nsec + 500L) / 1000;
|
||||||
|
|
||||||
|
if (p->max < usec)
|
||||||
|
p->max = usec;
|
||||||
|
|
||||||
|
p->culminate += usec;
|
||||||
|
|
||||||
|
++p->count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
17
trace.c
17
trace.c
@ -40,6 +40,7 @@
|
|||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
|
#include "main.h"
|
||||||
|
|
||||||
int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
@ -50,12 +51,20 @@ int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
if (bp->enabled && !bp->hw) {
|
if (bp->enabled && !bp->hw) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct timespec start;
|
||||||
|
|
||||||
|
if (unlikely(options.verbose > 1))
|
||||||
|
start_time(&start);
|
||||||
|
|
||||||
breakpoint_disable(task, bp);
|
breakpoint_disable(task, bp);
|
||||||
ret = do_singlestep(task);
|
ret = do_singlestep(task);
|
||||||
breakpoint_enable(task, bp);
|
breakpoint_enable(task, bp);
|
||||||
if (ret) {
|
|
||||||
if (ret == 1) {
|
if (unlikely(options.verbose > 1))
|
||||||
|
set_timer(&start, &skip_bp_time);
|
||||||
|
|
||||||
|
if (unlikely(ret)) {
|
||||||
|
if (unlikely(ret == 1)) {
|
||||||
breakpoint_put(task->skip_bp);
|
breakpoint_put(task->skip_bp);
|
||||||
task->skip_bp = breakpoint_get(bp);
|
task->skip_bp = breakpoint_get(bp);
|
||||||
}
|
}
|
||||||
@ -105,8 +114,8 @@ void detach_proc(struct task *leader)
|
|||||||
|
|
||||||
breakpoint_disable_all(leader);
|
breakpoint_disable_all(leader);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (unlikely(options.verbose > 1))
|
||||||
fprintf(stderr, "+++ process detach pid=%d sw-bp:%lu hw-bp:%lu +++\n", leader->pid, leader->num_sw_bp, leader->num_hw_bp);
|
fprintf(stderr, "+++ process detach pid=%d +++\n", leader->pid);
|
||||||
|
|
||||||
each_task(leader, &detach_cb, NULL);
|
each_task(leader, &detach_cb, NULL);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user