mirror of
https://github.com/sstefani/mtrace.git
synced 2025-12-06 08:46:41 +08:00
Version 0.2
Lots of performance improvement Better stack unwind Bug fixes
This commit is contained in:
parent
e8f26940d0
commit
d517c6fceb
@ -484,7 +484,7 @@ noinst_HEADERS = \
|
|||||||
|
|
||||||
dist_man1_MANS = mtrace.1
|
dist_man1_MANS = mtrace.1
|
||||||
dist_man5_MANS = mtrace.conf.5
|
dist_man5_MANS = mtrace.conf.5
|
||||||
dist_doc_DATA = COPYING CREDITS INSTALL README TODO
|
dist_doc_DATA = COPYING CREDITS INSTALL README TODO HOWTO
|
||||||
EXTRA_DIST =
|
EXTRA_DIST =
|
||||||
MAINTAINERCLEANFILES = \
|
MAINTAINERCLEANFILES = \
|
||||||
configure \
|
configure \
|
||||||
|
|||||||
@ -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 0.1.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace 0.2.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ 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'
|
PACKAGE_NAME='mtrace'
|
||||||
PACKAGE_TARNAME='mtrace'
|
PACKAGE_TARNAME='mtrace'
|
||||||
PACKAGE_VERSION='0.1'
|
PACKAGE_VERSION='0.2'
|
||||||
PACKAGE_STRING='mtrace 0.1'
|
PACKAGE_STRING='mtrace 0.2'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1326,7 +1326,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 0.1 to adapt to many kinds of systems.
|
\`configure' configures mtrace 0.2 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1396,7 +1396,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 0.1:";;
|
short | recursive ) echo "Configuration of mtrace 0.2:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1512,7 +1512,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 configure 0.1
|
mtrace configure 0.2
|
||||||
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.
|
||||||
@ -2118,7 +2118,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 $as_me 0.1, which was
|
It was created by mtrace $as_me 0.2, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12000,7 +12000,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace'
|
PACKAGE='mtrace'
|
||||||
VERSION='0.1'
|
VERSION='0.2'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -12746,6 +12746,8 @@ else
|
|||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
CPPFLAGS="${saved_CPPFLAGS}"
|
||||||
|
LDFLAGS="${saved_LDFLAGS}"
|
||||||
|
|
||||||
saved_CFLAGS="${CFLAGS}"
|
saved_CFLAGS="${CFLAGS}"
|
||||||
CFLAGS="${CFLAGS} -Wall -Werror"
|
CFLAGS="${CFLAGS} -Wall -Werror"
|
||||||
@ -13206,6 +13208,7 @@ for ac_func in \
|
|||||||
strerror \
|
strerror \
|
||||||
strtol \
|
strtol \
|
||||||
strtoul \
|
strtoul \
|
||||||
|
process_vm_readv \
|
||||||
|
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
@ -13799,7 +13802,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 $as_me 0.1, which was
|
This file was extended by mtrace $as_me 0.2, 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
|
||||||
@ -13865,7 +13868,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 config.status 0.1
|
mtrace config.status 0.2
|
||||||
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 0.1.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace 0.2.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ 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'
|
PACKAGE_NAME='mtrace'
|
||||||
PACKAGE_TARNAME='mtrace'
|
PACKAGE_TARNAME='mtrace'
|
||||||
PACKAGE_VERSION='0.1'
|
PACKAGE_VERSION='0.2'
|
||||||
PACKAGE_STRING='mtrace 0.1'
|
PACKAGE_STRING='mtrace 0.2'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1326,7 +1326,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 0.1 to adapt to many kinds of systems.
|
\`configure' configures mtrace 0.2 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1396,7 +1396,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 0.1:";;
|
short | recursive ) echo "Configuration of mtrace 0.2:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1512,7 +1512,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 configure 0.1
|
mtrace configure 0.2
|
||||||
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.
|
||||||
@ -2118,7 +2118,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 $as_me 0.1, which was
|
It was created by mtrace $as_me 0.2, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12000,7 +12000,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace'
|
PACKAGE='mtrace'
|
||||||
VERSION='0.1'
|
VERSION='0.2'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -12746,6 +12746,8 @@ else
|
|||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
CPPFLAGS="${saved_CPPFLAGS}"
|
||||||
|
LDFLAGS="${saved_LDFLAGS}"
|
||||||
|
|
||||||
saved_CFLAGS="${CFLAGS}"
|
saved_CFLAGS="${CFLAGS}"
|
||||||
CFLAGS="${CFLAGS} -Wall -Werror"
|
CFLAGS="${CFLAGS} -Wall -Werror"
|
||||||
@ -13206,6 +13208,7 @@ for ac_func in \
|
|||||||
strerror \
|
strerror \
|
||||||
strtol \
|
strtol \
|
||||||
strtoul \
|
strtoul \
|
||||||
|
process_vm_readv \
|
||||||
|
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
@ -13799,7 +13802,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 $as_me 0.1, which was
|
This file was extended by mtrace $as_me 0.2, 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
|
||||||
@ -13865,7 +13868,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 config.status 0.1
|
mtrace config.status 0.2
|
||||||
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 0.1.
|
@%:@ Generated by GNU Autoconf 2.69 for mtrace 0.2.
|
||||||
@%:@
|
@%:@
|
||||||
@%:@ 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'
|
PACKAGE_NAME='mtrace'
|
||||||
PACKAGE_TARNAME='mtrace'
|
PACKAGE_TARNAME='mtrace'
|
||||||
PACKAGE_VERSION='0.1'
|
PACKAGE_VERSION='0.2'
|
||||||
PACKAGE_STRING='mtrace 0.1'
|
PACKAGE_STRING='mtrace 0.2'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1326,7 +1326,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 0.1 to adapt to many kinds of systems.
|
\`configure' configures mtrace 0.2 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1396,7 +1396,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 0.1:";;
|
short | recursive ) echo "Configuration of mtrace 0.2:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1512,7 +1512,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 configure 0.1
|
mtrace configure 0.2
|
||||||
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.
|
||||||
@ -2118,7 +2118,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 $as_me 0.1, which was
|
It was created by mtrace $as_me 0.2, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12000,7 +12000,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace'
|
PACKAGE='mtrace'
|
||||||
VERSION='0.1'
|
VERSION='0.2'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -12746,6 +12746,8 @@ else
|
|||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
CPPFLAGS="${saved_CPPFLAGS}"
|
||||||
|
LDFLAGS="${saved_LDFLAGS}"
|
||||||
|
|
||||||
saved_CFLAGS="${CFLAGS}"
|
saved_CFLAGS="${CFLAGS}"
|
||||||
CFLAGS="${CFLAGS} -Wall -Werror"
|
CFLAGS="${CFLAGS} -Wall -Werror"
|
||||||
@ -13206,6 +13208,7 @@ for ac_func in \
|
|||||||
strerror \
|
strerror \
|
||||||
strtol \
|
strtol \
|
||||||
strtoul \
|
strtoul \
|
||||||
|
process_vm_readv \
|
||||||
|
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
@ -13799,7 +13802,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 $as_me 0.1, which was
|
This file was extended by mtrace $as_me 0.2, 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
|
||||||
@ -13865,7 +13868,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 config.status 0.1
|
mtrace config.status 0.2
|
||||||
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'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'LT_AC_PROG_RC' => 1,
|
'_LT_CC_BASENAME' => 1,
|
||||||
'AM_SUBST_NOTMAKE' => 1,
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
'AC_LTDL_PREOPEN' => 1,
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
'_AM_SET_OPTIONS' => 1,
|
||||||
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
'AC_CHECK_LIBM' => 1,
|
||||||
'LT_LIB_M' => 1,
|
|
||||||
'AM_SILENT_RULES' => 1,
|
|
||||||
'AC_LIBTOOL_SETUP' => 1,
|
|
||||||
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
|
||||||
'AC_PATH_MAGIC' => 1,
|
|
||||||
'_LT_AC_LOCK' => 1,
|
|
||||||
'LTOPTIONS_VERSION' => 1,
|
|
||||||
'_LT_AC_LANG_CXX' => 1,
|
|
||||||
'_LT_LINKER_BOILERPLATE' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'AM_DISABLE_SHARED' => 1,
|
|
||||||
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
|
||||||
'AC_LIBTOOL_PICMODE' => 1,
|
|
||||||
'AU_DEFUN' => 1,
|
'AU_DEFUN' => 1,
|
||||||
'_LT_PATH_TOOL_PREFIX' => 1,
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
'AC_LTDL_DLLIB' => 1,
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
'AM_PROG_NM' => 1,
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
'LTDL_INSTALLABLE' => 1,
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
'_m4_warn' => 1,
|
||||||
'LT_SYS_DLSEARCH_PATH' => 1,
|
|
||||||
'_AM_PROG_TAR' => 1,
|
|
||||||
'AC_LTDL_DLSYM_USCORE' => 1,
|
|
||||||
'_LT_AC_LANG_F77' => 1,
|
|
||||||
'_AM_PROG_CC_C_O' => 1,
|
|
||||||
'AM_ENABLE_SHARED' => 1,
|
|
||||||
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
|
||||||
'AC_LTDL_SHLIBPATH' => 1,
|
|
||||||
'_LT_AC_TAGVAR' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
|
||||||
'AC_LIBTOOL_OBJDIR' => 1,
|
|
||||||
'_LT_COMPILER_BOILERPLATE' => 1,
|
|
||||||
'AM_ENABLE_STATIC' => 1,
|
|
||||||
'_LT_AC_SHELL_INIT' => 1,
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
'_LT_WITH_SYSROOT' => 1,
|
'_LT_DLL_DEF_P' => 1,
|
||||||
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1,
|
||||||
'LT_OUTPUT' => 1,
|
'LT_OUTPUT' => 1,
|
||||||
'_LT_AC_LANG_RC_CONFIG' => 1,
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'_AM_CONFIG_MACRO_DIRS' => 1,
|
||||||
|
'LT_PROG_GO' => 1,
|
||||||
|
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'_LT_PROG_CXX' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'AM_MISSING_PROG' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'AC_LTDL_DLLIB' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
'_AM_DEPENDENCIES' => 1,
|
'_AM_DEPENDENCIES' => 1,
|
||||||
'LT_WITH_LTDL' => 1,
|
'LT_WITH_LTDL' => 1,
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
'AM_DISABLE_SHARED' => 1,
|
||||||
'_AM_AUTOCONF_VERSION' => 1,
|
|
||||||
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
|
||||||
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
|
||||||
'LT_LIB_DLLOAD' => 1,
|
|
||||||
'AC_LIBTOOL_CONFIG' => 1,
|
|
||||||
'_LTDL_SETUP' => 1,
|
|
||||||
'LT_FUNC_DLSYM_USCORE' => 1,
|
|
||||||
'LTSUGAR_VERSION' => 1,
|
'LTSUGAR_VERSION' => 1,
|
||||||
'AM_MISSING_PROG' => 1,
|
|
||||||
'LT_PROG_GO' => 1,
|
|
||||||
'LT_AC_PROG_EGREP' => 1,
|
|
||||||
'_m4_warn' => 1,
|
|
||||||
'AM_DISABLE_STATIC' => 1,
|
|
||||||
'AM_PROG_CC_C_O' => 1,
|
|
||||||
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
|
||||||
'LT_SYS_DLOPEN_SELF' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
|
||||||
'AC_LTDL_OBJDIR' => 1,
|
|
||||||
'_LT_PROG_LTMAIN' => 1,
|
|
||||||
'AC_LIBLTDL_CONVENIENCE' => 1,
|
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
|
||||||
'AC_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
|
||||||
'_LT_CC_BASENAME' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
|
||||||
'AC_LIBTOOL_CXX' => 1,
|
|
||||||
'LT_SYS_MODULE_EXT' => 1,
|
|
||||||
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'LTOBSOLETE_VERSION' => 1,
|
|
||||||
'LT_INIT' => 1,
|
|
||||||
'LT_FUNC_ARGZ' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
|
||||||
'AC_DISABLE_FAST_INSTALL' => 1,
|
|
||||||
'AC_LIBTOOL_GCJ' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'AM_PROG_INSTALL_SH' => 1,
|
|
||||||
'AC_ENABLE_SHARED' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
|
||||||
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
|
||||||
'AC_DISABLE_SHARED' => 1,
|
|
||||||
'AC_PROG_EGREP' => 1,
|
|
||||||
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
|
||||||
'AC_LIBTOOL_FC' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
|
||||||
'_AC_PROG_LIBTOOL' => 1,
|
|
||||||
'LT_PATH_NM' => 1,
|
|
||||||
'AM_AUX_DIR_EXPAND' => 1,
|
|
||||||
'include' => 1,
|
|
||||||
'AC_DISABLE_STATIC' => 1,
|
|
||||||
'AM_SET_DEPDIR' => 1,
|
|
||||||
'_AM_MANGLE_OPTION' => 1,
|
|
||||||
'LT_PROG_GCJ' => 1,
|
|
||||||
'_AM_SET_OPTIONS' => 1,
|
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
|
||||||
'_LT_AC_PROG_CXXCPP' => 1,
|
|
||||||
'_LT_PROG_FC' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
|
||||||
'_LT_PROG_CXX' => 1,
|
|
||||||
'_LT_AC_CHECK_DLFCN' => 1,
|
|
||||||
'AM_SANITY_CHECK' => 1,
|
|
||||||
'AC_LTDL_SYMBOL_USCORE' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
|
||||||
'AC_LIBTOOL_RC' => 1,
|
|
||||||
'AC_LIBTOOL_F77' => 1,
|
|
||||||
'AM_RUN_LOG' => 1,
|
|
||||||
'm4_include' => 1,
|
|
||||||
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
|
||||||
'LT_PATH_LD' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'AM_PROG_LIBTOOL' => 1,
|
|
||||||
'LTDL_INIT' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
|
||||||
'AM_MAKE_INCLUDE' => 1,
|
|
||||||
'LTDL_CONVENIENCE' => 1,
|
|
||||||
'AC_LIB_LTDL' => 1,
|
|
||||||
'LT_SYS_MODULE_PATH' => 1,
|
|
||||||
'LT_CMD_MAX_LEN' => 1,
|
|
||||||
'm4_pattern_forbid' => 1,
|
|
||||||
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
|
||||||
'AM_PROG_LD' => 1,
|
|
||||||
'AC_LTDL_SHLIBEXT' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
|
||||||
'AC_LIBLTDL_INSTALLABLE' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
|
||||||
'_AM_CONFIG_MACRO_DIRS' => 1,
|
|
||||||
'AC_LTDL_ENABLE_INSTALL' => 1,
|
|
||||||
'AC_ENABLE_FAST_INSTALL' => 1,
|
|
||||||
'LT_AC_PROG_GCJ' => 1,
|
|
||||||
'AC_LTDL_SYSSEARCHPATH' => 1,
|
|
||||||
'AM_MISSING_HAS_RUN' => 1,
|
|
||||||
'AC_PROG_NM' => 1,
|
|
||||||
'AM_PROG_INSTALL_STRIP' => 1,
|
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'_AM_SET_OPTION' => 1,
|
|
||||||
'LT_PROG_RC' => 1,
|
|
||||||
'AM_CONDITIONAL' => 1,
|
|
||||||
'AC_ENABLE_STATIC' => 1,
|
|
||||||
'LT_SYS_SYMBOL_USCORE' => 1,
|
|
||||||
'AM_SET_LEADING_DOT' => 1,
|
|
||||||
'_LT_COMPILER_OPTION' => 1,
|
|
||||||
'_LT_LINKER_OPTION' => 1,
|
|
||||||
'_AM_IF_OPTION' => 1,
|
|
||||||
'AC_LIBTOOL_WIN32_DLL' => 1,
|
|
||||||
'_LT_LIBOBJ' => 1,
|
|
||||||
'AC_DEFUN' => 1,
|
|
||||||
'LT_AC_PROG_SED' => 1,
|
|
||||||
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'AC_WITH_LTDL' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ' => 1,
|
|
||||||
'AC_DEFUN_ONCE' => 1,
|
'AC_DEFUN_ONCE' => 1,
|
||||||
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
'_LT_AC_LANG_C_CONFIG' => 1,
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
'LT_FUNC_ARGZ' => 1,
|
||||||
'_LT_AC_FILE_LTDLL_C' => 1,
|
'_LTDL_SETUP' => 1,
|
||||||
'LTVERSION_VERSION' => 1,
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
'AC_PROG_LD_GNU' => 1,
|
'AC_DISABLE_SHARED' => 1,
|
||||||
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
|
||||||
'AC_CHECK_LIBM' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
|
||||||
'_LT_AC_LANG_F77_CONFIG' => 1,
|
|
||||||
'_LT_AC_SYS_COMPILER' => 1,
|
|
||||||
'_LT_DLL_DEF_P' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
'LT_LANG' => 1,
|
'AM_SUBST_NOTMAKE' => 1,
|
||||||
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
'AM_ENABLE_STATIC' => 1,
|
||||||
'AC_PROG_LD' => 1,
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
'AM_DEP_TRACK' => 1,
|
'AM_DEP_TRACK' => 1,
|
||||||
'_LT_PROG_F77' => 1
|
'_LT_WITH_SYSROOT' => 1,
|
||||||
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'AM_PROG_NM' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
|
'LT_AC_PROG_RC' => 1,
|
||||||
|
'AM_SILENT_RULES' => 1,
|
||||||
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
|
'LTDL_INIT' => 1,
|
||||||
|
'AM_DISABLE_STATIC' => 1,
|
||||||
|
'_LT_AC_PROG_CXXCPP' => 1,
|
||||||
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
||||||
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'AC_DISABLE_STATIC' => 1,
|
||||||
|
'AC_LTDL_SHLIBPATH' => 1,
|
||||||
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'_AM_IF_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'_LT_PROG_FC' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_LIB_DLLOAD' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'_AM_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'_LT_PROG_F77' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'AC_PROG_NM' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'AC_DEFUN' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'AM_SANITY_CHECK' => 1,
|
||||||
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' ),
|
], 'Autom4te::Request' ),
|
||||||
bless( [
|
bless( [
|
||||||
@ -263,186 +263,186 @@
|
|||||||
'configure.ac'
|
'configure.ac'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'AC_LIBTOOL_SETUP' => 1,
|
|
||||||
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
|
||||||
'AC_PATH_MAGIC' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
|
||||||
'LT_LIB_M' => 1,
|
|
||||||
'AM_SILENT_RULES' => 1,
|
|
||||||
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
|
||||||
'LT_AC_PROG_RC' => 1,
|
|
||||||
'AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'AC_LTDL_PREOPEN' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
|
||||||
'LT_SYS_DLSEARCH_PATH' => 1,
|
|
||||||
'AC_LTDL_DLSYM_USCORE' => 1,
|
|
||||||
'_AM_PROG_TAR' => 1,
|
|
||||||
'_AM_PROG_CC_C_O' => 1,
|
|
||||||
'_LT_AC_LANG_F77' => 1,
|
|
||||||
'AM_ENABLE_SHARED' => 1,
|
|
||||||
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
|
||||||
'AM_PROG_NM' => 1,
|
|
||||||
'LTDL_INSTALLABLE' => 1,
|
|
||||||
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
|
||||||
'AC_LIBTOOL_PICMODE' => 1,
|
|
||||||
'AU_DEFUN' => 1,
|
|
||||||
'_LT_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'AC_LTDL_DLLIB' => 1,
|
|
||||||
'_LT_AC_LOCK' => 1,
|
|
||||||
'_LT_AC_LANG_CXX' => 1,
|
|
||||||
'LTOPTIONS_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
|
||||||
'_LT_LINKER_BOILERPLATE' => 1,
|
|
||||||
'AM_DISABLE_SHARED' => 1,
|
|
||||||
'AM_MISSING_PROG' => 1,
|
|
||||||
'LT_PROG_GO' => 1,
|
|
||||||
'LT_AC_PROG_EGREP' => 1,
|
|
||||||
'_m4_warn' => 1,
|
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
|
||||||
'LT_WITH_LTDL' => 1,
|
|
||||||
'_AM_AUTOCONF_VERSION' => 1,
|
|
||||||
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
|
||||||
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
|
||||||
'LT_LIB_DLLOAD' => 1,
|
|
||||||
'AC_LIBTOOL_CONFIG' => 1,
|
|
||||||
'_LTDL_SETUP' => 1,
|
|
||||||
'LTSUGAR_VERSION' => 1,
|
|
||||||
'LT_FUNC_DLSYM_USCORE' => 1,
|
|
||||||
'AM_ENABLE_STATIC' => 1,
|
|
||||||
'_LT_WITH_SYSROOT' => 1,
|
|
||||||
'_LT_AC_SHELL_INIT' => 1,
|
|
||||||
'LT_OUTPUT' => 1,
|
|
||||||
'_LT_AC_LANG_RC_CONFIG' => 1,
|
|
||||||
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
|
||||||
'_AM_DEPENDENCIES' => 1,
|
|
||||||
'AC_LTDL_SHLIBPATH' => 1,
|
|
||||||
'_LT_AC_TAGVAR' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR' => 1,
|
|
||||||
'AC_LIBTOOL_OBJDIR' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
'AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE' => 1,
|
||||||
'_LT_COMPILER_BOILERPLATE' => 1,
|
'AM_PROG_NM' => 1,
|
||||||
'AC_DISABLE_SHARED' => 1,
|
|
||||||
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
|
||||||
'AC_PROG_EGREP' => 1,
|
|
||||||
'AC_LIBTOOL_FC' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
|
||||||
'AM_PROG_INSTALL_SH' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'AC_ENABLE_SHARED' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
|
||||||
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1,
|
|
||||||
'AC_LIBTOOL_CXX' => 1,
|
|
||||||
'LT_SYS_MODULE_EXT' => 1,
|
|
||||||
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'LTOBSOLETE_VERSION' => 1,
|
|
||||||
'LT_FUNC_ARGZ' => 1,
|
|
||||||
'LT_INIT' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
|
||||||
'AC_LIBTOOL_GCJ' => 1,
|
|
||||||
'AC_DISABLE_FAST_INSTALL' => 1,
|
|
||||||
'AM_PROG_CC_C_O' => 1,
|
|
||||||
'AM_DISABLE_STATIC' => 1,
|
|
||||||
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
|
||||||
'LT_SYS_DLOPEN_SELF' => 1,
|
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
|
||||||
'AC_LIBLTDL_CONVENIENCE' => 1,
|
|
||||||
'AC_PATH_TOOL_PREFIX' => 1,
|
|
||||||
'_LT_PROG_LTMAIN' => 1,
|
|
||||||
'AC_LTDL_OBJDIR' => 1,
|
|
||||||
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
|
||||||
'_LT_CC_BASENAME' => 1,
|
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
|
||||||
'AM_RUN_LOG' => 1,
|
|
||||||
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
|
||||||
'm4_include' => 1,
|
|
||||||
'LT_PATH_LD' => 1,
|
|
||||||
'AM_PROG_LIBTOOL' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'_LT_PROG_CXX' => 1,
|
|
||||||
'_LT_AC_CHECK_DLFCN' => 1,
|
|
||||||
'AM_SANITY_CHECK' => 1,
|
|
||||||
'AC_LTDL_SYMBOL_USCORE' => 1,
|
|
||||||
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
|
||||||
'AC_LIBTOOL_RC' => 1,
|
|
||||||
'AC_LIBTOOL_F77' => 1,
|
|
||||||
'_LT_AC_PROG_CXXCPP' => 1,
|
|
||||||
'_LT_PROG_FC' => 1,
|
|
||||||
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
|
||||||
'_AC_PROG_LIBTOOL' => 1,
|
|
||||||
'LT_PATH_NM' => 1,
|
|
||||||
'AM_AUX_DIR_EXPAND' => 1,
|
|
||||||
'include' => 1,
|
|
||||||
'AC_DISABLE_STATIC' => 1,
|
|
||||||
'AM_SET_DEPDIR' => 1,
|
|
||||||
'_AM_MANGLE_OPTION' => 1,
|
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
|
||||||
'_AM_SET_OPTIONS' => 1,
|
|
||||||
'LT_PROG_GCJ' => 1,
|
|
||||||
'AC_LTDL_SHLIBEXT' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
|
||||||
'AC_LIBLTDL_INSTALLABLE' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
|
||||||
'_AM_CONFIG_MACRO_DIRS' => 1,
|
|
||||||
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
|
||||||
'AM_PROG_LD' => 1,
|
|
||||||
'LT_SYS_MODULE_PATH' => 1,
|
|
||||||
'LT_CMD_MAX_LEN' => 1,
|
|
||||||
'm4_pattern_forbid' => 1,
|
|
||||||
'LTDL_INIT' => 1,
|
|
||||||
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
|
||||||
'AM_MAKE_INCLUDE' => 1,
|
|
||||||
'LTDL_CONVENIENCE' => 1,
|
|
||||||
'AC_LIB_LTDL' => 1,
|
|
||||||
'AC_PROG_NM' => 1,
|
|
||||||
'AM_PROG_INSTALL_STRIP' => 1,
|
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'_AM_SET_OPTION' => 1,
|
|
||||||
'LT_PROG_RC' => 1,
|
|
||||||
'AM_CONDITIONAL' => 1,
|
|
||||||
'AC_ENABLE_STATIC' => 1,
|
|
||||||
'AM_MISSING_HAS_RUN' => 1,
|
|
||||||
'AC_LTDL_SYSSEARCHPATH' => 1,
|
|
||||||
'AC_LTDL_ENABLE_INSTALL' => 1,
|
|
||||||
'AC_ENABLE_FAST_INSTALL' => 1,
|
|
||||||
'LT_AC_PROG_GCJ' => 1,
|
|
||||||
'_LT_AC_LANG_F77_CONFIG' => 1,
|
|
||||||
'_LT_DLL_DEF_P' => 1,
|
|
||||||
'_LT_AC_SYS_COMPILER' => 1,
|
|
||||||
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
|
||||||
'LT_LANG' => 1,
|
|
||||||
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
'AC_PROG_LD' => 1,
|
'AM_SILENT_RULES' => 1,
|
||||||
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
'LT_SYS_MODULE_PATH' => 1,
|
||||||
'_LT_PROG_F77' => 1,
|
'AC_LIBTOOL_LANG_F77_CONFIG' => 1,
|
||||||
'AM_DEP_TRACK' => 1,
|
'LT_AC_PROG_RC' => 1,
|
||||||
'_LT_AC_FILE_LTDLL_C' => 1,
|
'_LT_PREPARE_SED_QUOTE_VARS' => 1,
|
||||||
'LTVERSION_VERSION' => 1,
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
'AC_PROG_LD_GNU' => 1,
|
'AM_DISABLE_STATIC' => 1,
|
||||||
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
'_LT_AC_PROG_CXXCPP' => 1,
|
||||||
'AC_CHECK_LIBM' => 1,
|
'_LT_PATH_TOOL_PREFIX' => 1,
|
||||||
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
'LTDL_INIT' => 1,
|
||||||
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
'AC_LIBLTDL_CONVENIENCE' => 1,
|
||||||
'AC_WITH_LTDL' => 1,
|
'_LT_AC_LANG_F77_CONFIG' => 1,
|
||||||
'_LT_AC_LANG_GCJ' => 1,
|
'm4_pattern_forbid' => 1,
|
||||||
'AC_DEFUN_ONCE' => 1,
|
'AC_ENABLE_SHARED' => 1,
|
||||||
|
'AC_LTDL_SYMBOL_USCORE' => 1,
|
||||||
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
'AC_LIBTOOL_POSTDEP_PREDEP' => 1,
|
||||||
'_LT_AC_LANG_C_CONFIG' => 1,
|
'AC_LTDL_SHLIBPATH' => 1,
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
'AC_DISABLE_STATIC' => 1,
|
||||||
'LT_SYS_SYMBOL_USCORE' => 1,
|
'AC_LTDL_ENABLE_INSTALL' => 1,
|
||||||
'AM_SET_LEADING_DOT' => 1,
|
'LT_AC_PROG_GCJ' => 1,
|
||||||
'_LT_COMPILER_OPTION' => 1,
|
'AC_LIBTOOL_SYS_MAX_CMD_LEN' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_OLD_ARCHIVE' => 1,
|
||||||
'_LT_LINKER_OPTION' => 1,
|
'_LT_LINKER_OPTION' => 1,
|
||||||
|
'AM_CONDITIONAL' => 1,
|
||||||
|
'AC_PROG_LD_GNU' => 1,
|
||||||
|
'LT_LANG' => 1,
|
||||||
|
'_LT_AC_FILE_LTDLL_C' => 1,
|
||||||
'_AM_IF_OPTION' => 1,
|
'_AM_IF_OPTION' => 1,
|
||||||
'AC_LIBTOOL_WIN32_DLL' => 1,
|
'LT_INIT' => 1,
|
||||||
'_LT_LIBOBJ' => 1,
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
|
'AC_PATH_MAGIC' => 1,
|
||||||
|
'LTOPTIONS_VERSION' => 1,
|
||||||
|
'_LT_AC_CHECK_DLFCN' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN' => 1,
|
||||||
|
'_LT_PROG_LTMAIN' => 1,
|
||||||
|
'AC_LIBTOOL_PICMODE' => 1,
|
||||||
|
'_LT_AC_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AM_ENABLE_SHARED' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_DYNAMIC_LINKER' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR_TRACE' => 1,
|
||||||
|
'_LT_PROG_FC' => 1,
|
||||||
|
'_LT_LINKER_BOILERPLATE' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ' => 1,
|
||||||
|
'AC_LTDL_DLSYM_USCORE' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_LIB_STRIP' => 1,
|
||||||
|
'AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'LT_LIB_DLLOAD' => 1,
|
||||||
|
'LT_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'LT_AC_PROG_EGREP' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'_AM_SET_OPTION' => 1,
|
||||||
|
'_LT_AC_SYS_COMPILER' => 1,
|
||||||
|
'AC_PROG_NM' => 1,
|
||||||
|
'LTVERSION_VERSION' => 1,
|
||||||
'AC_DEFUN' => 1,
|
'AC_DEFUN' => 1,
|
||||||
'LT_AC_PROG_SED' => 1
|
'AC_WITH_LTDL' => 1,
|
||||||
|
'AC_LIB_LTDL' => 1,
|
||||||
|
'_LT_AC_SYS_LIBPATH_AIX' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'_LT_PROG_F77' => 1,
|
||||||
|
'LT_AC_PROG_SED' => 1,
|
||||||
|
'AC_LIBTOOL_COMPILER_OPTION' => 1,
|
||||||
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
|
'AC_LIBTOOL_DLOPEN_SELF' => 1,
|
||||||
|
'_AM_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LIBTOOL_FC' => 1,
|
||||||
|
'AC_PROG_LD' => 1,
|
||||||
|
'_LT_AC_LANG_CXX' => 1,
|
||||||
|
'AC_LTDL_SYSSEARCHPATH' => 1,
|
||||||
|
'LT_SYS_SYMBOL_USCORE' => 1,
|
||||||
|
'_LT_AC_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'_LT_COMPILER_BOILERPLATE' => 1,
|
||||||
|
'_AM_MANGLE_OPTION' => 1,
|
||||||
|
'AM_PROG_INSTALL_STRIP' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_GCJ_CONFIG' => 1,
|
||||||
|
'_LT_REQUIRED_DARWIN_CHECKS' => 1,
|
||||||
|
'LT_SYS_DLSEARCH_PATH' => 1,
|
||||||
|
'AC_LTDL_OBJDIR' => 1,
|
||||||
|
'AC_LIBTOOL_RC' => 1,
|
||||||
|
'LT_PROG_RC' => 1,
|
||||||
|
'AC_PROG_EGREP' => 1,
|
||||||
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'_LT_AC_LOCK' => 1,
|
||||||
|
'AC_DISABLE_FAST_INSTALL' => 1,
|
||||||
|
'AC_LIBTOOL_CXX' => 1,
|
||||||
|
'_LT_AC_LANG_RC_CONFIG' => 1,
|
||||||
|
'LT_PROG_GCJ' => 1,
|
||||||
|
'AC_LTDL_PREOPEN' => 1,
|
||||||
|
'AM_SANITY_CHECK' => 1,
|
||||||
|
'AC_LIBTOOL_SYS_HARD_LINK_LOCKS' => 1,
|
||||||
|
'_AM_SET_OPTIONS' => 1,
|
||||||
|
'AC_CHECK_LIBM' => 1,
|
||||||
|
'AC_PROG_LD_RELOAD_FLAG' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_NO_RTTI' => 1,
|
||||||
|
'_LT_CC_BASENAME' => 1,
|
||||||
|
'_AM_OUTPUT_DEPENDENCY_COMMANDS' => 1,
|
||||||
|
'AU_DEFUN' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_SHLIBS' => 1,
|
||||||
|
'AM_MISSING_HAS_RUN' => 1,
|
||||||
|
'LT_LIB_M' => 1,
|
||||||
|
'LT_FUNC_DLSYM_USCORE' => 1,
|
||||||
|
'AC_ENABLE_STATIC' => 1,
|
||||||
|
'AM_RUN_LOG' => 1,
|
||||||
|
'AC_CONFIG_MACRO_DIR' => 1,
|
||||||
|
'_m4_warn' => 1,
|
||||||
|
'AM_AUX_DIR_EXPAND' => 1,
|
||||||
|
'_LT_DLL_DEF_P' => 1,
|
||||||
|
'_LT_AC_SHELL_INIT' => 1,
|
||||||
|
'AC_LTDL_SYS_DLOPEN_DEPLIBS' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'LTDL_CONVENIENCE' => 1,
|
||||||
|
'LT_PATH_NM' => 1,
|
||||||
|
'AC_LIBLTDL_INSTALLABLE' => 1,
|
||||||
|
'AC_LIBTOOL_OBJDIR' => 1,
|
||||||
|
'LT_OUTPUT' => 1,
|
||||||
|
'_LT_LIBOBJ' => 1,
|
||||||
|
'LT_SYS_DLOPEN_SELF' => 1,
|
||||||
|
'_AC_AM_CONFIG_HEADER_HOOK' => 1,
|
||||||
|
'AM_MAKE_INCLUDE' => 1,
|
||||||
|
'AM_PROG_INSTALL_SH' => 1,
|
||||||
|
'_AM_AUTOCONF_VERSION' => 1,
|
||||||
|
'_LT_COMPILER_OPTION' => 1,
|
||||||
|
'AM_PROG_LD' => 1,
|
||||||
|
'AM_MISSING_PROG' => 1,
|
||||||
|
'_LT_PROG_CXX' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_COMPILER_PIC' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_C_CONFIG' => 1,
|
||||||
|
'_AM_CONFIG_MACRO_DIRS' => 1,
|
||||||
|
'LT_PROG_GO' => 1,
|
||||||
|
'_LT_PROG_ECHO_BACKSLASH' => 1,
|
||||||
|
'AC_LTDL_DLLIB' => 1,
|
||||||
|
'_AM_PROG_TAR' => 1,
|
||||||
|
'LTOBSOLETE_VERSION' => 1,
|
||||||
|
'_LT_AC_TAGVAR' => 1,
|
||||||
|
'LT_PATH_LD' => 1,
|
||||||
|
'AM_DISABLE_SHARED' => 1,
|
||||||
|
'_AM_DEPENDENCIES' => 1,
|
||||||
|
'LT_WITH_LTDL' => 1,
|
||||||
|
'AC_DEFUN_ONCE' => 1,
|
||||||
|
'LTSUGAR_VERSION' => 1,
|
||||||
|
'AC_LIBTOOL_GCJ' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AC_LIBTOOL_F77' => 1,
|
||||||
|
'AM_SET_LEADING_DOT' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_CC_C_O' => 1,
|
||||||
|
'AC_LTDL_SHLIBEXT' => 1,
|
||||||
|
'LT_FUNC_ARGZ' => 1,
|
||||||
|
'_LTDL_SETUP' => 1,
|
||||||
|
'_LT_AC_LANG_CXX_CONFIG' => 1,
|
||||||
|
'AC_ENABLE_FAST_INSTALL' => 1,
|
||||||
|
'AC_DISABLE_SHARED' => 1,
|
||||||
|
'AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH' => 1,
|
||||||
|
'_AC_PROG_LIBTOOL' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'_LT_AC_TRY_DLOPEN_SELF' => 1,
|
||||||
|
'AC_LIBTOOL_SETUP' => 1,
|
||||||
|
'AM_ENABLE_STATIC' => 1,
|
||||||
|
'AC_LIBTOOL_LANG_RC_CONFIG' => 1,
|
||||||
|
'AM_SUBST_NOTMAKE' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'AM_PROG_LIBTOOL' => 1,
|
||||||
|
'include' => 1,
|
||||||
|
'_LT_AC_LANG_F77' => 1,
|
||||||
|
'LT_SYS_MODULE_EXT' => 1,
|
||||||
|
'LT_CMD_MAX_LEN' => 1,
|
||||||
|
'AM_SET_DEPDIR' => 1,
|
||||||
|
'AC_LIBTOOL_WIN32_DLL' => 1,
|
||||||
|
'_LT_AC_LANG_C_CONFIG' => 1,
|
||||||
|
'_LT_WITH_SYSROOT' => 1,
|
||||||
|
'AM_DEP_TRACK' => 1,
|
||||||
|
'AC_PATH_TOOL_PREFIX' => 1,
|
||||||
|
'LTDL_INSTALLABLE' => 1,
|
||||||
|
'AC_LIBTOOL_LINKER_OPTION' => 1,
|
||||||
|
'AC_DEPLIBS_CHECK_METHOD' => 1,
|
||||||
|
'AC_LIBTOOL_CONFIG' => 1,
|
||||||
|
'AM_SET_CURRENT_AUTOMAKE_VERSION' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' ),
|
], 'Autom4te::Request' ),
|
||||||
bless( [
|
bless( [
|
||||||
@ -457,65 +457,65 @@
|
|||||||
'configure.ac'
|
'configure.ac'
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
'_AM_COND_IF' => 1,
|
|
||||||
'AM_PROG_AR' => 1,
|
|
||||||
'AC_CONFIG_HEADERS' => 1,
|
|
||||||
'AC_SUBST_TRACE' => 1,
|
|
||||||
'AM_INIT_AUTOMAKE' => 1,
|
|
||||||
'AM_POT_TOOLS' => 1,
|
|
||||||
'AM_PROG_CXX_C_O' => 1,
|
|
||||||
'm4_pattern_allow' => 1,
|
|
||||||
'AC_FC_SRCEXT' => 1,
|
|
||||||
'AC_CONFIG_SUBDIRS' => 1,
|
|
||||||
'AC_REQUIRE_AUX_FILE' => 1,
|
|
||||||
'AM_ENABLE_MULTILIB' => 1,
|
|
||||||
'LT_INIT' => 1,
|
|
||||||
'AM_GNU_GETTEXT' => 1,
|
|
||||||
'_AM_COND_ELSE' => 1,
|
|
||||||
'LT_CONFIG_LTDL_DIR' => 1,
|
|
||||||
'AC_CANONICAL_HOST' => 1,
|
|
||||||
'AC_CANONICAL_BUILD' => 1,
|
|
||||||
'm4_pattern_forbid' => 1,
|
|
||||||
'AM_PROG_MKDIR_P' => 1,
|
|
||||||
'_AM_COND_ENDIF' => 1,
|
|
||||||
'_AM_MAKEFILE_INCLUDE' => 1,
|
|
||||||
'LT_SUPPORTED_TAG' => 1,
|
|
||||||
'AM_PROG_CC_C_O' => 1,
|
|
||||||
'm4_sinclude' => 1,
|
|
||||||
'AM_PROG_FC_C_O' => 1,
|
|
||||||
'AM_PROG_F77_C_O' => 1,
|
|
||||||
'AC_PROG_LIBTOOL' => 1,
|
|
||||||
'AC_FC_PP_DEFINE' => 1,
|
|
||||||
'AH_OUTPUT' => 1,
|
|
||||||
'AC_SUBST' => 1,
|
|
||||||
'_AM_SUBST_NOTMAKE' => 1,
|
|
||||||
'AM_PROG_MOC' => 1,
|
|
||||||
'AC_CANONICAL_TARGET' => 1,
|
|
||||||
'_m4_warn' => 1,
|
|
||||||
'AM_MAINTAINER_MODE' => 1,
|
|
||||||
'AM_MAKEFILE_INCLUDE' => 1,
|
'AM_MAKEFILE_INCLUDE' => 1,
|
||||||
'AC_CANONICAL_SYSTEM' => 1,
|
|
||||||
'AM_CONDITIONAL' => 1,
|
'AM_CONDITIONAL' => 1,
|
||||||
'AM_NLS' => 1,
|
'AM_GNU_GETTEXT' => 1,
|
||||||
'AM_PATH_GUILE' => 1,
|
'include' => 1,
|
||||||
'm4_include' => 1,
|
'AC_CONFIG_HEADERS' => 1,
|
||||||
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
|
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
||||||
'AC_CONFIG_LINKS' => 1,
|
'_AM_COND_ENDIF' => 1,
|
||||||
|
'AC_DEFINE_TRACE_LITERAL' => 1,
|
||||||
|
'AM_PROG_AR' => 1,
|
||||||
|
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
||||||
|
'LT_CONFIG_LTDL_DIR' => 1,
|
||||||
|
'AC_CONFIG_AUX_DIR' => 1,
|
||||||
|
'AM_AUTOMAKE_VERSION' => 1,
|
||||||
|
'AM_POT_TOOLS' => 1,
|
||||||
|
'AM_PROG_FC_C_O' => 1,
|
||||||
|
'AH_OUTPUT' => 1,
|
||||||
|
'AM_ENABLE_MULTILIB' => 1,
|
||||||
|
'AC_SUBST_TRACE' => 1,
|
||||||
'_LT_AC_TAGCONFIG' => 1,
|
'_LT_AC_TAGCONFIG' => 1,
|
||||||
'AC_FC_FREEFORM' => 1,
|
'AC_FC_FREEFORM' => 1,
|
||||||
'AC_CONFIG_AUX_DIR' => 1,
|
'AM_PROG_MOC' => 1,
|
||||||
'AM_SILENT_RULES' => 1,
|
'AC_CANONICAL_SYSTEM' => 1,
|
||||||
'sinclude' => 1,
|
'sinclude' => 1,
|
||||||
'AM_XGETTEXT_OPTION' => 1,
|
'AC_PROG_LIBTOOL' => 1,
|
||||||
|
'LT_INIT' => 1,
|
||||||
|
'AM_NLS' => 1,
|
||||||
|
'm4_include' => 1,
|
||||||
|
'AM_PROG_CC_C_O' => 1,
|
||||||
|
'AM_PROG_CXX_C_O' => 1,
|
||||||
|
'_AM_MAKEFILE_INCLUDE' => 1,
|
||||||
|
'AM_INIT_AUTOMAKE' => 1,
|
||||||
|
'AC_LIBSOURCE' => 1,
|
||||||
|
'_AM_COND_ELSE' => 1,
|
||||||
|
'AM_SILENT_RULES' => 1,
|
||||||
|
'AC_CONFIG_LINKS' => 1,
|
||||||
|
'AM_EXTRA_RECURSIVE_TARGETS' => 1,
|
||||||
|
'AC_CONFIG_SUBDIRS' => 1,
|
||||||
'AC_INIT' => 1,
|
'AC_INIT' => 1,
|
||||||
'AC_FC_PP_SRCEXT' => 1,
|
'AC_CANONICAL_HOST' => 1,
|
||||||
|
'AC_REQUIRE_AUX_FILE' => 1,
|
||||||
|
'AM_XGETTEXT_OPTION' => 1,
|
||||||
|
'AC_CANONICAL_TARGET' => 1,
|
||||||
|
'AM_PROG_MKDIR_P' => 1,
|
||||||
|
'AC_FC_SRCEXT' => 1,
|
||||||
|
'm4_sinclude' => 1,
|
||||||
|
'm4_pattern_forbid' => 1,
|
||||||
|
'm4_pattern_allow' => 1,
|
||||||
|
'AC_CANONICAL_BUILD' => 1,
|
||||||
'AC_CONFIG_FILES' => 1,
|
'AC_CONFIG_FILES' => 1,
|
||||||
'AM_GNU_GETTEXT_INTL_SUBDIR' => 1,
|
'AM_PROG_F77_C_O' => 1,
|
||||||
'include' => 1,
|
'AC_FC_PP_SRCEXT' => 1,
|
||||||
'AC_CONFIG_LIBOBJ_DIR' => 1,
|
'_m4_warn' => 1,
|
||||||
'AC_DEFINE_TRACE_LITERAL' => 1,
|
'AM_MAINTAINER_MODE' => 1,
|
||||||
'AM_AUTOMAKE_VERSION' => 1,
|
'AM_PATH_GUILE' => 1,
|
||||||
'AC_LIBSOURCE' => 1
|
'LT_SUPPORTED_TAG' => 1,
|
||||||
|
'AC_SUBST' => 1,
|
||||||
|
'AC_FC_PP_DEFINE' => 1,
|
||||||
|
'_AM_COND_IF' => 1,
|
||||||
|
'_AM_SUBST_NOTMAKE' => 1
|
||||||
}
|
}
|
||||||
], 'Autom4te::Request' )
|
], 'Autom4te::Request' )
|
||||||
);
|
);
|
||||||
|
|||||||
@ -2729,29 +2729,29 @@ m4trace:configure.ac:130: -1- m4_pattern_allow([^HAVE_LIBREADLINE$])
|
|||||||
m4trace:configure.ac:136: -1- m4_pattern_allow([^HAVE_SELINUX_SELINUX_H$])
|
m4trace:configure.ac:136: -1- m4_pattern_allow([^HAVE_SELINUX_SELINUX_H$])
|
||||||
m4trace:configure.ac:137: -1- m4_pattern_allow([^HAVE_LIBSELINUX$])
|
m4trace:configure.ac:137: -1- m4_pattern_allow([^HAVE_LIBSELINUX$])
|
||||||
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
||||||
m4trace:configure.ac:159: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
m4trace:configure.ac:161: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^uid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^uid_t$])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^gid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^gid_t$])
|
||||||
m4trace:configure.ac:196: -1- m4_pattern_allow([^pid_t$])
|
m4trace:configure.ac:198: -1- m4_pattern_allow([^pid_t$])
|
||||||
m4trace:configure.ac:197: -1- m4_pattern_allow([^size_t$])
|
m4trace:configure.ac:199: -1- m4_pattern_allow([^size_t$])
|
||||||
m4trace:configure.ac:198: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
m4trace:configure.ac:200: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
||||||
m4trace:configure.ac:202: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:204: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^vfork$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^vfork$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
||||||
m4trace:configure.ac:233: -1- m4_pattern_allow([^DEBUG$])
|
m4trace:configure.ac:236: -1- m4_pattern_allow([^DEBUG$])
|
||||||
m4trace:configure.ac:247: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:250: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:248: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:251: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:249: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:252: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:250: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:253: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:261: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:264: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:261: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
m4trace:configure.ac:264: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
||||||
m4trace:configure.ac:261: -1- _LT_PROG_LTMAIN
|
m4trace:configure.ac:264: -1- _LT_PROG_LTMAIN
|
||||||
m4trace:configure.ac:261: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
m4trace:configure.ac:264: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
||||||
|
|||||||
@ -2729,29 +2729,29 @@ m4trace:configure.ac:130: -1- m4_pattern_allow([^HAVE_LIBREADLINE$])
|
|||||||
m4trace:configure.ac:136: -1- m4_pattern_allow([^HAVE_SELINUX_SELINUX_H$])
|
m4trace:configure.ac:136: -1- m4_pattern_allow([^HAVE_SELINUX_SELINUX_H$])
|
||||||
m4trace:configure.ac:137: -1- m4_pattern_allow([^HAVE_LIBSELINUX$])
|
m4trace:configure.ac:137: -1- m4_pattern_allow([^HAVE_LIBSELINUX$])
|
||||||
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
||||||
m4trace:configure.ac:159: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
m4trace:configure.ac:161: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^uid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^uid_t$])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^gid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^gid_t$])
|
||||||
m4trace:configure.ac:196: -1- m4_pattern_allow([^pid_t$])
|
m4trace:configure.ac:198: -1- m4_pattern_allow([^pid_t$])
|
||||||
m4trace:configure.ac:197: -1- m4_pattern_allow([^size_t$])
|
m4trace:configure.ac:199: -1- m4_pattern_allow([^size_t$])
|
||||||
m4trace:configure.ac:198: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
m4trace:configure.ac:200: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
||||||
m4trace:configure.ac:202: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:204: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^vfork$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^vfork$])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
||||||
m4trace:configure.ac:233: -1- m4_pattern_allow([^DEBUG$])
|
m4trace:configure.ac:236: -1- m4_pattern_allow([^DEBUG$])
|
||||||
m4trace:configure.ac:247: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:250: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:248: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:251: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:249: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:252: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:250: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:253: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:261: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:264: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:261: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
m4trace:configure.ac:264: -1- _AC_AM_CONFIG_HEADER_HOOK(["$ac_file"])
|
||||||
m4trace:configure.ac:261: -1- _LT_PROG_LTMAIN
|
m4trace:configure.ac:264: -1- _LT_PROG_LTMAIN
|
||||||
m4trace:configure.ac:261: -1- _AM_OUTPUT_DEPENDENCY_COMMANDS
|
m4trace:configure.ac:264: -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], [0.1], [stefani@seibold.net])
|
m4trace:configure.ac:27: -1- AC_INIT([mtrace], [0.2], [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'])
|
||||||
@ -559,122 +559,124 @@ m4trace:configure.ac:146: -1- AC_DEFINE_TRACE_LITERAL([HAVE_ELF_C_READ_MMAP])
|
|||||||
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
m4trace:configure.ac:146: -1- m4_pattern_allow([^HAVE_ELF_C_READ_MMAP$])
|
||||||
m4trace:configure.ac:146: -1- AH_OUTPUT([HAVE_ELF_C_READ_MMAP], [/* we have read mmap support */
|
m4trace:configure.ac:146: -1- AH_OUTPUT([HAVE_ELF_C_READ_MMAP], [/* we have read mmap support */
|
||||||
@%:@undef HAVE_ELF_C_READ_MMAP])
|
@%:@undef HAVE_ELF_C_READ_MMAP])
|
||||||
m4trace:configure.ac:159: -1- AC_DEFINE_TRACE_LITERAL([ELF_HASH_TAKES_CHARP])
|
m4trace:configure.ac:161: -1- AC_DEFINE_TRACE_LITERAL([ELF_HASH_TAKES_CHARP])
|
||||||
m4trace:configure.ac:159: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
m4trace:configure.ac:161: -1- m4_pattern_allow([^ELF_HASH_TAKES_CHARP$])
|
||||||
m4trace:configure.ac:159: -1- AH_OUTPUT([ELF_HASH_TAKES_CHARP], [/* elf_hash() takes char* (as opposed to unsigned char *) */
|
m4trace:configure.ac:161: -1- AH_OUTPUT([ELF_HASH_TAKES_CHARP], [/* elf_hash() takes char* (as opposed to unsigned char *) */
|
||||||
@%:@undef ELF_HASH_TAKES_CHARP])
|
@%:@undef ELF_HASH_TAKES_CHARP])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_FCNTL_H], [/* Define to 1 if you have the <fcntl.h> header file. */
|
||||||
@%:@undef HAVE_FCNTL_H])
|
@%:@undef HAVE_FCNTL_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_LIMITS_H], [/* Define to 1 if you have the <limits.h> header file. */
|
||||||
@%:@undef HAVE_LIMITS_H])
|
@%:@undef HAVE_LIMITS_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_STDDEF_H], [/* Define to 1 if you have the <stddef.h> header file. */
|
||||||
@%:@undef HAVE_STDDEF_H])
|
@%:@undef HAVE_STDDEF_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_STDINT_H], [/* Define to 1 if you have the <stdint.h> header file. */
|
||||||
@%:@undef HAVE_STDINT_H])
|
@%:@undef HAVE_STDINT_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_STDLIB_H], [/* Define to 1 if you have the <stdlib.h> header file. */
|
||||||
@%:@undef HAVE_STDLIB_H])
|
@%:@undef HAVE_STDLIB_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_STRING_H], [/* Define to 1 if you have the <string.h> header file. */
|
||||||
@%:@undef HAVE_STRING_H])
|
@%:@undef HAVE_STRING_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_IOCTL_H], [/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_SYS_IOCTL_H], [/* Define to 1 if you have the <sys/ioctl.h> header file. */
|
||||||
@%:@undef HAVE_SYS_IOCTL_H])
|
@%:@undef HAVE_SYS_IOCTL_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_SYS_PARAM_H], [/* Define to 1 if you have the <sys/param.h> header file. */
|
||||||
@%:@undef HAVE_SYS_PARAM_H])
|
@%:@undef HAVE_SYS_PARAM_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_SYS_TIME_H], [/* Define to 1 if you have the <sys/time.h> header file. */
|
||||||
@%:@undef HAVE_SYS_TIME_H])
|
@%:@undef HAVE_SYS_TIME_H])
|
||||||
m4trace:configure.ac:180: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
|
m4trace:configure.ac:182: -1- AH_OUTPUT([HAVE_UNISTD_H], [/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
@%:@undef HAVE_UNISTD_H])
|
@%:@undef HAVE_UNISTD_H])
|
||||||
m4trace:configure.ac:194: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
|
m4trace:configure.ac:196: -1- AC_DEFINE_TRACE_LITERAL([uid_t])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^uid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^uid_t$])
|
||||||
m4trace:configure.ac:194: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
|
m4trace:configure.ac:196: -1- AH_OUTPUT([uid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
|
||||||
@%:@undef uid_t])
|
@%:@undef uid_t])
|
||||||
m4trace:configure.ac:194: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
|
m4trace:configure.ac:196: -1- AC_DEFINE_TRACE_LITERAL([gid_t])
|
||||||
m4trace:configure.ac:194: -1- m4_pattern_allow([^gid_t$])
|
m4trace:configure.ac:196: -1- m4_pattern_allow([^gid_t$])
|
||||||
m4trace:configure.ac:194: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
|
m4trace:configure.ac:196: -1- AH_OUTPUT([gid_t], [/* Define to `int\' if <sys/types.h> doesn\'t define. */
|
||||||
@%:@undef gid_t])
|
@%:@undef gid_t])
|
||||||
m4trace:configure.ac:195: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
|
m4trace:configure.ac:197: -1- AH_OUTPUT([inline], [/* Define to `__inline__\' or `__inline\' if that\'s what the C compiler
|
||||||
calls it, or to nothing if \'inline\' is not supported under any name. */
|
calls it, or to nothing if \'inline\' is not supported under any name. */
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
#undef inline
|
#undef inline
|
||||||
#endif])
|
#endif])
|
||||||
m4trace:configure.ac:196: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
|
m4trace:configure.ac:198: -1- AC_DEFINE_TRACE_LITERAL([pid_t])
|
||||||
m4trace:configure.ac:196: -1- m4_pattern_allow([^pid_t$])
|
m4trace:configure.ac:198: -1- m4_pattern_allow([^pid_t$])
|
||||||
m4trace:configure.ac:196: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
|
m4trace:configure.ac:198: -1- AH_OUTPUT([pid_t], [/* Define to `int\' if <sys/types.h> does not define. */
|
||||||
@%:@undef pid_t])
|
@%:@undef pid_t])
|
||||||
m4trace:configure.ac:197: -1- AC_DEFINE_TRACE_LITERAL([size_t])
|
m4trace:configure.ac:199: -1- AC_DEFINE_TRACE_LITERAL([size_t])
|
||||||
m4trace:configure.ac:197: -1- m4_pattern_allow([^size_t$])
|
m4trace:configure.ac:199: -1- m4_pattern_allow([^size_t$])
|
||||||
m4trace:configure.ac:197: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
|
m4trace:configure.ac:199: -1- AH_OUTPUT([size_t], [/* Define to `unsigned int\' if <sys/types.h> does not define. */
|
||||||
@%:@undef size_t])
|
@%:@undef size_t])
|
||||||
m4trace:configure.ac:198: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG])
|
m4trace:configure.ac:200: -1- AC_DEFINE_TRACE_LITERAL([SIZEOF_LONG])
|
||||||
m4trace:configure.ac:198: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
m4trace:configure.ac:200: -1- m4_pattern_allow([^SIZEOF_LONG$])
|
||||||
m4trace:configure.ac:198: -1- AH_OUTPUT([SIZEOF_LONG], [/* The size of `long\', as computed by sizeof. */
|
m4trace:configure.ac:200: -1- AH_OUTPUT([SIZEOF_LONG], [/* The size of `long\', as computed by sizeof. */
|
||||||
@%:@undef SIZEOF_LONG])
|
@%:@undef SIZEOF_LONG])
|
||||||
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.h])
|
m4trace:configure.ac:204: -1- AC_LIBSOURCE([error.h])
|
||||||
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.c])
|
m4trace:configure.ac:204: -1- AC_LIBSOURCE([error.c])
|
||||||
m4trace:configure.ac:202: -1- AC_SUBST([LIB@&t@OBJS], ["$LIB@&t@OBJS error.$ac_objext"])
|
m4trace:configure.ac:204: -1- AC_SUBST([LIB@&t@OBJS], ["$LIB@&t@OBJS error.$ac_objext"])
|
||||||
m4trace:configure.ac:202: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
m4trace:configure.ac:204: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
||||||
m4trace:configure.ac:202: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:204: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:202: -1- AC_LIBSOURCE([error.c])
|
m4trace:configure.ac:204: -1- AC_LIBSOURCE([error.c])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_VFORK_H], [/* Define to 1 if you have the <vfork.h> header file. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([HAVE_VFORK_H], [/* Define to 1 if you have the <vfork.h> header file. */
|
||||||
@%:@undef HAVE_VFORK_H])
|
@%:@undef HAVE_VFORK_H])
|
||||||
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VFORK_H])
|
m4trace:configure.ac:205: -1- AC_DEFINE_TRACE_LITERAL([HAVE_VFORK_H])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_VFORK_H$])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_FORK], [/* Define to 1 if you have the `fork\' function. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([HAVE_FORK], [/* Define to 1 if you have the `fork\' function. */
|
||||||
@%:@undef HAVE_FORK])
|
@%:@undef HAVE_FORK])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_VFORK], [/* Define to 1 if you have the `vfork\' function. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([HAVE_VFORK], [/* Define to 1 if you have the `vfork\' function. */
|
||||||
@%:@undef HAVE_VFORK])
|
@%:@undef HAVE_VFORK])
|
||||||
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_VFORK])
|
m4trace:configure.ac:205: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_VFORK])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_VFORK$])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_WORKING_VFORK], [/* Define to 1 if `vfork\' works. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([HAVE_WORKING_VFORK], [/* Define to 1 if `vfork\' works. */
|
||||||
@%:@undef HAVE_WORKING_VFORK])
|
@%:@undef HAVE_WORKING_VFORK])
|
||||||
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([vfork])
|
m4trace:configure.ac:205: -1- AC_DEFINE_TRACE_LITERAL([vfork])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^vfork$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^vfork$])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([vfork], [/* Define as `fork\' if `vfork\' does not work. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([vfork], [/* Define as `fork\' if `vfork\' does not work. */
|
||||||
@%:@undef vfork])
|
@%:@undef vfork])
|
||||||
m4trace:configure.ac:203: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_FORK])
|
m4trace:configure.ac:205: -1- AC_DEFINE_TRACE_LITERAL([HAVE_WORKING_FORK])
|
||||||
m4trace:configure.ac:203: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
m4trace:configure.ac:205: -1- m4_pattern_allow([^HAVE_WORKING_FORK$])
|
||||||
m4trace:configure.ac:203: -1- AH_OUTPUT([HAVE_WORKING_FORK], [/* Define to 1 if `fork\' works. */
|
m4trace:configure.ac:205: -1- AH_OUTPUT([HAVE_WORKING_FORK], [/* Define to 1 if `fork\' works. */
|
||||||
@%:@undef HAVE_WORKING_FORK])
|
@%:@undef HAVE_WORKING_FORK])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_ALARM], [/* Define to 1 if you have the `alarm\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_ALARM], [/* Define to 1 if you have the `alarm\' function. */
|
||||||
@%:@undef HAVE_ALARM])
|
@%:@undef HAVE_ALARM])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_ATEXIT], [/* Define to 1 if you have the `atexit\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_ATEXIT], [/* Define to 1 if you have the `atexit\' function. */
|
||||||
@%:@undef HAVE_ATEXIT])
|
@%:@undef HAVE_ATEXIT])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_GETCWD], [/* Define to 1 if you have the `getcwd\' function. */
|
||||||
@%:@undef HAVE_GETCWD])
|
@%:@undef HAVE_GETCWD])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_GETTIMEOFDAY], [/* Define to 1 if you have the `gettimeofday\' function. */
|
||||||
@%:@undef HAVE_GETTIMEOFDAY])
|
@%:@undef HAVE_GETTIMEOFDAY])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_MEMSET], [/* Define to 1 if you have the `memset\' function. */
|
||||||
@%:@undef HAVE_MEMSET])
|
@%:@undef HAVE_MEMSET])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_MKDIR], [/* Define to 1 if you have the `mkdir\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_MKDIR], [/* Define to 1 if you have the `mkdir\' function. */
|
||||||
@%:@undef HAVE_MKDIR])
|
@%:@undef HAVE_MKDIR])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_RMDIR], [/* Define to 1 if you have the `rmdir\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_RMDIR], [/* Define to 1 if you have the `rmdir\' function. */
|
||||||
@%:@undef HAVE_RMDIR])
|
@%:@undef HAVE_RMDIR])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRCHR], [/* Define to 1 if you have the `strchr\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_STRCHR], [/* Define to 1 if you have the `strchr\' function. */
|
||||||
@%:@undef HAVE_STRCHR])
|
@%:@undef HAVE_STRCHR])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_STRDUP], [/* Define to 1 if you have the `strdup\' function. */
|
||||||
@%:@undef HAVE_STRDUP])
|
@%:@undef HAVE_STRDUP])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRERROR], [/* Define to 1 if you have the `strerror\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_STRERROR], [/* Define to 1 if you have the `strerror\' function. */
|
||||||
@%:@undef HAVE_STRERROR])
|
@%:@undef HAVE_STRERROR])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRTOL], [/* Define to 1 if you have the `strtol\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_STRTOL], [/* Define to 1 if you have the `strtol\' function. */
|
||||||
@%:@undef HAVE_STRTOL])
|
@%:@undef HAVE_STRTOL])
|
||||||
m4trace:configure.ac:204: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_STRTOUL], [/* Define to 1 if you have the `strtoul\' function. */
|
||||||
@%:@undef HAVE_STRTOUL])
|
@%:@undef HAVE_STRTOUL])
|
||||||
m4trace:configure.ac:233: -1- AC_DEFINE_TRACE_LITERAL([DEBUG])
|
m4trace:configure.ac:206: -1- AH_OUTPUT([HAVE_PROCESS_VM_READV], [/* Define to 1 if you have the `process_vm_readv\' function. */
|
||||||
m4trace:configure.ac:233: -1- m4_pattern_allow([^DEBUG$])
|
@%:@undef HAVE_PROCESS_VM_READV])
|
||||||
m4trace:configure.ac:233: -1- AH_OUTPUT([DEBUG], [/* debugging */
|
m4trace:configure.ac:236: -1- AC_DEFINE_TRACE_LITERAL([DEBUG])
|
||||||
|
m4trace:configure.ac:236: -1- m4_pattern_allow([^DEBUG$])
|
||||||
|
m4trace:configure.ac:236: -1- AH_OUTPUT([DEBUG], [/* debugging */
|
||||||
@%:@undef DEBUG])
|
@%:@undef DEBUG])
|
||||||
m4trace:configure.ac:247: -1- AC_SUBST([AM_CPPFLAGS])
|
m4trace:configure.ac:250: -1- AC_SUBST([AM_CPPFLAGS])
|
||||||
m4trace:configure.ac:247: -1- AC_SUBST_TRACE([AM_CPPFLAGS])
|
m4trace:configure.ac:250: -1- AC_SUBST_TRACE([AM_CPPFLAGS])
|
||||||
m4trace:configure.ac:247: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
m4trace:configure.ac:250: -1- m4_pattern_allow([^AM_CPPFLAGS$])
|
||||||
m4trace:configure.ac:248: -1- AC_SUBST([AM_CFLAGS])
|
m4trace:configure.ac:251: -1- AC_SUBST([AM_CFLAGS])
|
||||||
m4trace:configure.ac:248: -1- AC_SUBST_TRACE([AM_CFLAGS])
|
m4trace:configure.ac:251: -1- AC_SUBST_TRACE([AM_CFLAGS])
|
||||||
m4trace:configure.ac:248: -1- m4_pattern_allow([^AM_CFLAGS$])
|
m4trace:configure.ac:251: -1- m4_pattern_allow([^AM_CFLAGS$])
|
||||||
m4trace:configure.ac:249: -1- AC_SUBST([AM_LDFLAGS])
|
m4trace:configure.ac:252: -1- AC_SUBST([AM_LDFLAGS])
|
||||||
m4trace:configure.ac:249: -1- AC_SUBST_TRACE([AM_LDFLAGS])
|
m4trace:configure.ac:252: -1- AC_SUBST_TRACE([AM_LDFLAGS])
|
||||||
m4trace:configure.ac:249: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
m4trace:configure.ac:252: -1- m4_pattern_allow([^AM_LDFLAGS$])
|
||||||
m4trace:configure.ac:250: -1- AC_SUBST([libelf_LD_LIBRARY_PATH])
|
m4trace:configure.ac:253: -1- AC_SUBST([libelf_LD_LIBRARY_PATH])
|
||||||
m4trace:configure.ac:250: -1- AC_SUBST_TRACE([libelf_LD_LIBRARY_PATH])
|
m4trace:configure.ac:253: -1- AC_SUBST_TRACE([libelf_LD_LIBRARY_PATH])
|
||||||
m4trace:configure.ac:250: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
m4trace:configure.ac:253: -1- m4_pattern_allow([^libelf_LD_LIBRARY_PATH$])
|
||||||
m4trace:configure.ac:252: -1- AC_CONFIG_FILES([
|
m4trace:configure.ac:255: -1- AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
client/Makefile
|
client/Makefile
|
||||||
sysdeps/Makefile
|
sysdeps/Makefile
|
||||||
@ -683,30 +685,30 @@ m4trace:configure.ac:252: -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:261: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
|
m4trace:configure.ac:264: -1- AC_SUBST([LIB@&t@OBJS], [$ac_libobjs])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([LIB@&t@OBJS])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LIB@&t@OBJS$])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
|
m4trace:configure.ac:264: -1- AC_SUBST([LTLIBOBJS], [$ac_ltlibobjs])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([LTLIBOBJS])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([LTLIBOBJS])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^LTLIBOBJS$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^LTLIBOBJS$])
|
||||||
m4trace:configure.ac:261: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
m4trace:configure.ac:264: -1- AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST([am__EXEEXT_TRUE])
|
m4trace:configure.ac:264: -1- AC_SUBST([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_TRUE$])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST([am__EXEEXT_FALSE])
|
m4trace:configure.ac:264: -1- AC_SUBST([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:261: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
m4trace:configure.ac:264: -1- m4_pattern_allow([^am__EXEEXT_FALSE$])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_TRUE])
|
||||||
m4trace:configure.ac:261: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
m4trace:configure.ac:264: -1- _AM_SUBST_NOTMAKE([am__EXEEXT_FALSE])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_builddir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([top_builddir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_build_prefix])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([top_build_prefix])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([srcdir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([srcdir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_srcdir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([abs_srcdir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([top_srcdir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([top_srcdir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_top_srcdir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([abs_top_srcdir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([builddir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([builddir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_builddir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([abs_builddir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([abs_top_builddir])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([abs_top_builddir])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([INSTALL])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([INSTALL])
|
||||||
m4trace:configure.ac:261: -1- AC_SUBST_TRACE([MKDIR_P])
|
m4trace:configure.ac:264: -1- AC_SUBST_TRACE([MKDIR_P])
|
||||||
m4trace:configure.ac:261: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
|
m4trace:configure.ac:264: -1- AC_REQUIRE_AUX_FILE([ltmain.sh])
|
||||||
|
|||||||
@ -84,6 +84,10 @@ int handle_singlestep(struct task *task, int (*singlestep)(struct task *task));
|
|||||||
* function returns. */
|
* function returns. */
|
||||||
arch_addr_t get_return_addr(struct task *task);
|
arch_addr_t get_return_addr(struct task *task);
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 0
|
||||||
|
/* returns true if the hw breakpoint is pendig */
|
||||||
|
int get_hw_bp_state(struct task *task, unsigned int n);
|
||||||
|
|
||||||
/* set instruction hw breakpoint */
|
/* set instruction hw breakpoint */
|
||||||
int set_hw_bp(struct task *task, unsigned int n, arch_addr_t addr);
|
int set_hw_bp(struct task *task, unsigned int n, arch_addr_t addr);
|
||||||
|
|
||||||
@ -92,6 +96,7 @@ int reset_hw_bp(struct task *task, unsigned int n);
|
|||||||
|
|
||||||
/* remove all instruction hw breakpoints */
|
/* remove all instruction hw breakpoints */
|
||||||
int reset_all_hw_bp(struct task *task);
|
int reset_all_hw_bp(struct task *task);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* save the process context (state, registers, stack pointer) */
|
/* save the process context (state, registers, stack pointer) */
|
||||||
int fetch_context(struct task *task);
|
int fetch_context(struct task *task);
|
||||||
|
|||||||
@ -40,5 +40,8 @@ unsigned long backtrace_get_ip(struct task *task);
|
|||||||
/* step to next backtrace given task */
|
/* step to next backtrace given task */
|
||||||
int backtrace_step(struct task *task);
|
int backtrace_step(struct task *task);
|
||||||
|
|
||||||
|
/* get backtrace location type of given task */
|
||||||
|
int backtrace_location_type(struct task *task);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
399
breakpoint.c
399
breakpoint.c
@ -34,6 +34,7 @@
|
|||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "mtelf.h"
|
#include "mtelf.h"
|
||||||
|
#include "options.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
@ -98,54 +99,19 @@ struct breakpoint *breakpoint_find(struct task *task, arch_addr_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
#if HW_BREAKPOINTS > 1
|
|
||||||
static int find_hw_bp_slot(struct task *leader)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i)
|
|
||||||
if ((leader->hw_bp_mask & (1 << i)) == 0)
|
|
||||||
return i;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void enable_hw_bp(struct task *task, struct breakpoint *bp)
|
static void enable_hw_bp(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
unsigned int slot = bp->hw_bp_slot;
|
unsigned int slot = bp->hw_bp_slot;
|
||||||
|
|
||||||
if (bp->hw_bp_slot != HW_BP_SCRATCH_SLOT)
|
assert(bp->type != BP_SW);
|
||||||
assert(task->hw_bp[slot] == NULL);
|
assert(bp->type < BP_HW || task->hw_bp[slot] == NULL);
|
||||||
|
|
||||||
task->hw_bp[slot] = bp;
|
task->hw_bp[slot] = bp;
|
||||||
|
|
||||||
if (set_hw_bp(task, slot, bp->addr) == -1)
|
if (set_hw_bp(task, slot, bp->addr) == -1)
|
||||||
fatal("set_hw_bp");
|
fatal("set_hw_bp");
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_hw_clone(struct task *task)
|
|
||||||
{
|
|
||||||
unsigned int i;
|
|
||||||
struct task *leader = task->leader;
|
|
||||||
|
|
||||||
if (leader == task)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i) {
|
|
||||||
if ((leader->hw_bp_mask & (1 << i)) == 0) {
|
|
||||||
assert(task->hw_bp[i] == NULL);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (leader->hw_bp[i]) {
|
|
||||||
assert(leader->hw_bp[i]->enabled);
|
|
||||||
assert(leader->hw_bp[i]->hw_bp_slot == i);
|
|
||||||
|
|
||||||
enable_hw_bp(task, leader->hw_bp[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disable_hw_bp(struct task *task, struct breakpoint *bp)
|
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;
|
||||||
@ -155,33 +121,175 @@ static void disable_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
assert(task->hw_bp[slot] == bp);
|
assert(task->hw_bp[slot] == bp);
|
||||||
|
|
||||||
task->hw_bp[slot] = NULL;
|
|
||||||
|
|
||||||
if (reset_hw_bp(task, slot) == -1)
|
if (reset_hw_bp(task, slot) == -1)
|
||||||
fatal("reset_hw_bp");
|
fatal("reset_hw_bp");
|
||||||
|
|
||||||
|
task->hw_bp[slot] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
static void enable_hw_bp_cb(struct task *task, void *data)
|
||||||
|
{
|
||||||
|
enable_hw_bp(task, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void disable_hw_bp_cb(struct task *task, void *data)
|
||||||
|
{
|
||||||
|
disable_hw_bp(task, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hw2sw_bp(struct task *leader, struct breakpoint *bp)
|
||||||
|
{
|
||||||
|
each_task(leader, disable_hw_bp_cb, bp);
|
||||||
|
bp->hw = 0;
|
||||||
|
enable_sw_breakpoint(leader, bp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hw_bp_sort(const void *a, const void *b)
|
||||||
|
{
|
||||||
|
const struct breakpoint *p = *(const struct breakpoint **)a;
|
||||||
|
const struct breakpoint *q = *(const struct breakpoint **)b;
|
||||||
|
|
||||||
|
if (p->type != q->type)
|
||||||
|
return (p->type == BP_HW) ? -1 : 1;
|
||||||
|
|
||||||
|
return (int)(q->hwcnt - p->hwcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reorder_hw_bp(struct task *task)
|
||||||
|
{
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
struct list_head *it;
|
||||||
|
struct breakpoint *bp_list[leader->hw_bp_num + 1];
|
||||||
|
struct breakpoint *bp;
|
||||||
|
struct breakpoint **p;
|
||||||
|
unsigned long hw_bp_set = 0;
|
||||||
|
unsigned int i;
|
||||||
|
unsigned int n;
|
||||||
|
|
||||||
|
if (!leader->hw_bp_num)
|
||||||
|
return;
|
||||||
|
|
||||||
|
n = 0;
|
||||||
|
list_for_each(it, &leader->hw_bp_list) {
|
||||||
|
bp = container_of(it, struct breakpoint, link_list);
|
||||||
|
if (bp->enabled) {
|
||||||
|
assert(n < leader->hw_bp_num);
|
||||||
|
|
||||||
|
bp_list[n++] = bp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(bp_list, n, sizeof(*bp_list), hw_bp_sort);
|
||||||
|
|
||||||
|
for(i = 0; i < n; ++i) {
|
||||||
|
bp_list[i]->hwcnt = (i < HW_BREAKPOINTS - 1) ? BP_REORDER_THRESHOLD >> (i + 4) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n > HW_BREAKPOINTS - 1)
|
||||||
|
n = HW_BREAKPOINTS - 1;
|
||||||
|
|
||||||
|
p = bp_list;
|
||||||
|
for(i = 0; i < n; ++i) {
|
||||||
|
if (bp_list[i]->hw) {
|
||||||
|
assert(bp_list[i]->hw_bp_slot != HW_BP_SCRATCH_SLOT);
|
||||||
|
assert(bp_list[i]->hw_bp_slot < HW_BREAKPOINTS);
|
||||||
|
assert((hw_bp_set & 1 << bp_list[i]->hw_bp_slot) == 0);
|
||||||
|
|
||||||
|
hw_bp_set |= 1 << bp_list[i]->hw_bp_slot;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
*p++ = bp_list[i];
|
||||||
|
}
|
||||||
|
*p = NULL;
|
||||||
|
|
||||||
|
i = HW_BP_SCRATCH_SLOT + 1;
|
||||||
|
for(p = bp_list; (bp = *p); ++p) {
|
||||||
|
while(hw_bp_set & (1 << i))
|
||||||
|
++i;
|
||||||
|
|
||||||
|
stop_threads(leader);
|
||||||
|
disable_sw_breakpoint(leader, bp);
|
||||||
|
|
||||||
|
if (leader->hw_bp[i])
|
||||||
|
hw2sw_bp(leader, leader->hw_bp[i]);
|
||||||
|
|
||||||
|
bp->hw_bp_slot = i;
|
||||||
|
bp->hw = 1;
|
||||||
|
|
||||||
|
each_task(leader, enable_hw_bp_cb, bp);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int insert_hw_bp_slot(struct task *task, struct breakpoint *bp)
|
||||||
|
{
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i) {
|
||||||
|
if (!leader->hw_bp[i])
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (bp->type == BP_HW && leader->hw_bp[i]->type == BP_AUTO) {
|
||||||
|
stop_threads(leader);
|
||||||
|
hw2sw_bp(leader, leader->hw_bp[i]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i >= HW_BREAKPOINTS)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
bp->hwcnt = 0;
|
||||||
|
bp->enabled = 1;
|
||||||
|
bp->hw_bp_slot = i;
|
||||||
|
bp->hw = 1;
|
||||||
|
|
||||||
|
each_task(leader, enable_hw_bp_cb, bp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void breakpoint_hw_clone(struct task *task)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
|
if (leader == task)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(i = HW_BP_SCRATCH_SLOT + 1; i < HW_BREAKPOINTS; ++i) {
|
||||||
|
if (!leader->hw_bp[i]) {
|
||||||
|
assert(task->hw_bp[i] == NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(leader->hw_bp[i]->enabled);
|
||||||
|
assert(leader->hw_bp[i]->hw_bp_slot == i);
|
||||||
|
|
||||||
|
enable_hw_bp(task, leader->hw_bp[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void breakpoint_hw_destroy(struct task *task)
|
void breakpoint_hw_destroy(struct task *task)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for(i = 0; i < HW_BREAKPOINTS; ++i) {
|
for(i = 0; i < HW_BREAKPOINTS; ++i)
|
||||||
if (task->hw_bp[i]) {
|
task->hw_bp[i] = NULL;
|
||||||
assert(task->hw_bp[i]->hw_bp_slot == i);
|
|
||||||
|
|
||||||
task->hw_bp[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reset_all_hw_bp(task);
|
reset_all_hw_bp(task);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
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 (bp->deleted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bp->type == SW_BP)
|
if (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);
|
||||||
@ -190,17 +298,12 @@ void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
enable_hw_bp(task, bp);
|
enable_hw_bp(task, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enable_hw_bp_cb(struct task *task, void *data)
|
|
||||||
{
|
|
||||||
enable_hw_bp(task, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
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 (bp->deleted)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (bp->type == SW_BP)
|
if (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);
|
||||||
@ -208,11 +311,6 @@ void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
|||||||
disable_hw_bp(task, bp);
|
disable_hw_bp(task, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void disable_hw_bp_cb(struct task *task, void *data)
|
|
||||||
{
|
|
||||||
disable_hw_bp(task, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void remove_hw_scratch_bp_cb(struct task *task, void *data)
|
static void remove_hw_scratch_bp_cb(struct task *task, void *data)
|
||||||
{
|
{
|
||||||
if (task->hw_bp[HW_BP_SCRATCH_SLOT] == data) {
|
if (task->hw_bp[HW_BP_SCRATCH_SLOT] == data) {
|
||||||
@ -239,29 +337,30 @@ struct breakpoint *breakpoint_new_ext(struct task *task, arch_addr_t addr, struc
|
|||||||
bp->deleted = 0;
|
bp->deleted = 0;
|
||||||
bp->ext = ext;
|
bp->ext = ext;
|
||||||
bp->refcnt = 1;
|
bp->refcnt = 1;
|
||||||
|
bp->count = 0;
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
bp->hwcnt = 0;
|
||||||
|
#endif
|
||||||
|
bp->type = bp_type;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&bp->link_list);
|
||||||
|
|
||||||
switch(bp_type) {
|
switch(bp_type) {
|
||||||
case HW_BP_SCRATCH:
|
case BP_HW_SCRATCH:
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
bp->type = HW_BP_SCRATCH;
|
|
||||||
bp->hw_bp_slot = HW_BP_SCRATCH_SLOT;
|
bp->hw_bp_slot = HW_BP_SCRATCH_SLOT;
|
||||||
|
bp->hw = 1;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case HW_BP:
|
case BP_AUTO:
|
||||||
|
case BP_HW:
|
||||||
#if HW_BREAKPOINTS > 1
|
#if HW_BREAKPOINTS > 1
|
||||||
{
|
list_add_tail(&bp->link_list, &leader->hw_bp_list);
|
||||||
int slot = find_hw_bp_slot(leader);
|
leader->hw_bp_num++;
|
||||||
if (slot > 0) {
|
|
||||||
leader->hw_bp_mask |= (1 << slot);
|
|
||||||
bp->type = HW_BP;
|
|
||||||
bp->hw_bp_slot = slot;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
case SW_BP:
|
case BP_SW:
|
||||||
bp->type = SW_BP;
|
|
||||||
memset(bp->orig_value, 0, sizeof(bp->orig_value));
|
memset(bp->orig_value, 0, sizeof(bp->orig_value));
|
||||||
|
bp->hw = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) {
|
if (dict_add(leader->breakpoints, (unsigned long)addr, bp) < 0) {
|
||||||
@ -289,17 +388,21 @@ void breakpoint_enable(struct task *task, struct breakpoint *bp)
|
|||||||
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 (!bp->enabled) {
|
||||||
stop_threads(task);
|
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
if (bp->type != SW_BP) {
|
if (bp->type == BP_HW_SCRATCH) {
|
||||||
if (bp->type == HW_BP)
|
bp->enabled = 1;
|
||||||
each_task(task->leader, enable_hw_bp_cb, bp);
|
return;
|
||||||
|
}
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
if (bp->type >= BP_HW) {
|
||||||
|
if (!insert_hw_bp_slot(task, bp))
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
#endif
|
||||||
enable_sw_breakpoint(task, bp);
|
stop_threads(task);
|
||||||
}
|
bp->hw = 0;
|
||||||
|
enable_sw_breakpoint(task, bp);
|
||||||
bp->enabled = 1;
|
bp->enabled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,19 +415,29 @@ void breakpoint_disable(struct task *task, struct breakpoint *bp)
|
|||||||
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 (bp->enabled) {
|
||||||
stop_threads(task);
|
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
if (bp->type != SW_BP) {
|
if (bp->hw) {
|
||||||
if (bp->type == HW_BP)
|
struct task *leader = task->leader;
|
||||||
each_task(task->leader, disable_hw_bp_cb, bp);
|
#if HW_BREAKPOINTS > 1
|
||||||
|
if (bp->type != BP_HW_SCRATCH) {
|
||||||
|
assert(bp->hw_bp_slot != HW_BP_SCRATCH_SLOT);
|
||||||
|
|
||||||
|
each_task(leader, disable_hw_bp_cb, bp);
|
||||||
|
bp->hw = 0;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
each_task(task->leader, remove_hw_scratch_bp_cb, bp);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
disable_sw_breakpoint(task, bp);
|
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
||||||
|
|
||||||
|
each_task(leader, remove_hw_scratch_bp_cb, bp);
|
||||||
|
}
|
||||||
|
bp->enabled = 0;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
stop_threads(task);
|
||||||
|
disable_sw_breakpoint(task, bp);
|
||||||
bp->enabled = 0;
|
bp->enabled = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,24 +472,29 @@ void breakpoint_delete(struct task *task, struct breakpoint *bp)
|
|||||||
|
|
||||||
breakpoint_disable(task, bp);
|
breakpoint_disable(task, bp);
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 1
|
||||||
if (bp->type != SW_BP) {
|
if (bp->type >= BP_HW) {
|
||||||
unsigned int slot = bp->hw_bp_slot;
|
list_del(&bp->link_list);
|
||||||
|
|
||||||
if (bp->type == HW_BP) {
|
leader->hw_bp_num--;
|
||||||
assert(slot != HW_BP_SCRATCH_SLOT);
|
|
||||||
|
|
||||||
leader->hw_bp_mask &= ~(1 << slot);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
assert(slot == HW_BP_SCRATCH_SLOT);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
bp->deleted = 1;
|
|
||||||
|
|
||||||
dict_remove_entry(leader->breakpoints, (unsigned long)bp->addr);
|
dict_remove_entry(leader->breakpoints, (unsigned long)bp->addr);
|
||||||
|
|
||||||
breakpoint_unref(bp);
|
if (options.verbose > 1 && bp->libsym) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"delete %s breakpoint %s:%s [%#lx] count=%u\n",
|
||||||
|
bp->type == BP_SW ? "sw" : "hw",
|
||||||
|
bp->libsym->libref->filename,
|
||||||
|
bp->libsym->func->demangled_name,
|
||||||
|
bp->addr,
|
||||||
|
bp->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
bp->deleted = 1;
|
||||||
|
bp->libsym = NULL;
|
||||||
|
|
||||||
|
breakpoint_put(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enable_nonlocked_bp_cb(unsigned long key, const void *value, void *data)
|
static int enable_nonlocked_bp_cb(unsigned long key, const void *value, void *data)
|
||||||
@ -419,6 +537,7 @@ void breakpoint_disable_all_nonlocked(struct task *leader)
|
|||||||
|
|
||||||
if (leader->breakpoints)
|
if (leader->breakpoints)
|
||||||
dict_apply_to_all(leader->breakpoints, disable_nonlocked_bp_cb, leader);
|
dict_apply_to_all(leader->breakpoints, disable_nonlocked_bp_cb, leader);
|
||||||
|
leader->attached = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int enable_bp_cb(unsigned long key, const void *value, void *data)
|
static int enable_bp_cb(unsigned long key, const void *value, void *data)
|
||||||
@ -459,11 +578,15 @@ void breakpoint_disable_all(struct task *leader)
|
|||||||
|
|
||||||
if (leader->breakpoints)
|
if (leader->breakpoints)
|
||||||
dict_apply_to_all(leader->breakpoints, disable_bp_cb, leader);
|
dict_apply_to_all(leader->breakpoints, disable_bp_cb, leader);
|
||||||
|
leader->attached = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int destroy_breakpoint_cb(unsigned long key, const void *value, void *data)
|
static int destroy_breakpoint_cb(unsigned long key, const void *value, void *data)
|
||||||
{
|
{
|
||||||
free((struct breakpoint *)value);
|
struct breakpoint *bp = (struct breakpoint *)value;
|
||||||
|
struct task *leader = (struct task *)data;
|
||||||
|
|
||||||
|
breakpoint_delete(leader, bp);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,6 +594,7 @@ void breakpoint_clear_all(struct task *leader)
|
|||||||
{
|
{
|
||||||
if (leader->breakpoints) {
|
if (leader->breakpoints) {
|
||||||
dict_apply_to_all(leader->breakpoints, &destroy_breakpoint_cb, leader);
|
dict_apply_to_all(leader->breakpoints, &destroy_breakpoint_cb, leader);
|
||||||
|
assert(leader->hw_bp_num == 0);
|
||||||
dict_clear(leader->breakpoints);
|
dict_clear(leader->breakpoints);
|
||||||
leader->breakpoints = NULL;
|
leader->breakpoints = NULL;
|
||||||
}
|
}
|
||||||
@ -487,49 +611,66 @@ static int clone_single_cb(unsigned long key, const void *value, void *data)
|
|||||||
{
|
{
|
||||||
struct breakpoint *bp = (struct breakpoint *)value;
|
struct breakpoint *bp = (struct breakpoint *)value;
|
||||||
struct task *new_task = (struct task *)data;
|
struct task *new_task = (struct task *)data;
|
||||||
struct library_symbol *libsym = bp->libsym ? find_symbol(new_task, bp->libsym->addr) : NULL;
|
|
||||||
size_t ext = bp->ext;
|
size_t ext = bp->ext;
|
||||||
|
|
||||||
if (bp->deleted)
|
if (bp->deleted)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 0
|
||||||
|
if (bp->type == BP_HW_SCRATCH) {
|
||||||
|
assert(bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
||||||
|
|
||||||
|
if (bp->hw)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
struct breakpoint *new_bp = malloc(sizeof(*new_bp) + ext);
|
struct breakpoint *new_bp = malloc(sizeof(*new_bp) + ext);
|
||||||
if (!new_bp)
|
if (!new_bp)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
new_bp->libsym = libsym;
|
new_bp->libsym = bp->libsym;
|
||||||
new_bp->addr = bp->addr;
|
new_bp->addr = bp->addr;
|
||||||
new_bp->on_hit = bp->on_hit;
|
new_bp->on_hit = bp->on_hit;
|
||||||
new_bp->enabled = bp->enabled;
|
new_bp->enabled = bp->enabled;
|
||||||
new_bp->locked = bp->locked;
|
new_bp->locked = bp->locked;
|
||||||
|
new_bp->hw = bp->hw;
|
||||||
new_bp->type = bp->type;
|
new_bp->type = bp->type;
|
||||||
new_bp->ext = ext;
|
new_bp->ext = ext;
|
||||||
|
new_bp->refcnt = 1;
|
||||||
|
new_bp->deleted = 0;
|
||||||
|
new_bp->count = 0;
|
||||||
|
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 1
|
||||||
if (new_bp->type != SW_BP) {
|
new_bp->hwcnt = 0;
|
||||||
|
|
||||||
|
if (new_bp->type >= BP_HW) {
|
||||||
|
list_add_tail(&new_bp->link_list, &new_task->hw_bp_list);
|
||||||
|
new_task->hw_bp_num++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
INIT_LIST_HEAD(&new_bp->link_list);
|
||||||
|
|
||||||
|
if (new_bp->hw) {
|
||||||
new_bp->hw_bp_slot = bp->hw_bp_slot;
|
new_bp->hw_bp_slot = bp->hw_bp_slot;
|
||||||
|
|
||||||
if (bp->type == HW_BP) {
|
assert(new_bp->hw_bp_slot != HW_BP_SCRATCH_SLOT);
|
||||||
assert(new_bp->hw_bp_slot != HW_BP_SCRATCH_SLOT);
|
|
||||||
|
|
||||||
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 (set_hw_bp(new_task, new_bp->hw_bp_slot, new_bp->addr) == -1)
|
||||||
fatal("set_hw_bp");
|
fatal("set_hw_bp");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
assert(new_bp->hw_bp_slot == HW_BP_SCRATCH_SLOT);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
memcpy(new_bp->orig_value, bp->orig_value, sizeof(bp->orig_value));
|
memcpy(new_bp->orig_value, bp->orig_value, sizeof(bp->orig_value));
|
||||||
|
|
||||||
if (ext)
|
if (ext)
|
||||||
memcpy((void *)new_bp + ext, (void *)bp + ext, ext);
|
memcpy((void *)new_bp + ext, (void *)bp + ext, ext);
|
||||||
|
|
||||||
if (dict_add(new_task->leader->breakpoints, (unsigned long)new_bp->addr, new_bp) < 0) {
|
if (dict_add(new_task->breakpoints, (unsigned long)new_bp->addr, new_bp) < 0) {
|
||||||
fprintf(stderr, "couldn't enter breakpoint %lx to dictionary\n", new_bp->addr);
|
fprintf(stderr, "couldn't enter breakpoint %lx to dictionary\n", new_bp->addr);
|
||||||
goto fail2;
|
goto fail2;
|
||||||
}
|
}
|
||||||
@ -546,3 +687,23 @@ int breakpoint_clone_all(struct task *clone, struct task *leader)
|
|||||||
return dict_apply_to_all(leader->breakpoints, &clone_single_cb, clone);
|
return dict_apply_to_all(leader->breakpoints, &clone_single_cb, clone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct breakpoint *breakpoint_get(struct breakpoint *bp)
|
||||||
|
{
|
||||||
|
if (bp)
|
||||||
|
++bp->refcnt;
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int breakpoint_put(struct breakpoint *bp)
|
||||||
|
{
|
||||||
|
if (bp) {
|
||||||
|
assert(bp->refcnt != 0);
|
||||||
|
|
||||||
|
if (--bp->refcnt)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
free(bp);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
61
breakpoint.h
61
breakpoint.h
@ -26,34 +26,42 @@
|
|||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "arch.h"
|
||||||
|
#include "list.h"
|
||||||
#include "sysdep.h"
|
#include "sysdep.h"
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
|
||||||
#define SW_BP 0
|
#define BP_REORDER_THRESHOLD 1024U
|
||||||
#define HW_BP 1
|
|
||||||
#define HW_BP_SCRATCH 2
|
#define BP_SW 0
|
||||||
|
#define BP_HW_SCRATCH 1
|
||||||
|
#define BP_HW 2
|
||||||
|
#define BP_AUTO 3
|
||||||
|
|
||||||
struct breakpoint {
|
struct breakpoint {
|
||||||
arch_addr_t addr;
|
#if HW_BREAKPOINTS > 1
|
||||||
|
unsigned int hwcnt;
|
||||||
|
#endif
|
||||||
|
unsigned int refcnt;
|
||||||
|
unsigned int count;
|
||||||
|
|
||||||
|
unsigned int ext:8;
|
||||||
|
unsigned int type:2;
|
||||||
unsigned int enabled:1;
|
unsigned int enabled:1;
|
||||||
unsigned int locked:1;
|
unsigned int locked:1;
|
||||||
unsigned int deleted:1;
|
unsigned int deleted:1;
|
||||||
unsigned int type:2;
|
unsigned int hw:1;
|
||||||
unsigned int ext:8;
|
|
||||||
|
|
||||||
unsigned int refcnt;
|
|
||||||
|
|
||||||
int (*on_hit)(struct task *task, struct breakpoint *bp);
|
|
||||||
|
|
||||||
struct library_symbol *libsym;
|
|
||||||
|
|
||||||
union {
|
union {
|
||||||
unsigned char orig_value[BREAKPOINT_LENGTH];
|
unsigned char orig_value[BREAKPOINT_LENGTH];
|
||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
unsigned int hw_bp_slot;
|
unsigned int hw_bp_slot;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
int (*on_hit)(struct task *task, struct breakpoint *bp);
|
||||||
|
arch_addr_t addr;
|
||||||
|
struct library_symbol *libsym;
|
||||||
|
struct list_head link_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* setup the basic breakpoint support for a given leader */
|
/* setup the basic breakpoint support for a given leader */
|
||||||
@ -92,9 +100,6 @@ struct breakpoint *breakpoint_find(struct task *leader, arch_addr_t addr);
|
|||||||
#if HW_BREAKPOINTS > 0
|
#if HW_BREAKPOINTS > 0
|
||||||
void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp);
|
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);
|
||||||
|
|
||||||
void breakpoint_hw_clone(struct task *task);
|
|
||||||
void breakpoint_hw_destroy(struct task *task);
|
|
||||||
#else
|
#else
|
||||||
static inline void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
static inline void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
@ -103,7 +108,14 @@ static inline void enable_scratch_hw_bp(struct task *task, struct breakpoint *bp
|
|||||||
static inline void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
static inline void disable_scratch_hw_bp(struct task *task, struct breakpoint *bp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
void reorder_hw_bp(struct task *task);
|
||||||
|
|
||||||
|
void breakpoint_hw_clone(struct task *task);
|
||||||
|
void breakpoint_hw_destroy(struct task *task);
|
||||||
|
#else
|
||||||
static inline void breakpoint_hw_clone(struct task *task)
|
static inline void breakpoint_hw_clone(struct task *task)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -113,22 +125,9 @@ static inline void breakpoint_hw_destroy(struct task *task)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static inline struct breakpoint *breakpoint_ref(struct breakpoint *bp)
|
struct breakpoint *breakpoint_get(struct breakpoint *bp);
|
||||||
{
|
|
||||||
if (bp)
|
|
||||||
++bp->refcnt;
|
|
||||||
return bp;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int breakpoint_unref(struct breakpoint *bp)
|
int breakpoint_put(struct breakpoint *bp);
|
||||||
{
|
|
||||||
if (bp) {
|
|
||||||
if (--bp->refcnt)
|
|
||||||
return 0;
|
|
||||||
free(bp);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
153
client/binfile.c
153
client/binfile.c
@ -25,10 +25,13 @@
|
|||||||
#include <execinfo.h>
|
#include <execinfo.h>
|
||||||
#include <link.h>
|
#include <link.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include "binfile.h"
|
#include "binfile.h"
|
||||||
#include "process.h"
|
#include "process.h"
|
||||||
|
|
||||||
|
static LIST_HEAD(list_of_binfiles);
|
||||||
|
|
||||||
/* These variables are used to pass information between
|
/* These variables are used to pass information between
|
||||||
translate_addresses and find_address_in_section. */
|
translate_addresses and find_address_in_section. */
|
||||||
struct sym_info {
|
struct sym_info {
|
||||||
@ -50,7 +53,7 @@ static long slurp_symtab(struct bin_file *binfile)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
storage = bfd_get_symtab_upper_bound(binfile->abfd);
|
storage = bfd_get_symtab_upper_bound(binfile->abfd);
|
||||||
if (storage == 0) {
|
if (!storage) {
|
||||||
storage = bfd_get_dynamic_symtab_upper_bound(binfile->abfd);
|
storage = bfd_get_dynamic_symtab_upper_bound(binfile->abfd);
|
||||||
dynamic = TRUE;
|
dynamic = TRUE;
|
||||||
}
|
}
|
||||||
@ -98,19 +101,34 @@ static void find_address_in_section(bfd *abfd, asection *section, void *data __a
|
|||||||
psi->found = bfd_find_nearest_line(abfd, section, psi->syms, psi->pc - vma, &psi->filename, &psi->functionname, &psi->line);
|
psi->found = bfd_find_nearest_line(abfd, section, psi->syms, psi->pc - vma, &psi->filename, &psi->functionname, &psi->line);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off)
|
struct rb_sym *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off, const char *filename)
|
||||||
{
|
{
|
||||||
struct sym_info si = { 0 };
|
struct sym_info si = { 0 };
|
||||||
char *ret_buf = NULL;
|
char *sym_buf = NULL;
|
||||||
|
struct rb_root *root = &binfile->sym_table;
|
||||||
|
struct rb_node **new = &(root->rb_node), *parent = NULL;
|
||||||
|
struct rb_sym *this;
|
||||||
|
|
||||||
if (!binfile)
|
if (!binfile)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (!binfile->abfd)
|
/* Figure out where to put new node */
|
||||||
return NULL;
|
while (*new) {
|
||||||
|
this = container_of(*new, struct rb_sym, node);
|
||||||
|
|
||||||
if (!binfile->syms)
|
parent = *new;
|
||||||
return NULL;
|
|
||||||
|
if (addr < this->addr)
|
||||||
|
new = &((*new)->rb_left);
|
||||||
|
else
|
||||||
|
if (addr > this->addr)
|
||||||
|
new = &((*new)->rb_right);
|
||||||
|
else {
|
||||||
|
bin_file_sym_get(this);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
si.pc = (binfile->abfd->flags & EXEC_P) ? addr : addr - off;
|
si.pc = (binfile->abfd->flags & EXEC_P) ? addr : addr - off;
|
||||||
si.syms = binfile->syms;
|
si.syms = binfile->syms;
|
||||||
@ -120,8 +138,8 @@ char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off)
|
|||||||
bfd_map_over_sections(binfile->abfd, find_address_in_section, &si);
|
bfd_map_over_sections(binfile->abfd, find_address_in_section, &si);
|
||||||
|
|
||||||
if (!si.found) {
|
if (!si.found) {
|
||||||
if (asprintf(&ret_buf, "%s", bfd_get_filename(binfile->abfd)) == -1)
|
if (asprintf(&sym_buf, "%s", filename) == -1)
|
||||||
ret_buf = NULL;
|
sym_buf = NULL;
|
||||||
} else {
|
} else {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
@ -141,16 +159,16 @@ char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off)
|
|||||||
name = alloc;
|
name = alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret_buf)
|
if (sym_buf)
|
||||||
free(ret_buf);
|
free(sym_buf);
|
||||||
|
|
||||||
if (si.line) {
|
if (si.line) {
|
||||||
if (asprintf(&ret_buf, "%s:%u %s", si.filename ? si.filename : bfd_get_filename(binfile->abfd), si.line, name) == -1)
|
if (asprintf(&sym_buf, "%s:%u %s", si.filename ? si.filename : filename, si.line, name) == -1)
|
||||||
ret_buf = NULL;
|
sym_buf = NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (asprintf(&ret_buf, "%s %s", si.filename ? si.filename : bfd_get_filename(binfile->abfd), name) == -1)
|
if (asprintf(&sym_buf, "%s %s", si.filename ? si.filename : filename, name) == -1)
|
||||||
ret_buf = NULL;
|
sym_buf = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (alloc)
|
if (alloc)
|
||||||
@ -160,72 +178,119 @@ char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off)
|
|||||||
} while (si.found);
|
} while (si.found);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret_buf;
|
this = malloc(sizeof(*this));
|
||||||
|
if (!this)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
this->addr = addr;
|
||||||
|
this->sym = sym_buf;
|
||||||
|
this->refcnt = 1;
|
||||||
|
this->binfile = binfile;
|
||||||
|
|
||||||
|
++binfile->refcnt;
|
||||||
|
|
||||||
|
/* Add new node and rebalance tree. */
|
||||||
|
rb_link_node(&this->node, parent, new);
|
||||||
|
rb_insert_color(&this->node, root);
|
||||||
|
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bin_file *bin_file_new(const char *filename)
|
struct bin_file *bin_file_open(const char *filename)
|
||||||
{
|
{
|
||||||
bfd *abfd;
|
|
||||||
char **matching;
|
char **matching;
|
||||||
struct bin_file *binfile;
|
struct bin_file *binfile;
|
||||||
|
struct list_head *it;
|
||||||
|
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
list_for_each(it, &list_of_binfiles) {
|
||||||
|
binfile = container_of(it, struct bin_file, list);
|
||||||
|
|
||||||
|
if (!strcmp(filename, binfile->filename)) {
|
||||||
|
bin_file_get(binfile);
|
||||||
|
return binfile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
binfile = malloc(sizeof(struct bin_file));
|
binfile = malloc(sizeof(struct bin_file));
|
||||||
if (!binfile)
|
if (!binfile)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
abfd = bfd_openr(filename, NULL);
|
binfile->filename = strdup(filename);
|
||||||
if (!abfd)
|
binfile->refcnt = 1;
|
||||||
|
binfile->sym_table = RB_ROOT;
|
||||||
|
binfile->abfd = bfd_openr(binfile->filename, NULL);
|
||||||
|
|
||||||
|
if (!binfile->abfd)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* Decompress sections. */
|
if (bfd_check_format(binfile->abfd, bfd_archive))
|
||||||
// abfd->flags |= BFD_DECOMPRESS;
|
|
||||||
|
|
||||||
if (bfd_check_format(abfd, bfd_archive))
|
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if (!bfd_check_format_matches(abfd, bfd_object, &matching))
|
if (!bfd_check_format_matches(binfile->abfd, bfd_object, &matching))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
binfile->abfd = abfd;
|
|
||||||
|
|
||||||
if (slurp_symtab(binfile) <= 0)
|
if (slurp_symtab(binfile) <= 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
binfile->refcnt = 1;
|
list_add_tail(&binfile->list, &list_of_binfiles);
|
||||||
|
|
||||||
return binfile;
|
return binfile;
|
||||||
error:
|
error:
|
||||||
if (abfd)
|
if (binfile->abfd)
|
||||||
bfd_close(abfd);
|
bfd_close(binfile->abfd);
|
||||||
|
free(binfile->filename);
|
||||||
free(binfile);
|
free(binfile);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct bin_file *bin_file_clone(struct bin_file *binfile)
|
void bin_file_get(struct bin_file *binfile)
|
||||||
{
|
{
|
||||||
if (!binfile)
|
++binfile->refcnt;
|
||||||
return NULL;
|
|
||||||
|
|
||||||
binfile->refcnt++;
|
|
||||||
|
|
||||||
return binfile;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bin_file_free(struct bin_file *binfile)
|
void bin_file_put(struct bin_file *binfile)
|
||||||
{
|
{
|
||||||
if (!binfile)
|
if (!binfile)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (--binfile->refcnt > 0)
|
if (!--binfile->refcnt) {
|
||||||
return;
|
list_del(&binfile->list);
|
||||||
|
|
||||||
if (binfile->syms)
|
if (binfile->syms)
|
||||||
free(binfile->syms);
|
free(binfile->syms);
|
||||||
|
|
||||||
if (binfile->abfd)
|
if (binfile->abfd)
|
||||||
bfd_close(binfile->abfd);
|
bfd_close(binfile->abfd);
|
||||||
|
|
||||||
|
free(binfile->filename);
|
||||||
|
free(binfile);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void bin_file_sym_get(struct rb_sym *sym)
|
||||||
|
{
|
||||||
|
struct bin_file *binfile = sym->binfile;
|
||||||
|
|
||||||
|
++sym->refcnt;
|
||||||
|
++binfile->refcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
void bin_file_sym_put(struct rb_sym *sym)
|
||||||
|
{
|
||||||
|
struct bin_file *binfile = sym->binfile;
|
||||||
|
|
||||||
|
if (!--sym->refcnt) {
|
||||||
|
free(sym->sym);
|
||||||
|
|
||||||
|
if (!binfile)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rb_erase(&sym->node, &binfile->sym_table);
|
||||||
|
}
|
||||||
|
bin_file_put(binfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,16 +24,31 @@
|
|||||||
#define _INC_CLIENT_BINFILE_H
|
#define _INC_CLIENT_BINFILE_H
|
||||||
|
|
||||||
#include "bfdinc.h"
|
#include "bfdinc.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "rbtree.h"
|
||||||
|
|
||||||
struct bin_file {
|
struct rb_sym {
|
||||||
bfd *abfd;
|
struct rb_node node;
|
||||||
asymbol **syms;
|
bfd_vma addr;
|
||||||
unsigned int refcnt;
|
char *sym;
|
||||||
|
struct bin_file *binfile;
|
||||||
|
unsigned long refcnt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct bin_file *bin_file_new(const char *filename);
|
struct bin_file {
|
||||||
struct bin_file *bin_file_clone(struct bin_file *binfile);
|
struct list_head list;
|
||||||
void bin_file_free(struct bin_file *binfile);
|
bfd *abfd;
|
||||||
char *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off);
|
asymbol **syms;
|
||||||
|
struct rb_root sym_table;
|
||||||
|
unsigned long refcnt;
|
||||||
|
char *filename;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct bin_file *bin_file_open(const char *filename);
|
||||||
|
void bin_file_put(struct bin_file *binfile);
|
||||||
|
void bin_file_get(struct bin_file *binfile);
|
||||||
|
struct rb_sym *bin_file_lookup(struct bin_file *binfile, bfd_vma addr, unsigned long off, const char *filename);
|
||||||
|
void bin_file_sym_get(struct rb_sym *sym);
|
||||||
|
void bin_file_sym_put(struct rb_sym *sym);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
149
client/client.c
149
client/client.c
@ -306,6 +306,7 @@ static int socket_read_msg(struct mt_msg *mt_msg, void **payload, unsigned int *
|
|||||||
else
|
else
|
||||||
*swap_endian = 0;
|
*swap_endian = 0;
|
||||||
|
|
||||||
|
|
||||||
if (mt_msg->payload_len) {
|
if (mt_msg->payload_len) {
|
||||||
*payload = malloc(mt_msg->payload_len);
|
*payload = malloc(mt_msg->payload_len);
|
||||||
|
|
||||||
@ -333,8 +334,10 @@ static unsigned int attached_payload(void *payload)
|
|||||||
void client_close(void)
|
void client_close(void)
|
||||||
{
|
{
|
||||||
if (client_fd != -1) {
|
if (client_fd != -1) {
|
||||||
ioevent_del_input(client_fd);
|
if (thread) {
|
||||||
shutdown(client_fd, SHUT_RDWR);
|
ioevent_del_input(client_fd);
|
||||||
|
shutdown(client_fd, SHUT_RDWR);
|
||||||
|
}
|
||||||
close(client_fd);
|
close(client_fd);
|
||||||
client_fd = -1;
|
client_fd = -1;
|
||||||
}
|
}
|
||||||
@ -343,11 +346,29 @@ void client_close(void)
|
|||||||
static void client_broken(void)
|
static void client_broken(void)
|
||||||
{
|
{
|
||||||
if (client_fd != -1) {
|
if (client_fd != -1) {
|
||||||
fprintf(stderr, "connection lost\n");
|
if (!options.logfile)
|
||||||
|
fprintf(stderr, "connection lost\n");
|
||||||
|
|
||||||
client_close();
|
client_close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void client_add_process(struct process *process)
|
||||||
|
{
|
||||||
|
if (!first_pid)
|
||||||
|
first_pid = process->pid;
|
||||||
|
|
||||||
|
process_rb_insert(&pid_table, process);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void client_remove_process(struct process *process)
|
||||||
|
{
|
||||||
|
process = pid_rb_delete(&pid_table, process->pid);
|
||||||
|
|
||||||
|
if (process)
|
||||||
|
free(process);
|
||||||
|
}
|
||||||
|
|
||||||
static int client_func(void)
|
static int client_func(void)
|
||||||
{
|
{
|
||||||
struct mt_msg mt_msg;
|
struct mt_msg mt_msg;
|
||||||
@ -365,7 +386,10 @@ static int client_func(void)
|
|||||||
|
|
||||||
switch(mt_msg.operation) {
|
switch(mt_msg.operation) {
|
||||||
case MT_DISCONNECT:
|
case MT_DISCONNECT:
|
||||||
sock_send_msg(client_fd, MT_DISCONNECT, 0, 0, NULL, 0);
|
if (!options.trace && !options.logfile) {
|
||||||
|
printf("server disconnected\n");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
client_close();
|
client_close();
|
||||||
break;
|
break;
|
||||||
case MT_INFO:
|
case MT_INFO:
|
||||||
@ -433,7 +457,8 @@ static int client_func(void)
|
|||||||
process_exit(process);
|
process_exit(process);
|
||||||
break;
|
break;
|
||||||
case MT_NOFOLLOW:
|
case MT_NOFOLLOW:
|
||||||
process_delete(process);
|
process_reset(process);
|
||||||
|
client_remove_process(process);
|
||||||
break;
|
break;
|
||||||
case MT_SCAN:
|
case MT_SCAN:
|
||||||
process_scan(process, payload, mt_msg.payload_len);
|
process_scan(process, payload, mt_msg.payload_len);
|
||||||
@ -470,6 +495,9 @@ void client_show_info(void)
|
|||||||
|
|
||||||
int client_wait_op(enum mt_operation op)
|
int client_wait_op(enum mt_operation op)
|
||||||
{
|
{
|
||||||
|
if (options.logfile)
|
||||||
|
return -1;
|
||||||
|
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (client_fd == -1)
|
if (client_fd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
@ -483,22 +511,6 @@ int client_wait_op(enum mt_operation op)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int client_release_process(struct rb_node *node, void *user)
|
|
||||||
{
|
|
||||||
struct rb_process *data = (struct rb_process *)node;
|
|
||||||
|
|
||||||
process_delete(data->process);
|
|
||||||
free(data);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void client_finalize()
|
|
||||||
{
|
|
||||||
client_close();
|
|
||||||
|
|
||||||
rb_iterate(&pid_table, client_release_process, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
@ -529,23 +541,6 @@ struct process *client_first_process(void)
|
|||||||
return client_find_process(first_pid);
|
return client_find_process(first_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void client_add_process(struct process *process)
|
|
||||||
{
|
|
||||||
if (!first_pid)
|
|
||||||
first_pid = process->pid;
|
|
||||||
|
|
||||||
process_rb_insert(&pid_table, process);
|
|
||||||
}
|
|
||||||
|
|
||||||
void client_remove_process(struct process *process)
|
|
||||||
{
|
|
||||||
process = pid_rb_delete(&pid_table, process->pid);
|
|
||||||
|
|
||||||
if (process)
|
|
||||||
free(process);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int client_init(int do_trace)
|
static int client_init(int do_trace)
|
||||||
{
|
{
|
||||||
struct opt_F_t *p;
|
struct opt_F_t *p;
|
||||||
@ -602,14 +597,17 @@ int client_start(void)
|
|||||||
if (client_init(0) < 0)
|
if (client_init(0) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
client_fd = connect_to(options.client, options.port);
|
client_fd = connect_to(options.address, options.port);
|
||||||
|
|
||||||
if (client_fd == -1) {
|
if (client_fd == -1) {
|
||||||
fprintf(stderr, "could not connect: %s:%s\n", options.client, options.port);
|
fprintf(stderr, "could not connect: %s\n", options.address);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
client_wait_op(MT_INFO);
|
if (client_wait_op(MT_INFO) == -1) {
|
||||||
|
fprintf(stderr, "could not talk to server\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (mt_info.version != MEMTRACE_SI_VERSION) {
|
if (mt_info.version != MEMTRACE_SI_VERSION) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
@ -626,6 +624,8 @@ int client_start(void)
|
|||||||
ioevent_add_input(client_fd, client_func);
|
ioevent_add_input(client_fd, client_func);
|
||||||
|
|
||||||
if (options.interactive) {
|
if (options.interactive) {
|
||||||
|
int old_client_fd = client_fd;
|
||||||
|
|
||||||
signal(SIGINT, SIG_IGN);
|
signal(SIGINT, SIG_IGN);
|
||||||
signal(SIGTERM, SIG_IGN);
|
signal(SIGTERM, SIG_IGN);
|
||||||
|
|
||||||
@ -634,6 +634,13 @@ int client_start(void)
|
|||||||
while(ioevent_watch(-1) != -1)
|
while(ioevent_watch(-1) != -1)
|
||||||
;
|
;
|
||||||
|
|
||||||
|
if (client_fd == -1) {
|
||||||
|
ioevent_del_input(old_client_fd);
|
||||||
|
|
||||||
|
while(ioevent_watch(-1) != -1)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
readline_exit();
|
readline_exit();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -697,7 +704,12 @@ int client_start_pair(int handle)
|
|||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
int ret = sock_send_msg(client_fd, process->val16(op), process->pid, 0, payload, payload_len);
|
int ret;
|
||||||
|
|
||||||
|
if (options.logfile)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = sock_send_msg(client_fd, process->val16(op), process->pid, 0, payload, payload_len);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
client_broken();
|
client_broken();
|
||||||
@ -709,16 +721,63 @@ int client_connected(void)
|
|||||||
if (client_fd != -1)
|
if (client_fd != -1)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
printf("connection lost\n");
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int client_stop(void)
|
int client_stop(void)
|
||||||
{
|
{
|
||||||
if (thread)
|
if (thread) {
|
||||||
thread_join(thread);
|
thread_join(thread);
|
||||||
|
thread = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
client_close();
|
client_close();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int client_logfile(void)
|
||||||
|
{
|
||||||
|
const char spin[4] = "|/-\\";
|
||||||
|
unsigned int i;
|
||||||
|
const unsigned int spindepth = 14;
|
||||||
|
|
||||||
|
thread = NULL;
|
||||||
|
|
||||||
|
if (client_init(1) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
client_fd = open(options.logfile, O_RDONLY);
|
||||||
|
if (client_fd == -1)
|
||||||
|
fatal("could not open logfile: %s", options.logfile);
|
||||||
|
|
||||||
|
printf("processing logfile `%s'... ", options.logfile);
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
for(i = 0; client_fd != -1; ++i) {
|
||||||
|
if ((i & ((1 << spindepth) - 1)) == 0) {
|
||||||
|
printf("\b%c", spin[(i >> spindepth) & (ARRAY_SIZE(spin) - 1)]);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
client_func();
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("\bdone\n");
|
||||||
|
fflush(stdout);
|
||||||
|
|
||||||
|
if (options.interactive) {
|
||||||
|
client_show_info();
|
||||||
|
|
||||||
|
signal(SIGINT, SIG_IGN);
|
||||||
|
signal(SIGTERM, SIG_IGN);
|
||||||
|
|
||||||
|
readline_init();
|
||||||
|
|
||||||
|
while(ioevent_watch(-1) != -1)
|
||||||
|
;
|
||||||
|
|
||||||
|
readline_exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -27,13 +27,9 @@
|
|||||||
|
|
||||||
struct process;
|
struct process;
|
||||||
|
|
||||||
void client_finalize();
|
|
||||||
|
|
||||||
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(pid_t pid);
|
||||||
void client_iterate_processes(int (*func)(struct process *process));
|
void client_iterate_processes(int (*func)(struct process *process));
|
||||||
void client_add_process(struct process *process);
|
|
||||||
void client_remove_process(struct process *process);
|
|
||||||
void client_show_info(void);
|
void client_show_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);
|
||||||
@ -42,6 +38,7 @@ int client_connected(void);
|
|||||||
int client_start(void);
|
int client_start(void);
|
||||||
int client_start_pair(int handle);
|
int client_start_pair(int handle);
|
||||||
int client_stop(void);
|
int client_stop(void);
|
||||||
|
int client_logfile(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
105
client/process.c
105
client/process.c
@ -56,7 +56,7 @@ struct stack {
|
|||||||
void *addrs;
|
void *addrs;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t entries;
|
uint32_t entries;
|
||||||
char **syms;
|
struct rb_sym **syms;
|
||||||
enum mt_operation operation;
|
enum mt_operation operation;
|
||||||
unsigned int ignore:1;
|
unsigned int ignore:1;
|
||||||
};
|
};
|
||||||
@ -78,7 +78,6 @@ struct map {
|
|||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
char *filename;
|
char *filename;
|
||||||
char *realpath;
|
|
||||||
struct bin_file *binfile;
|
struct bin_file *binfile;
|
||||||
unsigned int ignore:1;
|
unsigned int ignore:1;
|
||||||
};
|
};
|
||||||
@ -284,7 +283,6 @@ static struct map *open_map(struct process *process, bfd_vma addr)
|
|||||||
return map;
|
return map;
|
||||||
|
|
||||||
p = options.opt_b;
|
p = options.opt_b;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
p = &opt_b_default;
|
p = &opt_b_default;
|
||||||
|
|
||||||
@ -294,53 +292,54 @@ static struct map *open_map(struct process *process, bfd_vma addr)
|
|||||||
while(len && (p->pathname)[len - 1] == '/')
|
while(len && (p->pathname)[len - 1] == '/')
|
||||||
--len;
|
--len;
|
||||||
|
|
||||||
for(fname = map->filename; *fname == '/'; ++fname)
|
fname = map->filename;
|
||||||
;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (asprintf(&realpath, "%.*s/%s", len, p->pathname, fname) == -1) {
|
if (asprintf(&realpath, "%.*s%s%s", len, p->pathname, *p->pathname ? "/" : "", fname) == -1) {
|
||||||
map->ignore = 1;
|
map->ignore = 1;
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!access(realpath, R_OK)) {
|
if (!access(realpath, R_OK))
|
||||||
map->binfile = bin_file_new(realpath);
|
map->binfile = bin_file_open(realpath);
|
||||||
|
|
||||||
if (map->binfile) {
|
|
||||||
map->realpath = realpath;
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free(realpath);
|
free(realpath);
|
||||||
|
|
||||||
|
if (map->binfile)
|
||||||
|
return map;
|
||||||
|
|
||||||
fname = strchr(fname + 1, '/');
|
fname = strchr(fname + 1, '/');
|
||||||
} while(fname++);
|
} while(fname++);
|
||||||
|
|
||||||
p = p->next;
|
p = p->next;
|
||||||
} while(p);
|
} while(p);
|
||||||
|
|
||||||
|
fprintf(stderr, "file `%s' not found!\n", map->filename);
|
||||||
|
|
||||||
map->ignore = 1;
|
map->ignore = 1;
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *resolv_address(struct process *process, bfd_vma addr)
|
static struct rb_sym *resolv_address(struct process *process, bfd_vma addr)
|
||||||
{
|
{
|
||||||
char *sym;
|
struct rb_sym *sym;
|
||||||
struct map *map = open_map(process, addr);
|
struct map *map = open_map(process, addr);
|
||||||
|
|
||||||
if (!map)
|
if (!map)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (map->binfile) {
|
sym = bin_file_lookup(map->binfile, addr, map->addr, map->filename);
|
||||||
sym = bin_file_lookup(map->binfile, addr, map->addr);
|
if (!sym) {
|
||||||
if (sym)
|
sym = malloc(sizeof(*sym));
|
||||||
return sym;
|
if (!sym)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
sym->addr = addr;
|
||||||
|
sym->sym = strdup(map->filename);
|
||||||
|
sym->refcnt = 1;
|
||||||
|
sym->binfile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (asprintf(&sym, "%s", map->filename) == -1)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,7 +367,7 @@ static void stack_resolv(struct process *process, struct stack *stack)
|
|||||||
struct regex_list *p;
|
struct regex_list *p;
|
||||||
|
|
||||||
for(p = regex_ignore_list; p; p = p->next)
|
for(p = regex_ignore_list; p; p = p->next)
|
||||||
if (stack->syms[i] && !regexec(&p->re, stack->syms[i], 0, NULL, 0)) {
|
if (stack->syms[i] && !regexec(&p->re, stack->syms[i]->sym, 0, NULL, 0)) {
|
||||||
stack->ignore = 1;
|
stack->ignore = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -379,14 +378,14 @@ static void stack_resolv(struct process *process, struct stack *stack)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void stack_unref(struct stack *stack)
|
static void stack_put(struct stack *stack)
|
||||||
{
|
{
|
||||||
if (--stack->refcnt == 0) {
|
if (--stack->refcnt == 0) {
|
||||||
if (stack->syms) {
|
if (stack->syms) {
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
for(i = 0; i < stack->entries; ++i)
|
for(i = 0; i < stack->entries; ++i)
|
||||||
free(stack->syms[i]);
|
bin_file_sym_put(stack->syms[i]);
|
||||||
|
|
||||||
free(stack->syms);
|
free(stack->syms);
|
||||||
}
|
}
|
||||||
@ -459,8 +458,11 @@ static struct rb_stack *stack_add(struct process *process, pid_t pid, void *addr
|
|||||||
else
|
else
|
||||||
if (ret > 0)
|
if (ret > 0)
|
||||||
new = &((*new)->rb_right);
|
new = &((*new)->rb_right);
|
||||||
else
|
else {
|
||||||
|
assert(this->stack->operation == operation);
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this = malloc(sizeof(*this));
|
this = malloc(sizeof(*this));
|
||||||
@ -511,7 +513,7 @@ static void process_dump_stack(struct process *process, struct rb_stack *this)
|
|||||||
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] %s\n", process->get_ulong(addrs), stack->syms[i] ? stack->syms[i] : "?") == -1)
|
if (dump_printf(" [0x%lx] %s\n", process->get_ulong(addrs), stack->syms[i] ? stack->syms[i]->sym : "?") == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addrs += process->ptr_size;
|
addrs += process->ptr_size;
|
||||||
@ -648,7 +650,7 @@ static int process_rb_insert_block(struct process *process, unsigned long addr,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct map *_process_add_map(struct process *process, unsigned long addr, unsigned long offset, unsigned long size, const char *filename, size_t len)
|
static struct map *_process_add_map(struct process *process, unsigned long addr, unsigned long offset, unsigned long size, const char *filename, size_t len, struct bin_file *binfile)
|
||||||
{
|
{
|
||||||
struct map *map = malloc(sizeof(*map));
|
struct map *map = malloc(sizeof(*map));
|
||||||
|
|
||||||
@ -656,10 +658,12 @@ static struct map *_process_add_map(struct process *process, unsigned long addr,
|
|||||||
map->offset = offset;
|
map->offset = offset;
|
||||||
map->size = size;
|
map->size = size;
|
||||||
map->filename = malloc(len + 1);
|
map->filename = malloc(len + 1);
|
||||||
map->realpath = NULL;
|
map->binfile = binfile;
|
||||||
map->binfile = NULL;
|
|
||||||
map->ignore = 0;
|
map->ignore = 0;
|
||||||
|
|
||||||
|
if (binfile)
|
||||||
|
bin_file_get(binfile);
|
||||||
|
|
||||||
safe_strncpy(map->filename, filename, len + 1);
|
safe_strncpy(map->filename, filename, len + 1);
|
||||||
|
|
||||||
if (list_empty(&process->map_list)) {
|
if (list_empty(&process->map_list)) {
|
||||||
@ -669,7 +673,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: stack_add() can produce now false matches */
|
/* fixit: it is possible that stack_add() can produce false matches */
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@ -682,18 +686,16 @@ void process_add_map(struct process *process, void *payload, uint32_t payload_le
|
|||||||
uint64_t offset = process->val64(mt_map->offset);
|
uint64_t offset = process->val64(mt_map->offset);
|
||||||
uint64_t size = process->val64(mt_map->size);
|
uint64_t size = process->val64(mt_map->size);
|
||||||
|
|
||||||
_process_add_map(process, addr, offset, size, mt_map->filename, payload_len - sizeof(*mt_map));
|
_process_add_map(process, addr, offset, size, mt_map->filename, payload_len - sizeof(*mt_map), NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _process_del_map(struct map *map)
|
static void _process_del_map(struct map *map)
|
||||||
{
|
{
|
||||||
bin_file_free(map->binfile);
|
bin_file_put(map->binfile);
|
||||||
|
|
||||||
list_del(&map->list);
|
list_del(&map->list);
|
||||||
|
|
||||||
free(map->filename);
|
free(map->filename);
|
||||||
free(map->realpath);
|
|
||||||
free(map->binfile);
|
|
||||||
free(map);
|
free(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -752,7 +754,7 @@ void process_reset_allocations(struct process *process)
|
|||||||
process->block_table = RB_ROOT;
|
process->block_table = RB_ROOT;
|
||||||
|
|
||||||
rbtree_postorder_for_each_entry_safe(rbs, rbs_next, &process->stack_table, node) {
|
rbtree_postorder_for_each_entry_safe(rbs, rbs_next, &process->stack_table, node) {
|
||||||
stack_unref(rbs->stack);
|
stack_put(rbs->stack);
|
||||||
free(rbs);
|
free(rbs);
|
||||||
}
|
}
|
||||||
process->stack_table = RB_ROOT;
|
process->stack_table = RB_ROOT;
|
||||||
@ -765,7 +767,7 @@ void process_reset_allocations(struct process *process)
|
|||||||
process->tsc = 0;
|
process->tsc = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void process_reset(struct process *process)
|
void process_reset(struct process *process)
|
||||||
{
|
{
|
||||||
struct list_head *it, *next;
|
struct list_head *it, *next;
|
||||||
|
|
||||||
@ -808,10 +810,13 @@ void process_duplicate(struct process *process, struct process *copy)
|
|||||||
|
|
||||||
rb_iterate(©->block_table, process_rb_duplicate_block, process);
|
rb_iterate(©->block_table, process_rb_duplicate_block, process);
|
||||||
|
|
||||||
|
assert(copy->bytes_used == process->bytes_used);
|
||||||
|
assert(copy->n_allocations == process->n_allocations);
|
||||||
|
|
||||||
list_for_each(it, ©->map_list) {
|
list_for_each(it, ©->map_list) {
|
||||||
struct map *map = container_of(it, struct map, list);
|
struct map *map = container_of(it, struct map, list);
|
||||||
|
|
||||||
_process_add_map(process, map->addr, map->offset, map->size, map->filename, strlen(map->filename));
|
_process_add_map(process, map->addr, map->offset, map->size, map->filename, strlen(map->filename), map->binfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
process->total_allocations = copy->total_allocations;
|
process->total_allocations = copy->total_allocations;
|
||||||
@ -916,7 +921,7 @@ static void _process_dump(struct process *process, int (*sortby)(const struct rb
|
|||||||
|
|
||||||
assert(i == process->stack_trees);
|
assert(i == process->stack_trees);
|
||||||
|
|
||||||
qsort(arr, process->stack_trees, sizeof(struct stack *), (void *)sortby);
|
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 = process->stack_trees / 2;
|
||||||
@ -933,7 +938,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 < process->stack_trees; ++i) {
|
||||||
struct rb_stack *stack = arr[i];
|
struct rb_stack *stack = arr[i];
|
||||||
|
|
||||||
if (!stack->stack->ignore && !skipfunc(stack)) {
|
if (!skipfunc(stack)) {
|
||||||
if (dump_printf(
|
if (dump_printf(
|
||||||
"Stack (%s):\n"
|
"Stack (%s):\n"
|
||||||
" bytes used: %llu\n"
|
" bytes used: %llu\n"
|
||||||
@ -1232,7 +1237,7 @@ void process_alloc(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 *stack_data;
|
void *stack_data;
|
||||||
unsigned long stack_size;
|
unsigned long stack_size;
|
||||||
unsigned long ptr;
|
unsigned long ptr;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
@ -1343,11 +1348,10 @@ void process_exit(struct process *process)
|
|||||||
{
|
{
|
||||||
process_set_status(process, MT_PROCESS_EXIT);
|
process_set_status(process, MT_PROCESS_EXIT);
|
||||||
|
|
||||||
if (options.client || (!options.client && !options.verbose))
|
|
||||||
fprintf(stderr, "+++ process %d exited +++\n", process->pid);
|
|
||||||
|
|
||||||
if (!options.interactive)
|
if (!options.interactive)
|
||||||
process_dump_sortby(process);
|
process_dump_sortby(process);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "+++ process %d exited +++\n", process->pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_about_exit(struct process *process)
|
void process_about_exit(struct process *process)
|
||||||
@ -1373,12 +1377,6 @@ void process_detach(struct process *process)
|
|||||||
client_send_msg(process, MT_DETACH, NULL, 0);
|
client_send_msg(process, MT_DETACH, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_delete(struct process *process)
|
|
||||||
{
|
|
||||||
process_reset(process);
|
|
||||||
free(process);
|
|
||||||
}
|
|
||||||
|
|
||||||
void process_set_status(struct process *process, enum process_status status)
|
void process_set_status(struct process *process, enum process_status status)
|
||||||
{
|
{
|
||||||
process->status = status;
|
process->status = status;
|
||||||
@ -1457,6 +1455,9 @@ static void set_block(struct rb_block *block, void *data)
|
|||||||
struct block_helper *bh = data;
|
struct block_helper *bh = data;
|
||||||
unsigned long addr;
|
unsigned long addr;
|
||||||
|
|
||||||
|
if (block->stack_node->stack->ignore)
|
||||||
|
return;
|
||||||
|
|
||||||
if ((block->flags & bh->fmask) != 0)
|
if ((block->flags & bh->fmask) != 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@ -78,11 +78,11 @@ struct process {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct process *process_new(pid_t pid, unsigned int swap_endian, unsigned int tracing);
|
struct process *process_new(pid_t pid, unsigned int swap_endian, unsigned int tracing);
|
||||||
|
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);
|
||||||
void process_set_clone(struct process *process, struct process *clone);
|
void process_set_clone(struct process *process, struct process *clone);
|
||||||
struct process *process_clone_of(struct process *process);
|
struct process *process_clone_of(struct process *process);
|
||||||
void process_delete(struct process *process);
|
|
||||||
void process_duplicate(struct process *process, struct process *copy);
|
void process_duplicate(struct process *process, struct process *copy);
|
||||||
void process_run(struct process *process, const char *libpath, const char *path, char **args);
|
void process_run(struct process *process, const char *libpath, const char *path, char **args);
|
||||||
void process_set_status(struct process *process, enum process_status status);
|
void process_set_status(struct process *process, enum process_status status);
|
||||||
|
|||||||
@ -437,10 +437,12 @@ finish:
|
|||||||
free(argv);
|
free(argv);
|
||||||
free(linedup);
|
free(linedup);
|
||||||
|
|
||||||
|
if (quit)
|
||||||
|
rl_callback_handler_remove();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void split_search_patch(const char *str)
|
static void split_search_patch(const char *str)
|
||||||
{
|
{
|
||||||
struct opt_b_t *opt_b_last = NULL;
|
struct opt_b_t *opt_b_last = NULL;
|
||||||
@ -870,6 +872,7 @@ void readline_init(void)
|
|||||||
|
|
||||||
void readline_exit(void)
|
void readline_exit(void)
|
||||||
{
|
{
|
||||||
rl_callback_handler_remove();
|
if (!quit)
|
||||||
|
rl_callback_handler_remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -75,6 +75,9 @@
|
|||||||
/* Define to 1 if you have the `mkdir' function. */
|
/* Define to 1 if you have the `mkdir' function. */
|
||||||
#undef HAVE_MKDIR
|
#undef HAVE_MKDIR
|
||||||
|
|
||||||
|
/* Define to 1 if you have the `process_vm_readv' function. */
|
||||||
|
#undef HAVE_PROCESS_VM_READV
|
||||||
|
|
||||||
/* Define to 1 if you have the <pthread.h> header file. */
|
/* Define to 1 if you have the <pthread.h> header file. */
|
||||||
#undef HAVE_PTHREAD_H
|
#undef HAVE_PTHREAD_H
|
||||||
|
|
||||||
|
|||||||
6
config/autoconf/config.guess
vendored
6
config/autoconf/config.guess
vendored
@ -2,7 +2,7 @@
|
|||||||
# Attempt to guess a canonical system name.
|
# Attempt to guess a canonical system name.
|
||||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2015-03-04'
|
timestamp='2015-07-03'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
@ -221,7 +221,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
|
|||||||
release='-gnu'
|
release='-gnu'
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'`
|
release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
|
||||||
@ -1049,7 +1049,7 @@ EOF
|
|||||||
X86_64_ABI=x32
|
X86_64_ABI=x32
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
echo x86_64-unknown-linux-gnu${X86_64_ABI}
|
echo ${UNAME_MACHINE}-pc-linux-${LIBC}${X86_64_ABI}
|
||||||
exit ;;
|
exit ;;
|
||||||
xtensa*:Linux:*:*)
|
xtensa*:Linux:*:*)
|
||||||
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
|
||||||
|
|||||||
7
config/autoconf/config.sub
vendored
7
config/autoconf/config.sub
vendored
@ -2,7 +2,7 @@
|
|||||||
# Configuration validation subroutine script.
|
# Configuration validation subroutine script.
|
||||||
# Copyright 1992-2015 Free Software Foundation, Inc.
|
# Copyright 1992-2015 Free Software Foundation, Inc.
|
||||||
|
|
||||||
timestamp='2015-03-08'
|
timestamp='2015-07-28'
|
||||||
|
|
||||||
# This file is free software; you can redistribute it and/or modify it
|
# This file is free software; you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU General Public License as published by
|
# under the terms of the GNU General Public License as published by
|
||||||
@ -255,6 +255,7 @@ case $basic_machine in
|
|||||||
| arc | arceb \
|
| arc | arceb \
|
||||||
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
|
||||||
| avr | avr32 \
|
| avr | avr32 \
|
||||||
|
| ba \
|
||||||
| be32 | be64 \
|
| be32 | be64 \
|
||||||
| bfin \
|
| bfin \
|
||||||
| c4x | c8051 | clipper \
|
| c4x | c8051 | clipper \
|
||||||
@ -376,6 +377,7 @@ case $basic_machine in
|
|||||||
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
|
||||||
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
|
||||||
| avr-* | avr32-* \
|
| avr-* | avr32-* \
|
||||||
|
| ba-* \
|
||||||
| be32-* | be64-* \
|
| be32-* | be64-* \
|
||||||
| bfin-* | bs2000-* \
|
| bfin-* | bs2000-* \
|
||||||
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
| c[123]* | c30-* | [cjt]90-* | c4x-* \
|
||||||
@ -428,12 +430,13 @@ case $basic_machine in
|
|||||||
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
|
||||||
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
|
||||||
| pyramid-* \
|
| pyramid-* \
|
||||||
|
| riscv32-* | riscv64-* \
|
||||||
| rl78-* | romp-* | rs6000-* | rx-* \
|
| rl78-* | romp-* | rs6000-* | rx-* \
|
||||||
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
|
||||||
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
|
||||||
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
|
||||||
| sparclite-* \
|
| sparclite-* \
|
||||||
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
|
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
|
||||||
| tahoe-* \
|
| tahoe-* \
|
||||||
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
|
||||||
| tile*-* \
|
| tile*-* \
|
||||||
|
|||||||
23
configure
vendored
23
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 0.1.
|
# Generated by GNU Autoconf 2.69 for mtrace 0.2.
|
||||||
#
|
#
|
||||||
# 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'
|
PACKAGE_NAME='mtrace'
|
||||||
PACKAGE_TARNAME='mtrace'
|
PACKAGE_TARNAME='mtrace'
|
||||||
PACKAGE_VERSION='0.1'
|
PACKAGE_VERSION='0.2'
|
||||||
PACKAGE_STRING='mtrace 0.1'
|
PACKAGE_STRING='mtrace 0.2'
|
||||||
PACKAGE_BUGREPORT='stefani@seibold.net'
|
PACKAGE_BUGREPORT='stefani@seibold.net'
|
||||||
PACKAGE_URL=''
|
PACKAGE_URL=''
|
||||||
|
|
||||||
@ -1326,7 +1326,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 0.1 to adapt to many kinds of systems.
|
\`configure' configures mtrace 0.2 to adapt to many kinds of systems.
|
||||||
|
|
||||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||||
|
|
||||||
@ -1396,7 +1396,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 0.1:";;
|
short | recursive ) echo "Configuration of mtrace 0.2:";;
|
||||||
esac
|
esac
|
||||||
cat <<\_ACEOF
|
cat <<\_ACEOF
|
||||||
|
|
||||||
@ -1512,7 +1512,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 configure 0.1
|
mtrace configure 0.2
|
||||||
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.
|
||||||
@ -2118,7 +2118,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 $as_me 0.1, which was
|
It was created by mtrace $as_me 0.2, which was
|
||||||
generated by GNU Autoconf 2.69. Invocation command line was
|
generated by GNU Autoconf 2.69. Invocation command line was
|
||||||
|
|
||||||
$ $0 $@
|
$ $0 $@
|
||||||
@ -12000,7 +12000,7 @@ fi
|
|||||||
|
|
||||||
# Define the identity of the package.
|
# Define the identity of the package.
|
||||||
PACKAGE='mtrace'
|
PACKAGE='mtrace'
|
||||||
VERSION='0.1'
|
VERSION='0.2'
|
||||||
|
|
||||||
|
|
||||||
cat >>confdefs.h <<_ACEOF
|
cat >>confdefs.h <<_ACEOF
|
||||||
@ -12746,6 +12746,8 @@ else
|
|||||||
$as_echo "no" >&6; }
|
$as_echo "no" >&6; }
|
||||||
fi
|
fi
|
||||||
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
CPPFLAGS="${saved_CPPFLAGS}"
|
||||||
|
LDFLAGS="${saved_LDFLAGS}"
|
||||||
|
|
||||||
saved_CFLAGS="${CFLAGS}"
|
saved_CFLAGS="${CFLAGS}"
|
||||||
CFLAGS="${CFLAGS} -Wall -Werror"
|
CFLAGS="${CFLAGS} -Wall -Werror"
|
||||||
@ -13206,6 +13208,7 @@ for ac_func in \
|
|||||||
strerror \
|
strerror \
|
||||||
strtol \
|
strtol \
|
||||||
strtoul \
|
strtoul \
|
||||||
|
process_vm_readv \
|
||||||
|
|
||||||
do :
|
do :
|
||||||
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
|
||||||
@ -13799,7 +13802,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 $as_me 0.1, which was
|
This file was extended by mtrace $as_me 0.2, 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
|
||||||
@ -13865,7 +13868,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 config.status 0.1
|
mtrace config.status 0.2
|
||||||
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],[0.1],[stefani@seibold.net])
|
AC_INIT([mtrace],[0.2],[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])
|
||||||
@ -152,6 +152,8 @@ int main () {
|
|||||||
AC_DEFINE([HAVE_ELF_C_READ_MMAP], [1], [we have read mmap support])
|
AC_DEFINE([HAVE_ELF_C_READ_MMAP], [1], [we have read mmap support])
|
||||||
AC_MSG_RESULT([yes])],[
|
AC_MSG_RESULT([yes])],[
|
||||||
AC_MSG_RESULT([no])])
|
AC_MSG_RESULT([no])])
|
||||||
|
CPPFLAGS="${saved_CPPFLAGS}"
|
||||||
|
LDFLAGS="${saved_LDFLAGS}"
|
||||||
|
|
||||||
saved_CFLAGS="${CFLAGS}"
|
saved_CFLAGS="${CFLAGS}"
|
||||||
CFLAGS="${CFLAGS} -Wall -Werror"
|
CFLAGS="${CFLAGS} -Wall -Werror"
|
||||||
@ -214,6 +216,7 @@ AC_CHECK_FUNCS([ \
|
|||||||
strerror \
|
strerror \
|
||||||
strtol \
|
strtol \
|
||||||
strtoul \
|
strtoul \
|
||||||
|
process_vm_readv \
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
137
dwarf.c
137
dwarf.c
@ -470,7 +470,7 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
{
|
{
|
||||||
struct dwarf_addr_space *indirect_as = as;
|
struct dwarf_addr_space *indirect_as = as;
|
||||||
arch_addr_t val, initial_addr = *addr;
|
arch_addr_t val, initial_addr = *addr;
|
||||||
arch_addr_t gp = as->cursor.lib->gp;
|
arch_addr_t gp = as->cursor.libref->gp;
|
||||||
int is_64bit = as->is_64bit;
|
int is_64bit = as->is_64bit;
|
||||||
void *tmp_ptr;
|
void *tmp_ptr;
|
||||||
int ret;
|
int ret;
|
||||||
@ -486,12 +486,12 @@ static int dwarf_read_encoded_pointer(struct dwarf_addr_space *as, int local,
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct library *lib = c->lib;
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
if (*addr < ARCH_ADDR_T(lib->image_addr))
|
if (*addr < ARCH_ADDR_T(libref->image_addr))
|
||||||
fatal("invalid access mem: addr %#lx < %p", *addr, lib->image_addr);
|
fatal("invalid access mem: addr %#lx < %p", *addr, libref->image_addr);
|
||||||
if (*addr >= ARCH_ADDR_T(lib->image_addr + lib->load_size))
|
if (*addr >= ARCH_ADDR_T(libref->image_addr + libref->load_size))
|
||||||
fatal("invalid access mem: addr %#lx >= %p", *addr, lib->image_addr + lib->load_size);
|
fatal("invalid access mem: addr %#lx >= %p", *addr, libref->image_addr + libref->load_size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
memset(&tmp, 0, sizeof(tmp));
|
memset(&tmp, 0, sizeof(tmp));
|
||||||
@ -877,9 +877,9 @@ static int dwarf_extract_cfi_from_fde(struct dwarf_addr_space *as, void *addrp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int lib_addr_match(struct library *lib, arch_addr_t ip)
|
static inline int lib_addr_match(struct libref *libref, arch_addr_t ip)
|
||||||
{
|
{
|
||||||
return ip >= lib->load_addr && ip < lib->load_addr + lib->load_size;
|
return ip >= libref->load_addr && ip < libref->load_addr + libref->load_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -888,25 +888,28 @@ int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip)
|
|||||||
struct task *leader;
|
struct task *leader;
|
||||||
struct list_head *it;
|
struct list_head *it;
|
||||||
|
|
||||||
if (as->cursor.lib) {
|
if (c->use_prev_instr)
|
||||||
if (lib_addr_match(as->cursor.lib, ip))
|
ip -= 1;
|
||||||
|
|
||||||
|
if (as->cursor.libref) {
|
||||||
|
if (lib_addr_match(as->cursor.libref, ip))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
leader = c->task->leader;
|
leader = c->task->leader;
|
||||||
|
|
||||||
as->cursor.lib = NULL;
|
as->cursor.libref = NULL;
|
||||||
|
|
||||||
list_for_each(it, &leader->libraries_list) {
|
list_for_each(it, &leader->libraries_list) {
|
||||||
struct library *lib = container_of(it, struct library, list);
|
struct libref *libref = container_of(it, struct library, list)->libref;
|
||||||
|
|
||||||
if (lib_addr_match(lib, ip)) {
|
if (lib_addr_match(libref, ip)) {
|
||||||
as->cursor.lib = lib;
|
as->cursor.libref = libref;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!as->cursor.lib) {
|
if (!as->cursor.libref) {
|
||||||
debug(DEBUG_DWARF, "no mapping found for IP %#lx", ip);
|
debug(DEBUG_DWARF, "no mapping found for IP %#lx", ip);
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
}
|
}
|
||||||
@ -947,21 +950,21 @@ static int dwarf_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip
|
|||||||
void *fde_addr;
|
void *fde_addr;
|
||||||
int ret;
|
int ret;
|
||||||
struct dwarf_cie_info *dci = &as->cursor.dci;
|
struct dwarf_cie_info *dci = &as->cursor.dci;
|
||||||
struct library *lib = as->cursor.lib;
|
struct libref *libref = as->cursor.libref;
|
||||||
|
|
||||||
e = lookup(table_data, table_len, ip - lib->load_addr - lib->seg_offset);
|
e = lookup(table_data, table_len, ip - libref->load_addr - libref->seg_offset);
|
||||||
if (!e) {
|
if (!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;
|
||||||
}
|
}
|
||||||
|
|
||||||
fde_addr = lib->image_addr - lib->load_offset + e->fde_offset + lib->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 ((ret = dwarf_extract_cfi_from_fde(as, fde_addr)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
dci->start_ip -= ARCH_ADDR_T(lib->image_addr) - lib->load_addr;
|
dci->start_ip -= ARCH_ADDR_T(libref->image_addr) - libref->load_addr;
|
||||||
|
|
||||||
if (!as->is_64bit)
|
if (!as->is_64bit)
|
||||||
dci->start_ip &= 0xffffffff;
|
dci->start_ip &= 0xffffffff;
|
||||||
@ -1824,10 +1827,10 @@ static int apply_reg_state(struct dwarf_addr_space *as, struct dwarf_reg_state *
|
|||||||
static int fetch_proc_info(struct dwarf_addr_space *as, arch_addr_t ip)
|
static int fetch_proc_info(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct library *lib = c->lib;
|
struct libref *libref = c->libref;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = dwarf_search_unwind_table(as, ip, lib->table_data, lib->table_len);
|
ret = dwarf_search_unwind_table(as, ip, libref->table_data, libref->table_len);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@ -1840,13 +1843,14 @@ static int fetch_proc_info(struct dwarf_addr_space *as, arch_addr_t ip)
|
|||||||
int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task)
|
int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
|
int ret;
|
||||||
|
|
||||||
c->cfa = 0;
|
c->cfa = 0;
|
||||||
c->ip = 0;
|
c->ip = 0;
|
||||||
c->ret_addr_column = 0;
|
c->ret_addr_column = 0;
|
||||||
c->use_prev_instr = 0;
|
c->use_prev_instr = 0;
|
||||||
c->valid = 1;
|
c->valid = 1;
|
||||||
c->lib = NULL;
|
c->libref = NULL;
|
||||||
c->task = task;
|
c->task = task;
|
||||||
|
|
||||||
as->addr = 0;
|
as->addr = 0;
|
||||||
@ -1854,7 +1858,11 @@ int dwarf_init_unwind(struct dwarf_addr_space *as, struct task *task)
|
|||||||
|
|
||||||
memset(&c->dci, 0, sizeof(c->dci));
|
memset(&c->dci, 0, sizeof(c->dci));
|
||||||
|
|
||||||
return dwarf_arch_init_unwind(as);
|
ret = dwarf_arch_init_unwind(as);
|
||||||
|
if (!ret)
|
||||||
|
ret = dwarf_locate_map(as, c->ip);
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *dwarf_init(int is_64bit)
|
void *dwarf_init(int is_64bit)
|
||||||
@ -1887,6 +1895,18 @@ void dwarf_destroy(struct dwarf_addr_space *as)
|
|||||||
free(as);
|
free(as);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef GUESS_CALLER
|
||||||
|
static arch_addr_t get32val(unsigned char *buf)
|
||||||
|
{
|
||||||
|
return *(uint32_t *)buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static arch_addr_t get64val(unsigned char *buf)
|
||||||
|
{
|
||||||
|
return *(uint64_t *)buf;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int dwarf_step(struct dwarf_addr_space *as)
|
int dwarf_step(struct dwarf_addr_space *as)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1900,6 +1920,10 @@ int dwarf_step(struct dwarf_addr_space *as)
|
|||||||
ip = c->ip;
|
ip = c->ip;
|
||||||
cfa = c->cfa;
|
cfa = c->cfa;
|
||||||
|
|
||||||
|
ret = dwarf_locate_map(as, ip);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
/* 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
|
||||||
to resume execution (e.g. after signal frame).
|
to resume execution (e.g. after signal frame).
|
||||||
@ -1918,10 +1942,6 @@ int dwarf_step(struct dwarf_addr_space *as)
|
|||||||
if (c->use_prev_instr)
|
if (c->use_prev_instr)
|
||||||
--ip;
|
--ip;
|
||||||
|
|
||||||
ret = dwarf_locate_map(as, ip);
|
|
||||||
if (ret < 0)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ret = fetch_proc_info(as, ip);
|
ret = fetch_proc_info(as, ip);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -1936,34 +1956,57 @@ int dwarf_step(struct dwarf_addr_space *as)
|
|||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
return 0;
|
ret = dwarf_locate_map(as, c->ip);
|
||||||
|
if (ret < 0)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
|
c->ip = ip;
|
||||||
|
|
||||||
if (ret == -DWARF_ENOINFO) {
|
if (ret == -DWARF_ENOINFO) {
|
||||||
debug(DEBUG_DWARF, "try arch specific step");
|
debug(DEBUG_DWARF, "try arch specific step");
|
||||||
|
|
||||||
ret = dwarf_arch_step(as);
|
ret = dwarf_arch_step(as);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
if (dwarf_locate_map(as, c->use_prev_instr ? c->ip - 1 : c->ip))
|
if (dwarf_locate_map(as, c->ip) < 0)
|
||||||
ret = -DWARF_ENOINFO;
|
ret = -DWARF_ENOINFO;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
unsigned int i;
|
#ifdef GUESS_CALLER
|
||||||
|
ssize_t n;
|
||||||
|
unsigned char buf[4096];
|
||||||
|
|
||||||
for(i = 0; i < 16; ++i) {
|
n = copy_from_proc(c->task, cfa, &buf, ARRAY_SIZE(buf));
|
||||||
if (dwarf_readw(as, &cfa, &ip, as->is_64bit))
|
if (n > 0) {
|
||||||
break;
|
arch_addr_t (*getval)(unsigned char *buf);
|
||||||
|
ssize_t i;
|
||||||
|
ssize_t addr_size = DWARF_ADDR_SIZE(as);
|
||||||
|
|
||||||
if (!dwarf_locate_map(as, ip)) {
|
if (addr_size == 8)
|
||||||
c->cfa = cfa;
|
getval = get64val;
|
||||||
c->ip = ip;
|
else
|
||||||
|
getval = get32val;
|
||||||
|
|
||||||
return 0;
|
for(i = 0; i + addr_size <= n ; i += addr_size) {
|
||||||
|
ip = getval(&buf[i]);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
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->ip = ip;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
debug(DEBUG_DWARF, "error %d", ret);
|
debug(DEBUG_DWARF, "error %d", ret);
|
||||||
|
|
||||||
c->valid = 0;
|
c->valid = 0;
|
||||||
@ -1982,7 +2025,7 @@ arch_addr_t dwarf_get_ip(struct dwarf_addr_space *as)
|
|||||||
return c->ip;
|
return c->ip;
|
||||||
}
|
}
|
||||||
|
|
||||||
int dwarf_get_unwind_table(struct task *task, struct library *lib, 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;
|
||||||
int ret;
|
int ret;
|
||||||
@ -1991,7 +2034,7 @@ int dwarf_get_unwind_table(struct task *task, struct library *lib, struct dwarf_
|
|||||||
memset(&tmp_as, 0, sizeof(tmp_as));
|
memset(&tmp_as, 0, sizeof(tmp_as));
|
||||||
|
|
||||||
tmp_as.is_64bit = task->is_64bit;
|
tmp_as.is_64bit = task->is_64bit;
|
||||||
tmp_as.cursor.lib = lib;
|
tmp_as.cursor.libref = libref;
|
||||||
tmp_as.cursor.task = task;
|
tmp_as.cursor.task = task;
|
||||||
|
|
||||||
if (hdr->version != DW_EH_VERSION) {
|
if (hdr->version != DW_EH_VERSION) {
|
||||||
@ -2014,9 +2057,19 @@ int dwarf_get_unwind_table(struct task *task, struct library *lib, struct dwarf_
|
|||||||
return -DWARF_EINVAL;
|
return -DWARF_EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
lib->table_data = (void *)addr;
|
libref->table_data = (void *)addr;
|
||||||
lib->table_len = fde_count;
|
libref->table_len = fde_count;
|
||||||
|
|
||||||
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
7
dwarf.h
7
dwarf.h
@ -89,7 +89,7 @@ struct dwarf_cursor {
|
|||||||
arch_addr_t ret_addr_column; /* column for return-address */
|
arch_addr_t ret_addr_column; /* column for return-address */
|
||||||
unsigned int use_prev_instr:1; /* use previous (= call) or current (= signal) instruction? */
|
unsigned int use_prev_instr:1; /* use previous (= call) or current (= signal) instruction? */
|
||||||
unsigned int valid:1;
|
unsigned int valid:1;
|
||||||
struct library *lib;
|
struct libref *libref;
|
||||||
struct dwarf_cie_info dci;
|
struct dwarf_cie_info dci;
|
||||||
struct dwarf_loc *loc;
|
struct dwarf_loc *loc;
|
||||||
};
|
};
|
||||||
@ -119,12 +119,15 @@ int dwarf_locate_map(struct dwarf_addr_space *as, arch_addr_t ip);
|
|||||||
|
|
||||||
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
|
int dwarf_get(struct dwarf_addr_space *as, struct dwarf_loc loc, arch_addr_t *valp);
|
||||||
|
|
||||||
int dwarf_get_unwind_table(struct task *task, struct library *lib, 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);
|
||||||
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg);
|
int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg);
|
||||||
|
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);
|
||||||
|
|||||||
90
event.c
90
event.c
@ -61,12 +61,6 @@ void queue_event(struct task *task)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wait_for_event(struct task *task)
|
|
||||||
{
|
|
||||||
while(task->event.type == EVENT_NONE)
|
|
||||||
queue_event(wait_event());
|
|
||||||
}
|
|
||||||
|
|
||||||
struct task *next_event(void)
|
struct task *next_event(void)
|
||||||
{
|
{
|
||||||
if (!list_empty(&event_head)) {
|
if (!list_empty(&event_head)) {
|
||||||
@ -113,7 +107,7 @@ static void show_clone(struct task *task, enum event_type type)
|
|||||||
fprintf(stderr, "+++ process pid=%d %s (newpid=%d) +++\n", task->pid, str, task->event.e_un.newpid);
|
fprintf(stderr, "+++ process pid=%d %s (newpid=%d) +++\n", task->pid, str, task->event.e_un.newpid);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_clone(struct task *task, enum event_type type)
|
static void handle_clone(struct task *task, enum event_type type)
|
||||||
{
|
{
|
||||||
struct task *newtask;
|
struct task *newtask;
|
||||||
int newpid = task->event.e_un.newpid;
|
int newpid = task->event.e_un.newpid;
|
||||||
@ -135,7 +129,7 @@ static struct task *handle_clone(struct task *task, enum event_type type)
|
|||||||
|
|
||||||
if (!options.follow) {
|
if (!options.follow) {
|
||||||
remove_proc(newtask);
|
remove_proc(newtask);
|
||||||
return task;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
report_fork(newtask, task);
|
report_fork(newtask, task);
|
||||||
@ -147,21 +141,23 @@ static struct task *handle_clone(struct task *task, enum event_type type)
|
|||||||
|
|
||||||
continue_task(newtask, newtask->event.e_un.signum);
|
continue_task(newtask, newtask->event.e_un.signum);
|
||||||
|
|
||||||
return task;
|
return;
|
||||||
fail:
|
fail:
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error during init of tracing process %d\n"
|
"Error during init of tracing process %d\n"
|
||||||
"This process won't be traced.\n",
|
"This process won't be traced.\n",
|
||||||
newpid
|
newpid
|
||||||
);
|
);
|
||||||
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_signal(struct task *task)
|
static void handle_signal(struct task *task)
|
||||||
{
|
{
|
||||||
|
if (options.verbose > 1) {
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
continue_task(task, task->event.e_un.signum);
|
continue_task(task, task->event.e_un.signum);
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_exit(struct task *task)
|
static void show_exit(struct task *task)
|
||||||
@ -171,17 +167,18 @@ static void show_exit(struct task *task)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_about_exit(struct task *task)
|
static void handle_about_exit(struct task *task)
|
||||||
{
|
{
|
||||||
if (task->leader == task)
|
if (task->leader == task) {
|
||||||
report_about_exit(task);
|
if (report_about_exit(task) != -1) {
|
||||||
else
|
task->about_exit = 1;
|
||||||
continue_task(task, 0);
|
return;
|
||||||
|
}
|
||||||
return task;
|
}
|
||||||
|
continue_task(task, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_exit(struct task *task)
|
static void handle_exit(struct task *task)
|
||||||
{
|
{
|
||||||
show_exit(task);
|
show_exit(task);
|
||||||
|
|
||||||
@ -189,13 +186,12 @@ static struct task *handle_exit(struct task *task)
|
|||||||
report_exit(task);
|
report_exit(task);
|
||||||
remove_proc(task);
|
remove_proc(task);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
remove_task(task);
|
remove_task(task);
|
||||||
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_exit_signal(struct task *task)
|
static void handle_exit_signal(struct task *task)
|
||||||
{
|
{
|
||||||
if (options.verbose)
|
if (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);
|
||||||
@ -204,13 +200,12 @@ static struct task *handle_exit_signal(struct task *task)
|
|||||||
report_exit(task);
|
report_exit(task);
|
||||||
remove_proc(task);
|
remove_proc(task);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
remove_task(task);
|
remove_task(task);
|
||||||
|
}
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *handle_exec(struct task *task)
|
static void handle_exec(struct task *task)
|
||||||
{
|
{
|
||||||
debug(DEBUG_FUNCTION, "pid=%d", task->pid);
|
debug(DEBUG_FUNCTION, "pid=%d", task->pid);
|
||||||
|
|
||||||
@ -226,12 +221,11 @@ static struct task *handle_exec(struct task *task)
|
|||||||
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);
|
||||||
return task;
|
return;
|
||||||
nofollow:
|
nofollow:
|
||||||
report_nofollow(task);
|
report_nofollow(task);
|
||||||
untrace:
|
untrace:
|
||||||
remove_proc(task);
|
remove_proc(task);
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_call_after(struct task *task, struct breakpoint *bp)
|
static int handle_call_after(struct task *task, struct breakpoint *bp)
|
||||||
@ -247,12 +241,22 @@ static int handle_call_after(struct task *task, struct breakpoint *bp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct task *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;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
debug(DEBUG_FUNCTION, "pid=%d, addr=%#lx", task->pid, bp->addr);
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
if (bp->type >= BP_HW) {
|
||||||
|
if (++bp->hwcnt >= (BP_REORDER_THRESHOLD << bp->hw))
|
||||||
|
reorder_hw_bp(task);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (options.verbose)
|
||||||
|
++bp->count;
|
||||||
|
|
||||||
if (bp->deleted) {
|
if (bp->deleted) {
|
||||||
struct breakpoint *nbp = breakpoint_find(task, bp->addr);
|
struct breakpoint *nbp = breakpoint_find(task, bp->addr);
|
||||||
|
|
||||||
@ -264,7 +268,7 @@ static struct task *handle_breakpoint(struct task *task)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (task->skip_bp == bp) {
|
if (task->skip_bp == bp) {
|
||||||
breakpoint_unref(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;
|
||||||
@ -281,7 +285,7 @@ static struct task *handle_breakpoint(struct task *task)
|
|||||||
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, HW_BP_SCRATCH);
|
task->breakpoint = breakpoint_insert(task, get_return_addr(task), NULL, BP_HW_SCRATCH);
|
||||||
if (task->breakpoint) {
|
if (task->breakpoint) {
|
||||||
task->libsym = libsym;
|
task->libsym = libsym;
|
||||||
task->breakpoint->on_hit = handle_call_after;
|
task->breakpoint->on_hit = handle_call_after;
|
||||||
@ -298,9 +302,7 @@ static struct task *handle_breakpoint(struct task *task)
|
|||||||
skip_breakpoint(task, bp);
|
skip_breakpoint(task, bp);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
breakpoint_unref(bp);
|
breakpoint_put(bp);
|
||||||
|
|
||||||
return task;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int handle_event(void)
|
int handle_event(void)
|
||||||
@ -322,33 +324,33 @@ int handle_event(void)
|
|||||||
break;
|
break;
|
||||||
case EVENT_SIGNAL:
|
case EVENT_SIGNAL:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event signal %d", task->pid, event->e_un.signum);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event signal %d", task->pid, event->e_un.signum);
|
||||||
task = handle_signal(task);
|
handle_signal(task);
|
||||||
break;
|
break;
|
||||||
case EVENT_ABOUT_EXIT:
|
case EVENT_ABOUT_EXIT:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
|
||||||
task = handle_about_exit(task);
|
handle_about_exit(task);
|
||||||
break;
|
break;
|
||||||
case EVENT_EXIT:
|
case EVENT_EXIT:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit %d", task->pid, event->e_un.ret_val);
|
||||||
task = handle_exit(task);
|
handle_exit(task);
|
||||||
break;
|
break;
|
||||||
case EVENT_EXIT_SIGNAL:
|
case EVENT_EXIT_SIGNAL:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit signal %d", task->pid, event->e_un.signum);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exit signal %d", task->pid, event->e_un.signum);
|
||||||
task = handle_exit_signal(task);
|
handle_exit_signal(task);
|
||||||
break;
|
break;
|
||||||
case EVENT_FORK:
|
case EVENT_FORK:
|
||||||
case EVENT_VFORK:
|
case EVENT_VFORK:
|
||||||
case EVENT_CLONE:
|
case EVENT_CLONE:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event clone (%u)", task->pid, event->e_un.newpid);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event clone (%u)", task->pid, event->e_un.newpid);
|
||||||
task = handle_clone(task, type);
|
handle_clone(task, type);
|
||||||
break;
|
break;
|
||||||
case EVENT_EXEC:
|
case EVENT_EXEC:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exec()", task->pid);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event exec()", task->pid);
|
||||||
task = handle_exec(task);
|
handle_exec(task);
|
||||||
break;
|
break;
|
||||||
case EVENT_BREAKPOINT:
|
case EVENT_BREAKPOINT:
|
||||||
debug(DEBUG_EVENT_HANDLER, "pid=%d, event breakpoint %#lx", task->pid, event->e_un.breakpoint->addr);
|
debug(DEBUG_EVENT_HANDLER, "pid=%d, event breakpoint %#lx", task->pid, event->e_un.breakpoint->addr);
|
||||||
task = handle_breakpoint(task);
|
handle_breakpoint(task);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Error! unknown event?\n");
|
fprintf(stderr, "Error! unknown event?\n");
|
||||||
|
|||||||
1
event.h
1
event.h
@ -53,7 +53,6 @@ struct event {
|
|||||||
void init_event(struct task *task);
|
void init_event(struct task *task);
|
||||||
void remove_event(struct task *task);
|
void remove_event(struct task *task);
|
||||||
struct task *next_event(void);
|
struct task *next_event(void);
|
||||||
void wait_for_event(struct task *task);
|
|
||||||
void queue_event(struct task *task);
|
void queue_event(struct task *task);
|
||||||
int handle_event(void);
|
int handle_event(void);
|
||||||
|
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
struct event;
|
struct event;
|
||||||
struct task;
|
struct task;
|
||||||
struct breakpoint;
|
struct breakpoint;
|
||||||
|
struct libref;
|
||||||
struct library;
|
struct library;
|
||||||
struct library_symbol;
|
struct library_symbol;
|
||||||
struct mt_elf;
|
struct mt_elf;
|
||||||
|
|||||||
238
library.c
238
library.c
@ -38,126 +38,107 @@
|
|||||||
#include "server.h"
|
#include "server.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
struct library_symbol *library_symbol_new(struct library *lib, arch_addr_t addr, const struct function *func)
|
struct libref *libref_new(unsigned int type)
|
||||||
|
{
|
||||||
|
struct libref *libref = malloc(sizeof(*libref));
|
||||||
|
|
||||||
|
if (!libref)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset(libref, 0, sizeof(*libref));
|
||||||
|
|
||||||
|
libref->refcnt = 0;
|
||||||
|
libref->type = type;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&libref->sym_list);
|
||||||
|
|
||||||
|
return libref;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void libref_delete(struct libref *libref)
|
||||||
|
{
|
||||||
|
struct list_head *it, *next;
|
||||||
|
|
||||||
|
list_for_each_safe(it, next, &libref->sym_list) {
|
||||||
|
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
||||||
|
|
||||||
|
list_del(&sym->list);
|
||||||
|
free(sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libref->image_addr)
|
||||||
|
munmap(libref->image_addr, libref->load_size);
|
||||||
|
|
||||||
|
free((void *)libref->filename);
|
||||||
|
free(libref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void libref_put(struct libref *libref)
|
||||||
|
{
|
||||||
|
assert(libref->refcnt != 0);
|
||||||
|
|
||||||
|
if (!--libref->refcnt)
|
||||||
|
libref_delete(libref);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct libref *libref_get(struct libref *libref)
|
||||||
|
{
|
||||||
|
assert(libref);
|
||||||
|
|
||||||
|
++libref->refcnt;
|
||||||
|
|
||||||
|
return libref;
|
||||||
|
}
|
||||||
|
|
||||||
|
void libref_set_filename(struct libref *libref, const char *new_name)
|
||||||
|
{
|
||||||
|
free((void *)libref->filename);
|
||||||
|
libref->filename = new_name ? strdup(new_name) : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t addr, const struct function *func)
|
||||||
{
|
{
|
||||||
struct library_symbol *libsym = malloc(sizeof(*libsym));
|
struct library_symbol *libsym = malloc(sizeof(*libsym));
|
||||||
|
|
||||||
if (!libsym)
|
if (!libsym)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&libsym->list);
|
libsym->libref = libref;
|
||||||
libsym->lib = NULL;
|
|
||||||
libsym->func = func;
|
libsym->func = func;
|
||||||
libsym->addr = addr;
|
libsym->addr = addr;
|
||||||
|
|
||||||
list_add_tail(&libsym->list, &lib->sym_list);
|
list_add_tail(&libsym->list, &libref->sym_list);
|
||||||
|
|
||||||
return libsym;
|
return libsym;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void library_symbol_destroy(struct task *task, struct library_symbol *libsym)
|
void library_delete(struct task *task, struct library *lib)
|
||||||
{
|
|
||||||
struct breakpoint *bp = breakpoint_find(task, libsym->addr);
|
|
||||||
|
|
||||||
if (bp)
|
|
||||||
breakpoint_delete(task, bp);
|
|
||||||
|
|
||||||
list_del(&libsym->list);
|
|
||||||
free(libsym);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct library_symbol *library_symbol_clone(struct library *lib, struct library_symbol *libsym)
|
|
||||||
{
|
|
||||||
struct library_symbol *retp = library_symbol_new(lib, libsym->addr, libsym->func);
|
|
||||||
if (!retp)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return retp;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct library *library_new(void)
|
|
||||||
{
|
|
||||||
struct library *lib = malloc(sizeof(*lib));
|
|
||||||
|
|
||||||
if (lib == NULL)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
memset(lib, 0, sizeof(*lib));
|
|
||||||
|
|
||||||
INIT_LIST_HEAD(&lib->list);
|
|
||||||
INIT_LIST_HEAD(&lib->sym_list);
|
|
||||||
|
|
||||||
return lib;
|
|
||||||
}
|
|
||||||
|
|
||||||
void library_destroy(struct task *task, struct library *lib)
|
|
||||||
{
|
{
|
||||||
if (lib == NULL)
|
if (lib == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
struct list_head *it, *next;
|
struct list_head *it, *next;
|
||||||
|
struct libref *libref = lib->libref;
|
||||||
|
|
||||||
list_for_each_safe(it, next, &lib->sym_list) {
|
list_for_each_safe(it, next, &libref->sym_list) {
|
||||||
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
struct breakpoint *bp = breakpoint_find(task, container_of(it, struct library_symbol, list)->addr);
|
||||||
|
|
||||||
library_symbol_destroy(task, sym);
|
if (bp)
|
||||||
|
breakpoint_delete(task, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&lib->list);
|
list_del(&lib->list);
|
||||||
|
|
||||||
if (lib->image_addr)
|
|
||||||
munmap(lib->image_addr, lib->load_size);
|
|
||||||
|
|
||||||
free(lib);
|
free(lib);
|
||||||
|
|
||||||
|
libref_put(libref);
|
||||||
}
|
}
|
||||||
|
|
||||||
void library_set_filename(struct library *lib, const char *new_name)
|
struct library_symbol *library_find_symbol(struct libref *libref, arch_addr_t addr)
|
||||||
{
|
|
||||||
free((void *)lib->filename);
|
|
||||||
lib->filename = new_name ? strdup(new_name) : NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct library *library_clone(struct task *clone, struct library *lib)
|
|
||||||
{
|
|
||||||
struct list_head *it;
|
|
||||||
struct library *retp = library_new();
|
|
||||||
|
|
||||||
if (!retp)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
library_set_filename(retp, lib->filename);
|
|
||||||
|
|
||||||
retp->key = lib->key;
|
|
||||||
|
|
||||||
/* Clone symbols. */
|
|
||||||
list_for_each(it, &lib->sym_list) {
|
|
||||||
if (!library_symbol_clone(retp, container_of(it, struct library_symbol, list)))
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return retp;
|
|
||||||
fail:
|
|
||||||
/* Release what we managed to allocate. */
|
|
||||||
library_destroy(clone, retp);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void library_each_symbol(struct library *lib, void (*cb)(struct library_symbol *, void *), void *data)
|
|
||||||
{
|
|
||||||
struct list_head *it, *next;
|
|
||||||
|
|
||||||
list_for_each_safe(it, next, &lib->sym_list) {
|
|
||||||
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
|
||||||
|
|
||||||
(*cb) (sym, data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct library_symbol *library_find_symbol(struct library *lib, arch_addr_t addr)
|
|
||||||
{
|
{
|
||||||
struct list_head *it;
|
struct list_head *it;
|
||||||
|
|
||||||
list_for_each(it, &lib->sym_list) {
|
list_for_each(it, &libref->sym_list) {
|
||||||
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
||||||
|
|
||||||
if (sym->addr == addr)
|
if (sym->addr == addr)
|
||||||
@ -166,21 +147,6 @@ struct library_symbol *library_find_symbol(struct library *lib, arch_addr_t addr
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct library_symbol *find_symbol(struct task *leader, arch_addr_t addr)
|
|
||||||
{
|
|
||||||
/* Clone symbols first so that we can clone and relink breakpoints. */
|
|
||||||
struct list_head *it;
|
|
||||||
|
|
||||||
list_for_each(it, &leader->libraries_list) {
|
|
||||||
struct library *lib = container_of(it, struct library, list);
|
|
||||||
struct library_symbol *libsym = library_find_symbol(lib, addr);
|
|
||||||
|
|
||||||
if (libsym)
|
|
||||||
return libsym;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct library *library_find_with_key(struct list_head *list, arch_addr_t key)
|
struct library *library_find_with_key(struct list_head *list, arch_addr_t key)
|
||||||
{
|
{
|
||||||
struct list_head *it;
|
struct list_head *it;
|
||||||
@ -188,7 +154,7 @@ struct library *library_find_with_key(struct list_head *list, arch_addr_t key)
|
|||||||
list_for_each(it, list) {
|
list_for_each(it, list) {
|
||||||
struct library *lib = container_of(it, struct library, list);
|
struct library *lib = container_of(it, struct library, list);
|
||||||
|
|
||||||
if (lib->key == key)
|
if (lib->libref->key == key)
|
||||||
return lib;
|
return lib;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -200,13 +166,14 @@ void library_delete_list(struct task *leader, struct list_head *list)
|
|||||||
|
|
||||||
list_for_each_safe(it, next, list) {
|
list_for_each_safe(it, next, list) {
|
||||||
struct library *lib = container_of(it, struct library, list);
|
struct library *lib = container_of(it, struct library, list);
|
||||||
|
struct libref *libref = lib->libref;
|
||||||
|
|
||||||
debug(DEBUG_FUNCTION, "%s@%#lx", lib->filename, lib->base);
|
debug(DEBUG_FUNCTION, "%s@%#lx", libref->filename, libref->base);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (options.verbose > 1)
|
||||||
fprintf(stderr, "+++ library del pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, lib->filename, lib->base, lib->load_addr, lib->load_addr + lib->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_destroy(leader, lib);
|
library_delete(leader, lib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,7 +189,7 @@ static void cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
|
|||||||
bp->libsym = libsym;
|
bp->libsym = libsym;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bp = breakpoint_new(task, addr, libsym, libsym->func->hw_bp_min <= HW_BREAKPOINTS ? HW_BP : SW_BP);
|
bp = breakpoint_new(task, addr, libsym, BP_AUTO);
|
||||||
if (!bp)
|
if (!bp)
|
||||||
fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s", libsym->func->name, task->pid, strerror(errno));
|
fprintf(stderr, "Couldn't insert breakpoint for %s to %d: %s", libsym->func->name, task->pid, strerror(errno));
|
||||||
|
|
||||||
@ -230,21 +197,50 @@ static void cb_breakpoint_for_symbol(struct library_symbol *libsym, void *data)
|
|||||||
breakpoint_enable(task, bp);
|
breakpoint_enable(task, bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void library_add(struct task *leader, struct library *lib)
|
static void library_each_symbol(struct libref *libref, void (*cb)(struct library_symbol *, void *), void *data)
|
||||||
{
|
{
|
||||||
|
struct list_head *it, *next;
|
||||||
|
|
||||||
|
list_for_each_safe(it, next, &libref->sym_list) {
|
||||||
|
struct library_symbol *sym = container_of(it, struct library_symbol, list);
|
||||||
|
|
||||||
|
(*cb) (sym, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
assert(leader->leader == leader);
|
assert(leader->leader == leader);
|
||||||
|
|
||||||
debug(DEBUG_PROCESS, "%s@%#lx to pid=%d", lib->filename, lib->base, leader->pid);
|
struct library *lib = malloc(sizeof(*lib));
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (lib == NULL)
|
||||||
fprintf(stderr, "+++ library add pid=%d %s@%#lx %#lx-%#lx +++\n", leader->pid, lib->filename, lib->base, lib->load_addr, lib->load_addr + lib->load_size);
|
return NULL;
|
||||||
|
|
||||||
/* Insert breakpoints for all active symbols. */
|
memset(lib, 0, sizeof(*lib));
|
||||||
library_each_symbol(lib, cb_breakpoint_for_symbol, leader);
|
|
||||||
|
lib->libref = libref_get(libref);
|
||||||
|
|
||||||
list_add_tail(&lib->list, &leader->libraries_list);
|
list_add_tail(&lib->list, &leader->libraries_list);
|
||||||
|
|
||||||
|
if (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);
|
||||||
|
|
||||||
|
return lib;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct library *library_add(struct task *leader, struct libref *libref)
|
||||||
|
{
|
||||||
|
struct library *lib = _library_add(leader, libref);
|
||||||
|
|
||||||
|
/* Insert breakpoints for all active symbols. */
|
||||||
|
library_each_symbol(libref, cb_breakpoint_for_symbol, leader);
|
||||||
|
|
||||||
report_add_map(leader, lib);
|
report_add_map(leader, lib);
|
||||||
|
|
||||||
|
return lib;
|
||||||
}
|
}
|
||||||
|
|
||||||
void library_clear_all(struct task *leader)
|
void library_clear_all(struct task *leader)
|
||||||
@ -258,12 +254,8 @@ int library_clone_all(struct task *clone, struct task *leader)
|
|||||||
|
|
||||||
list_for_each(it, &leader->libraries_list) {
|
list_for_each(it, &leader->libraries_list) {
|
||||||
struct library *lib = container_of(it, struct library, list);
|
struct library *lib = container_of(it, struct library, list);
|
||||||
struct library *nlibp = library_clone(clone, lib);
|
|
||||||
|
|
||||||
if (!nlibp)
|
_library_add(clone, lib->libref);
|
||||||
return -1;
|
|
||||||
|
|
||||||
list_add_tail(&nlibp->list, &clone->libraries_list);
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -278,6 +270,6 @@ const char *library_execname(struct task *leader)
|
|||||||
if (list_empty(&leader->libraries_list))
|
if (list_empty(&leader->libraries_list))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return container_of(leader->libraries_list.next, struct library, list)->filename;
|
return container_of(leader->libraries_list.next, struct library, list)->libref->filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
55
library.h
55
library.h
@ -31,21 +31,18 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "mtelf.h"
|
#include "mtelf.h"
|
||||||
|
|
||||||
|
#define LIBTYPE_LIB 0
|
||||||
|
#define LIBTYPE_MAIN 1
|
||||||
|
#define LIBTYPE_LOADER 2
|
||||||
|
|
||||||
struct library_symbol {
|
struct library_symbol {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct library *lib;
|
struct libref *libref;
|
||||||
const struct function *func;
|
const struct function *func;
|
||||||
arch_addr_t addr;
|
arch_addr_t addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct library_symbol *library_symbol_new(struct library *lib, arch_addr_t addr, const struct function *func);
|
struct libref {
|
||||||
|
|
||||||
struct library {
|
|
||||||
struct list_head list;
|
|
||||||
/* Symbols associated with the library. This includes a
|
|
||||||
* symbols that don't have a breakpoint attached (yet). */
|
|
||||||
struct list_head sym_list;
|
|
||||||
|
|
||||||
/* Unique key. Two library objects are considered equal, if
|
/* Unique key. Two library objects are considered equal, if
|
||||||
* they have the same key. */
|
* they have the same key. */
|
||||||
arch_addr_t key;
|
arch_addr_t key;
|
||||||
@ -74,24 +71,36 @@ struct library {
|
|||||||
unsigned long seg_offset;
|
unsigned long seg_offset;
|
||||||
void *table_data;
|
void *table_data;
|
||||||
unsigned long table_len;
|
unsigned long table_len;
|
||||||
|
unsigned int type;
|
||||||
|
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
void *exidx_data;
|
void *exidx_data;
|
||||||
unsigned long exidx_len;
|
unsigned long exidx_len;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
unsigned int refcnt;
|
||||||
|
|
||||||
|
/* Symbols associated with the library. This includes a
|
||||||
|
* symbols that don't have a breakpoint attached (yet). */
|
||||||
|
struct list_head sym_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Init LIB. */
|
struct library {
|
||||||
struct library *library_new(void);
|
/* link list of libraries associated with the task */
|
||||||
|
struct list_head list;
|
||||||
|
|
||||||
/* Destroy library. Doesn't free LIB itself. Symbols are destroyed
|
/* pointer to the real library refernce */
|
||||||
* and freed. */
|
struct libref *libref;
|
||||||
void library_destroy(struct task *leader, struct library *lib);
|
};
|
||||||
|
|
||||||
/* Set library filename. Frees the old name if necessary. */
|
/* create a new symbol */
|
||||||
void library_set_filename(struct library *lib, const char *new_name);
|
struct library_symbol *library_symbol_new(struct libref *libref, arch_addr_t addr, const struct function *func);
|
||||||
|
|
||||||
|
/* Delete library. Symbols are destroyed and freed. */
|
||||||
|
void library_delete(struct task *leader, struct library *lib);
|
||||||
|
|
||||||
/* Add a library to the list of the thread leader libraries. */
|
/* Add a library to the list of the thread leader libraries. */
|
||||||
void library_add(struct task *leader, struct library *lib);
|
struct library *library_add(struct task *leader, struct libref *libref);
|
||||||
|
|
||||||
/* delete a given list of libraries */
|
/* delete a given list of libraries */
|
||||||
void library_delete_list(struct task *leader, struct list_head *list);
|
void library_delete_list(struct task *leader, struct list_head *list);
|
||||||
@ -109,13 +118,19 @@ void library_setup(struct task *leader);
|
|||||||
const char *library_execname(struct task *leader);
|
const char *library_execname(struct task *leader);
|
||||||
|
|
||||||
/* Iterate through list of symbols of library. */
|
/* Iterate through list of symbols of library. */
|
||||||
struct library_symbol *library_find_symbol(struct library *lib, arch_addr_t addr);
|
struct library_symbol *library_find_symbol(struct libref *libref, arch_addr_t addr);
|
||||||
|
|
||||||
/* find a library with a given key */
|
/* find a library with a given key */
|
||||||
struct library *library_find_with_key(struct list_head *list, arch_addr_t key);
|
struct library *library_find_with_key(struct list_head *list, arch_addr_t key);
|
||||||
|
|
||||||
/* Iterate through list all symbols of leader task. */
|
/* create a library reference. */
|
||||||
struct library_symbol *find_symbol(struct task *leader, arch_addr_t addr);
|
struct libref *libref_new(unsigned int type);
|
||||||
|
|
||||||
|
/* delete a library reference. */
|
||||||
|
void libref_delete(struct libref *libref);
|
||||||
|
|
||||||
|
/* Set library filename. Frees the old name if necessary. */
|
||||||
|
void libref_set_filename(struct libref *libref, const char *new_name);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
52
main.c
52
main.c
@ -64,15 +64,15 @@ void mtrace_request_exit(void)
|
|||||||
wait_event_wakeup();
|
wait_event_wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dump_process(struct task *leader)
|
static void detach_process(struct task *leader)
|
||||||
{
|
{
|
||||||
if (!leader)
|
if (!leader)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
pid_t pid = leader->pid;
|
|
||||||
|
|
||||||
report_detach(leader);
|
report_detach(leader);
|
||||||
|
|
||||||
|
pid_t pid = leader->pid;
|
||||||
|
|
||||||
while(server_handle_command() != -1) {
|
while(server_handle_command() != -1) {
|
||||||
struct task *task = pid2task(pid);
|
struct task *task = pid2task(pid);
|
||||||
|
|
||||||
@ -88,12 +88,7 @@ static void mtrace_exit(void)
|
|||||||
{
|
{
|
||||||
if (!options.interactive) {
|
if (!options.interactive) {
|
||||||
each_process(stop_threads);
|
each_process(stop_threads);
|
||||||
|
each_process(detach_process);
|
||||||
while(server_connected()) {
|
|
||||||
if (task_list_empty())
|
|
||||||
break;
|
|
||||||
dump_process(get_first_process());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
each_process(remove_proc);
|
each_process(remove_proc);
|
||||||
@ -139,24 +134,35 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
char **cmd = process_options(argc, argv);
|
char **cmd = process_options(argc, argv);
|
||||||
|
|
||||||
if (options.client) {
|
if (options.trace) {
|
||||||
if (client_start() == -1)
|
if (options.logfile) {
|
||||||
exit(EXIT_FAILURE);
|
if (server_logfile() == -1)
|
||||||
return 0;
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
if (options.server) {
|
||||||
|
if (server_start() == -1)
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int ret = server_start_pair();
|
||||||
|
|
||||||
if (options.server) {
|
if (ret == -1)
|
||||||
if (server_start() == -1)
|
exit(EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
|
if (client_start_pair(ret))
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int ret = server_start_pair();
|
if (options.logfile) {
|
||||||
|
if (client_logfile() == -1)
|
||||||
if (ret == -1)
|
exit(EXIT_FAILURE);
|
||||||
exit(EXIT_FAILURE);
|
}
|
||||||
|
else
|
||||||
if (client_start_pair(ret))
|
if (client_start() == -1)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtrace_init(cmd);
|
mtrace_init(cmd);
|
||||||
|
|||||||
142
mtelf.c
142
mtelf.c
@ -146,7 +146,7 @@ static void read_symbol_table(struct mt_elf *mte, const char *filename, Elf_Scn
|
|||||||
*strsp = data->d_buf;
|
*strsp = data->d_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int populate_this_symtab(struct mt_elf *mte, struct library *lib, Elf_Data *symtab, const char *strtab, size_t size)
|
static int populate_this_symtab(struct mt_elf *mte, struct libref *libref, Elf_Data *symtab, const char *strtab, size_t size)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
@ -177,9 +177,9 @@ static int populate_this_symtab(struct mt_elf *mte, struct library *lib, Elf_Dat
|
|||||||
|
|
||||||
arch_addr_t addr = ARCH_ADDR_T(sym.st_value + mte->bias);
|
arch_addr_t addr = ARCH_ADDR_T(sym.st_value + mte->bias);
|
||||||
|
|
||||||
struct library_symbol *libsym = library_find_symbol(lib, addr);
|
struct library_symbol *libsym = library_find_symbol(libref, addr);
|
||||||
if (!libsym) {
|
if (!libsym) {
|
||||||
struct library_symbol *libsym = library_symbol_new(lib, addr, func);
|
struct library_symbol *libsym = library_symbol_new(libref, addr, func);
|
||||||
|
|
||||||
if (!libsym) {
|
if (!libsym) {
|
||||||
fprintf(stderr, "couldn't init symbol: %s%s\n", name, func->name);
|
fprintf(stderr, "couldn't init symbol: %s%s\n", name, func->name);
|
||||||
@ -191,21 +191,30 @@ static int populate_this_symtab(struct mt_elf *mte, struct library *lib, Elf_Dat
|
|||||||
if (libsym->func->level > func->level)
|
if (libsym->func->level > func->level)
|
||||||
libsym->func = func;
|
libsym->func = func;
|
||||||
}
|
}
|
||||||
|
if (options.verbose > 1)
|
||||||
|
fprintf(stderr, "breakpoint for %s:%s at %#lx\n", libref->filename, func->demangled_name, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int populate_symtab(struct mt_elf *mte, struct library *lib)
|
static int populate_symtab(struct mt_elf *mte, struct libref *libref)
|
||||||
{
|
{
|
||||||
|
struct opt_O_t *p;
|
||||||
|
|
||||||
|
for(p = options.opt_O; p; p = p->next) {
|
||||||
|
if (!strcmp(p->pathname, libref->filename))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (mte->symtab != NULL && mte->strtab != NULL) {
|
if (mte->symtab != NULL && mte->strtab != NULL) {
|
||||||
int status = populate_this_symtab(mte, lib, mte->symtab, mte->strtab, mte->symtab_count);
|
int status = populate_this_symtab(mte, libref, mte->symtab, mte->strtab, mte->symtab_count);
|
||||||
|
|
||||||
if (status < 0)
|
if (status < 0)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
return populate_this_symtab(mte, lib, mte->dynsym, mte->dynstr, mte->dynsym_count);
|
return populate_this_symtab(mte, libref, mte->dynsym, mte->dynstr, mte->dynsym_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
@ -223,32 +232,32 @@ static inline int elf_map_image(struct mt_elf *mte, void **image_addr)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int elf_lib_init(struct mt_elf *mte, struct task *task, struct library *lib)
|
static int elf_lib_init(struct mt_elf *mte, struct task *task, struct libref *libref)
|
||||||
{
|
{
|
||||||
if (elf_map_image(mte, &lib->image_addr))
|
if (elf_map_image(mte, &libref->image_addr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
lib->base = ARCH_ADDR_T(mte->base_addr);
|
libref->base = ARCH_ADDR_T(mte->base_addr);
|
||||||
lib->entry = ARCH_ADDR_T(mte->entry_addr);
|
libref->entry = ARCH_ADDR_T(mte->entry_addr);
|
||||||
lib->load_offset = mte->txt_hdr.p_offset;
|
libref->load_offset = mte->txt_hdr.p_offset;
|
||||||
lib->load_addr = mte->txt_hdr.p_vaddr + mte->bias;
|
libref->load_addr = mte->txt_hdr.p_vaddr + mte->bias;
|
||||||
lib->load_size = mte->txt_hdr.p_filesz;
|
libref->load_size = mte->txt_hdr.p_filesz;
|
||||||
lib->seg_offset = mte->eh_hdr.p_offset;
|
libref->seg_offset = mte->eh_hdr.p_offset;
|
||||||
lib->gp = mte->pltgot;
|
libref->gp = mte->pltgot;
|
||||||
|
|
||||||
#ifdef __arm__
|
#ifdef __arm__
|
||||||
if (mte->exidx_hdr.p_filesz) {
|
if (mte->exidx_hdr.p_filesz) {
|
||||||
lib->exidx_data = lib->image_addr + mte->exidx_hdr.p_offset;
|
libref->exidx_data = libref->image_addr + mte->exidx_hdr.p_offset;
|
||||||
lib->exidx_len = mte->exidx_hdr.p_memsz;
|
libref->exidx_len = mte->exidx_hdr.p_memsz;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (mte->eh_hdr.p_filesz && mte->dyn_addr) {
|
if (mte->eh_hdr.p_filesz && mte->dyn_addr) {
|
||||||
if (dwarf_get_unwind_table(task, lib, (struct dwarf_eh_frame_hdr *)(lib->image_addr - lib->load_offset + mte->eh_hdr.p_offset)) < 0)
|
if (dwarf_get_unwind_table(task, libref, (struct dwarf_eh_frame_hdr *)(libref->image_addr - libref->load_offset + mte->eh_hdr.p_offset)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (populate_symtab(mte, lib) < 0)
|
if (populate_symtab(mte, libref) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -370,12 +379,12 @@ static int elf_read(struct mt_elf *mte, struct task *task, const char *filename,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int elf_read_library(struct task *task, struct library *lib, const char *filename, GElf_Addr bias)
|
int elf_read_library(struct task *task, struct libref *libref, const char *filename, GElf_Addr bias)
|
||||||
{
|
{
|
||||||
struct mt_elf mte = { };
|
struct mt_elf mte = { };
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
library_set_filename(lib, filename);
|
libref_set_filename(libref, filename);
|
||||||
|
|
||||||
if (elf_read(&mte, task, filename, bias) == -1)
|
if (elf_read(&mte, task, filename, bias) == -1)
|
||||||
return -1;
|
return -1;
|
||||||
@ -383,7 +392,7 @@ int elf_read_library(struct task *task, struct library *lib, const char *filenam
|
|||||||
mte.bias = bias;
|
mte.bias = bias;
|
||||||
mte.entry_addr = mte.ehdr.e_entry + bias;
|
mte.entry_addr = mte.ehdr.e_entry + bias;
|
||||||
|
|
||||||
ret = elf_lib_init(&mte, task, lib);
|
ret = elf_lib_init(&mte, task, libref);
|
||||||
|
|
||||||
close_elf(&mte);
|
close_elf(&mte);
|
||||||
|
|
||||||
@ -456,7 +465,7 @@ static int entry_breakpoint_on_hit(struct task *task, struct breakpoint *a)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct library *elf_read_main_binary(struct task *task)
|
struct libref *elf_read_main_binary(struct task *task)
|
||||||
{
|
{
|
||||||
char fname[PATH_MAX];
|
char fname[PATH_MAX];
|
||||||
int ret;
|
int ret;
|
||||||
@ -464,14 +473,14 @@ struct library *elf_read_main_binary(struct task *task)
|
|||||||
struct mt_elf mte = { };
|
struct mt_elf mte = { };
|
||||||
unsigned long entry;
|
unsigned long entry;
|
||||||
unsigned long base;
|
unsigned long base;
|
||||||
struct library *lib;
|
struct libref *libref;
|
||||||
|
|
||||||
filename = pid2name(task->pid);
|
filename = pid2name(task->pid);
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
lib = library_new();
|
libref = libref_new(LIBTYPE_MAIN);
|
||||||
if (lib == NULL)
|
if (libref == NULL)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
ret = readlink(filename, fname, sizeof(fname) - 1);
|
ret = readlink(filename, fname, sizeof(fname) - 1);
|
||||||
@ -480,7 +489,7 @@ struct library *elf_read_main_binary(struct task *task)
|
|||||||
|
|
||||||
fname[ret] = 0;
|
fname[ret] = 0;
|
||||||
|
|
||||||
library_set_filename(lib, strdup(fname));
|
libref_set_filename(libref, fname);
|
||||||
|
|
||||||
if (elf_read(&mte, task, filename, 0) == -1)
|
if (elf_read(&mte, task, filename, 0) == -1)
|
||||||
goto fail3;
|
goto fail3;
|
||||||
@ -497,57 +506,90 @@ struct library *elf_read_main_binary(struct task *task)
|
|||||||
mte.bias = (GElf_Addr) (uintptr_t) entry - mte.ehdr.e_entry;
|
mte.bias = (GElf_Addr) (uintptr_t) entry - mte.ehdr.e_entry;
|
||||||
mte.entry_addr = (GElf_Addr) (uintptr_t) entry;
|
mte.entry_addr = (GElf_Addr) (uintptr_t) entry;
|
||||||
|
|
||||||
if (elf_lib_init(&mte, task, lib))
|
libref->key = ARCH_ADDR_T(mte.bias);
|
||||||
|
|
||||||
|
if (elf_lib_init(&mte, task, libref))
|
||||||
goto fail3;
|
goto fail3;
|
||||||
|
|
||||||
close_elf(&mte);
|
close_elf(&mte);
|
||||||
|
|
||||||
report_attach(task);
|
report_attach(task);
|
||||||
|
|
||||||
library_add(task, lib);
|
library_add(task, libref);
|
||||||
|
|
||||||
if (!linkmap_init(task, ARCH_ADDR_T(mte.dyn_addr)))
|
|
||||||
return lib;
|
|
||||||
|
|
||||||
if (!mte.interp)
|
if (!mte.interp)
|
||||||
return lib;
|
return libref;
|
||||||
|
|
||||||
struct mt_elf mte_ld = { };
|
struct mt_elf mte_ld = { };
|
||||||
|
|
||||||
copy_str_from_proc(task, ARCH_ADDR_T(mte.interp), fname, sizeof(fname));
|
copy_str_from_proc(task, ARCH_ADDR_T(mte.interp), fname, sizeof(fname));
|
||||||
|
|
||||||
if (!elf_read(&mte_ld, task, fname, (GElf_Addr)base)) {
|
if (!elf_read(&mte_ld, task, fname, (GElf_Addr)base)) {
|
||||||
|
struct libref *libref;
|
||||||
|
|
||||||
|
libref = libref_new(LIBTYPE_LOADER);
|
||||||
|
if (libref == NULL)
|
||||||
|
goto fail4;
|
||||||
|
|
||||||
|
libref_set_filename(libref, fname);
|
||||||
|
|
||||||
mte_ld.bias = (GElf_Addr)base;
|
mte_ld.bias = (GElf_Addr)base;
|
||||||
mte_ld.entry_addr = mte_ld.ehdr.e_entry + (GElf_Addr)base;
|
mte_ld.entry_addr = mte_ld.ehdr.e_entry + (GElf_Addr)base;
|
||||||
|
|
||||||
arch_addr_t addr = find_solib_break(&mte_ld);
|
libref->key = ARCH_ADDR_T(mte_ld.bias);
|
||||||
if (!addr)
|
|
||||||
addr = ARCH_ADDR_T(entry);
|
|
||||||
|
|
||||||
struct entry_breakpoint *entry_bp = (void *)breakpoint_new_ext(task, addr, NULL, 0, sizeof(*entry_bp) - sizeof(entry_bp->breakpoint));
|
ret = elf_lib_init(&mte_ld, task, libref);
|
||||||
if (!entry_bp)
|
if (!ret) {
|
||||||
|
library_add(task, libref);
|
||||||
|
|
||||||
|
if (linkmap_init(task, ARCH_ADDR_T(mte.dyn_addr))) {
|
||||||
|
arch_addr_t addr = find_solib_break(&mte_ld);
|
||||||
|
if (!addr)
|
||||||
|
addr = ARCH_ADDR_T(entry);
|
||||||
|
|
||||||
|
struct entry_breakpoint *entry_bp = (void *)breakpoint_new_ext(task, addr, NULL, 0, sizeof(*entry_bp) - sizeof(entry_bp->breakpoint));
|
||||||
|
if (!entry_bp)
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldn't initialize entry breakpoint for PID %d.\n"
|
||||||
|
"Tracing events may be missed.\n",
|
||||||
|
task->pid
|
||||||
|
);
|
||||||
|
else {
|
||||||
|
entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit;
|
||||||
|
entry_bp->breakpoint.locked = 1;
|
||||||
|
entry_bp->dyn_addr = ARCH_ADDR_T(mte.dyn_addr);
|
||||||
|
|
||||||
|
breakpoint_enable(task, &entry_bp->breakpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Couldn't initialize entry breakpoint for PID %d.\n"
|
"Couldn't read dynamic loader `%s` for PID %d.\n"
|
||||||
"Some tracing events may be missed.\n",
|
"Tracing events may be missed.\n",
|
||||||
|
fname,
|
||||||
task->pid
|
task->pid
|
||||||
);
|
);
|
||||||
else {
|
|
||||||
entry_bp->breakpoint.on_hit = entry_breakpoint_on_hit;
|
|
||||||
entry_bp->breakpoint.locked = 1;
|
|
||||||
entry_bp->dyn_addr = ARCH_ADDR_T(mte.dyn_addr);
|
|
||||||
|
|
||||||
breakpoint_enable(task, &entry_bp->breakpoint);
|
|
||||||
}
|
}
|
||||||
|
fail4:
|
||||||
|
close_elf(&mte_ld);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr,
|
||||||
|
"Couldn't open dynamic loader `%s` for PID %d.\n"
|
||||||
|
"Tracing events may be missed.\n",
|
||||||
|
fname,
|
||||||
|
task->pid
|
||||||
|
);
|
||||||
}
|
}
|
||||||
close_elf(&mte_ld);
|
|
||||||
|
|
||||||
return lib;
|
return libref;
|
||||||
fail3:
|
fail3:
|
||||||
close_elf(&mte);
|
close_elf(&mte);
|
||||||
fail2:
|
fail2:
|
||||||
library_destroy(task, lib);
|
libref_delete(libref);
|
||||||
fail1:
|
fail1:
|
||||||
free(filename);
|
free(filename);
|
||||||
return lib;
|
return libref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
mtelf.h
4
mtelf.h
@ -58,10 +58,10 @@ struct elf_image {
|
|||||||
size_t size; /* (file-) size of the image */
|
size_t size; /* (file-) size of the image */
|
||||||
};
|
};
|
||||||
|
|
||||||
int elf_read_library(struct task *task, struct library *lib, const char *filename, GElf_Addr bias);
|
int elf_read_library(struct task *task, struct libref *libref, const char *filename, GElf_Addr bias);
|
||||||
|
|
||||||
/* Create a library object representing the main binary. */
|
/* Create a library object representing the main binary. */
|
||||||
struct library *elf_read_main_binary(struct task *task);
|
struct libref *elf_read_main_binary(struct task *task);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
126
mtrace.1
126
mtrace.1
@ -16,7 +16,7 @@
|
|||||||
.\" Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
.\" Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||||
.\" 02110-1301 USA
|
.\" 02110-1301 USA
|
||||||
.\"
|
.\"
|
||||||
.TH MTRACE "1" "May 2015" "" "User Commands"
|
.TH MTRACE "12" "Oct 2015" "" "User Commands"
|
||||||
.SH NAME
|
.SH NAME
|
||||||
mtrace \- A dynamic memory allocation tracer
|
mtrace \- A dynamic memory allocation tracer
|
||||||
.SH SYNOPSIS
|
.SH SYNOPSIS
|
||||||
@ -24,14 +24,14 @@ mtrace \- A dynamic memory allocation tracer
|
|||||||
.\" ---------------------------------------------------------------------------
|
.\" ---------------------------------------------------------------------------
|
||||||
.\"
|
.\"
|
||||||
.PP
|
.PP
|
||||||
.B mtrace
|
.BR mtrace " \-t|\-\-trace
|
||||||
.\"
|
.\"
|
||||||
.\" Output formatting:
|
.\" Output formatting:
|
||||||
.\"
|
.\"
|
||||||
[\-d|\-\-depth \fIlevel\fR]
|
[\-d|\-\-depth \fIlevel\fR]
|
||||||
[\-F|\-\-config \fIfile\fR]
|
[\-F|\-\-config \fIfilename\fR]
|
||||||
[\-S|\-\-sort \fIoption\fR]
|
[\-S|\-\-sort \fIoption\fR]
|
||||||
[\-o|\-\-output \fIfile\fR]
|
[\-o|\-\-output \fIfilename\fR]
|
||||||
.\"
|
.\"
|
||||||
.\" Various:
|
.\" Various:
|
||||||
.\"
|
.\"
|
||||||
@ -39,8 +39,11 @@ mtrace \- A dynamic memory allocation tracer
|
|||||||
[\-b|\-\-binpath \fIpath\fR]
|
[\-b|\-\-binpath \fIpath\fR]
|
||||||
[\-C|\-\-cwd \fIpath\fR]
|
[\-C|\-\-cwd \fIpath\fR]
|
||||||
[\-D|\-\-debug \fImask\fR]
|
[\-D|\-\-debug \fImask\fR]
|
||||||
|
[\-i|\-\-interactive]
|
||||||
|
[\-l|\-\-logfile \fIfilename\fR]
|
||||||
[\-n|\-\-nocpp]
|
[\-n|\-\-nocpp]
|
||||||
[\-u \fIusername\fR]
|
[\-O|\-\-omit \fIfilename\fR]
|
||||||
|
[\-u|\-\-user \fIusername\fR]
|
||||||
[\-v|\-\-verbose]
|
[\-v|\-\-verbose]
|
||||||
.\"
|
.\"
|
||||||
.\" What processes to trace:
|
.\" What processes to trace:
|
||||||
@ -53,42 +56,22 @@ mtrace \- A dynamic memory allocation tracer
|
|||||||
.\" ---------------------------------------------------------------------------
|
.\" ---------------------------------------------------------------------------
|
||||||
.\"
|
.\"
|
||||||
.PP
|
.PP
|
||||||
.BR mtrace " \-c|\-\-client addr"
|
.BR mtrace " \-t|\-\-trace \-r|\-\-remote \fIaddr\fR"
|
||||||
[\-P|\-\-port num]
|
[\-P|\-\-port \fInum\fR]
|
||||||
[\-i|\-\-interactive]
|
|
||||||
.\"
|
|
||||||
.\" Output formatting:
|
|
||||||
.\"
|
|
||||||
[\-b|\-\-binpath \fIpath\fR]
|
|
||||||
[\-F|\-\-config \fIfile\fR]
|
|
||||||
[\-S|\-\-sort \fIoption\fR]
|
|
||||||
[\-o|\-\-output \fIfilenfR]
|
|
||||||
.\"
|
|
||||||
.\" Various:
|
|
||||||
.\"
|
|
||||||
[\-a|\-\-autoscan]
|
|
||||||
[\-D|\-\-debug \fImask\fR]
|
|
||||||
[\-v|\-\-verbose]
|
|
||||||
.\"
|
|
||||||
.\" ---------------------------------------------------------------------------
|
|
||||||
.\"
|
|
||||||
.PP
|
|
||||||
.BR mtrace " \-s|\-\-server"
|
|
||||||
[\-P|\-\-port num]
|
|
||||||
[\-l|\-\-listen addr]
|
|
||||||
[\-w|\-\-wait]
|
[\-w|\-\-wait]
|
||||||
.\"
|
.\"
|
||||||
.\" Output formatting:
|
.\" Output formatting:
|
||||||
.\"
|
.\"
|
||||||
[\-d|\-\-depth \fIlevel\fR]
|
[\-d|\-\-depth \fIlevel\fR]
|
||||||
[\-o|\-\-output \fIfile\fR]
|
|
||||||
.\"
|
.\"
|
||||||
.\" Various:
|
.\" Various:
|
||||||
.\"
|
.\"
|
||||||
[\-C|\-\-cwd \fIpath\fR]
|
[\-C|\-\-cwd \fIpath\fR]
|
||||||
[\-D|\-\-debug \fImask\fR]
|
[\-D|\-\-debug \fImask\fR]
|
||||||
|
[\-l|\-\-logfile \fIfilename\fR]
|
||||||
[\-n|\-\-nocpp]
|
[\-n|\-\-nocpp]
|
||||||
[\-u \fIusername\fR]
|
[\-O|\-\-omit \fIfilename\fR]
|
||||||
|
[\-u|\-\-user \fIusername\fR]
|
||||||
[\-v|\-\-verbose]
|
[\-v|\-\-verbose]
|
||||||
.\"
|
.\"
|
||||||
.\" What processes to trace:
|
.\" What processes to trace:
|
||||||
@ -101,30 +84,25 @@ mtrace \- A dynamic memory allocation tracer
|
|||||||
.\" ---------------------------------------------------------------------------
|
.\" ---------------------------------------------------------------------------
|
||||||
.\"
|
.\"
|
||||||
.PP
|
.PP
|
||||||
.B mtrace -i|\-\-interactive
|
.BR mtrace
|
||||||
|
[\-r|\-\-remote \fIaddr\fR]
|
||||||
|
[\-P|\-\-port \fInum\fR]
|
||||||
.\"
|
.\"
|
||||||
.\" Output formatting:
|
.\" Output formatting:
|
||||||
.\"
|
.\"
|
||||||
[\-d|\-\-depth \fIlevel\fR]
|
[\-F|\-\-config \fIfilename\fR]
|
||||||
[\-F|\-\-config \fIfile\fR]
|
|
||||||
[\-S|\-\-sort \fIoption\fR]
|
[\-S|\-\-sort \fIoption\fR]
|
||||||
|
[\-o|\-\-output \fIfilename\fR]
|
||||||
.\"
|
.\"
|
||||||
.\" Various:
|
.\" Various:
|
||||||
.\"
|
.\"
|
||||||
[\-a|\-\-autoscan]
|
[\-a|\-\-autoscan]
|
||||||
[\-b|\-\-binpath \fIpath\fR]
|
[\-b|\-\-binpath \fIpath\fR]
|
||||||
[\-C|\-\-cwd]
|
|
||||||
[\-D|\-\-debug \fImask\fR]
|
[\-D|\-\-debug \fImask\fR]
|
||||||
[\-n|\-\-nocpp]
|
[\-i|\-\-interactive]
|
||||||
[\-u \fIusername\fR]
|
[\-l|\-\-logfile \fIfilename\fR]
|
||||||
[\-v|\-\-verbose]
|
[\-v|\-\-verbose]
|
||||||
.\"
|
.\"
|
||||||
.\" What processes to trace:
|
|
||||||
.\"
|
|
||||||
[\-e|\-\-follow\-exec]
|
|
||||||
[\-f|\-\-follow\-fork]
|
|
||||||
[\-p|\-\-pid \fIpid\fR]
|
|
||||||
.\"
|
|
||||||
.\" ---------------------------------------------------------------------------
|
.\" ---------------------------------------------------------------------------
|
||||||
.\"
|
.\"
|
||||||
.PP
|
.PP
|
||||||
@ -154,7 +132,7 @@ writable memory mappings of the program against the pointer of an allocation.
|
|||||||
If the memory address will be not found during a scan there is a high change
|
If the memory address will be not found during a scan there is a high change
|
||||||
for a missing reference and therefore for a memory leak.
|
for a missing reference and therefore for a memory leak.
|
||||||
|
|
||||||
The following funtions will be intercepted:
|
The following functions will be intercepted:
|
||||||
|
|
||||||
.in +4
|
.in +4
|
||||||
.nf
|
.nf
|
||||||
@ -226,13 +204,7 @@ of the binary to the search path. If the binary is not found it will strip
|
|||||||
down the leading directory of the remote path and try again until no more
|
down the leading directory of the remote path and try again until no more
|
||||||
leading directory is found. It is possible to add several binary search paths
|
leading directory is found. It is possible to add several binary search paths
|
||||||
by passing more than one \-b option.
|
by passing more than one \-b option.
|
||||||
.IP "\-c, \-\-client \fIaddr\fR"
|
.IP "\-c, \-\-cwd \fIpath\fR"
|
||||||
Run
|
|
||||||
.B mtrace
|
|
||||||
as client and connect to a socket. If addr begins with / or . it will assumed
|
|
||||||
a named socket, otherwise it will be passed to getaddrinfo(3), which handles
|
|
||||||
any kind of hostname, IPv4 or IPv6 addresses.
|
|
||||||
.IP "\-C, \-\-cwd \fIpath\fR"
|
|
||||||
This option is valid in any mode except the client mode. Its used for locating
|
This option is valid in any mode except the client mode. Its used for locating
|
||||||
libraries for an attached process which are linked with relative paths. In this
|
libraries for an attached process which are linked with relative paths. In this
|
||||||
case
|
case
|
||||||
@ -249,12 +221,12 @@ to see what can be used. This option is only available when
|
|||||||
was build with --enable-debug.
|
was build with --enable-debug.
|
||||||
.IP "\-d, \-\-depth \fIlevel\fR"
|
.IP "\-d, \-\-depth \fIlevel\fR"
|
||||||
Do backtrace of \fIlevel\fR stack frames for each memory allocation function.
|
Do backtrace of \fIlevel\fR stack frames for each memory allocation function.
|
||||||
|
.IP "\-e, \-\-follow-exec"
|
||||||
|
Trace processes as they are created by one of the currently traced processes as
|
||||||
|
a result of execve(2) system call.
|
||||||
.IP "\-f, \-\-follow-fork"
|
.IP "\-f, \-\-follow-fork"
|
||||||
Trace child processes as they are created by one of the currently traced
|
Trace child processes as they are created by one of the currently traced
|
||||||
processes as a result of the fork(2) system call.
|
processes as a result of the fork(2) system call.
|
||||||
.IP "\-f, \-\-follow-exec"
|
|
||||||
Trace processes as they are created by one of the currently traced processes as
|
|
||||||
a result of execve(2) system call.
|
|
||||||
.IP "\-F, \-\-config \fIpath"
|
.IP "\-F, \-\-config \fIpath"
|
||||||
Set the config file. For a detailed description of this file see
|
Set the config file. For a detailed description of this file see
|
||||||
mtrace.conf(5). It is possible to pass several config files by passing more
|
mtrace.conf(5). It is possible to pass several config files by passing more
|
||||||
@ -266,24 +238,31 @@ $XDG_CONFIG_HOME/mtrace,
|
|||||||
SYSCONFDIR/mtrace.conf,
|
SYSCONFDIR/mtrace.conf,
|
||||||
/etc/mtrace.conf
|
/etc/mtrace.conf
|
||||||
.IP "\-h, \-\-help"
|
.IP "\-h, \-\-help"
|
||||||
Show a summary of the options to mtrace and exit.
|
Show a summary of the options to \fBmtrace\fR and exit.
|
||||||
.IP "\-i, \-\-interactive"
|
.IP "\-i, \-\-interactive"
|
||||||
Enables the interactive mode for client or when attaching to a process. See
|
Enables the interactive mode for client or when attaching to a process. See
|
||||||
the section \fBINTERACTIVE MODE\fR to learn more about the interactive commands
|
the section \fBINTERACTIVE MODE\fR to learn more about the interactive commands
|
||||||
in this mode.
|
in this mode.
|
||||||
.IP "\-k, \-\-kill"
|
.IP "\-k, \-\-kill"
|
||||||
Kill mtrace in case of a bookkeeping error. This options is for
|
Kill \fBmtrace\fR in case of a bookkeeping error. This options is intended for
|
||||||
.B mtrace
|
.B mtrace
|
||||||
development only!
|
development only!
|
||||||
.IP "\-l, \-\-listen \fIaddr"
|
.IP "\-O, \-\-omit \fIfilename"
|
||||||
Listen on socket path or address in server mode. If addr begins with / or . it
|
Do not place any dynamic memory interception breakpoints in the given file.
|
||||||
will assumed a named socket, otherwise it will be passed to getaddrinfo(3),
|
This is usefull when a library offers memory allocation functions which does
|
||||||
which handles any kind of hostname, IPv4 or IPv6 addresses.
|
only forward the calls. Use of this option can improve the trace performace in
|
||||||
|
this case. It is possible to omit several files by passing more than one
|
||||||
|
\-O option.
|
||||||
.IP "\-o, \-\-output \fIfilename"
|
.IP "\-o, \-\-output \fIfilename"
|
||||||
Write the trace output to the file \fIfilename\fR rather than to stderr. When
|
Write the trace output to the file \fIfilename\fR rather than to stderr. When
|
||||||
passing this option the output will be written in reserve order in opposite the
|
passing this option the output will be written in reserve order in opposite the
|
||||||
stderr output. So the highest value of the sort order is at the beginning of
|
stderr output. So the highest value of the sort order is at the beginning of
|
||||||
the file and the lowest at the end of the file.
|
the file and the lowest at the end of the file.
|
||||||
|
.IP "\-l, \-\-logfile \fIfilename"
|
||||||
|
Use a given logfile instead of a socket connection. In trace mode all data will
|
||||||
|
be written into the logfile. In the non trace mode the data will be retrieved
|
||||||
|
from the logfile. This option can improve the performance of the trace
|
||||||
|
since the trace will be split into to different actions.
|
||||||
.IP "\-n, \-\-nocpp"
|
.IP "\-n, \-\-nocpp"
|
||||||
Disable the trace of C++ allocation operators. This is safe and faster for libstdc++,
|
Disable the trace of C++ allocation operators. This is safe and faster for libstdc++,
|
||||||
since this library does call malloc() and free() inside the allocation operators.
|
since this library does call malloc() and free() inside the allocation operators.
|
||||||
@ -294,11 +273,13 @@ It is possible to attach to several processes by passing more than one
|
|||||||
\-p option.
|
\-p option.
|
||||||
.IP "\-P, \-\-port \fInum"
|
.IP "\-P, \-\-port \fInum"
|
||||||
Set the port number for client or server mode. The default port number is 4576.
|
Set the port number for client or server mode. The default port number is 4576.
|
||||||
.IP "\-s, \-\-server"
|
.IP "\-r, \-\-remote \fIaddr"
|
||||||
Run mtrace in server mode. This is mostly needed for remote cross architecture
|
Run \fBmtrace\fR in remote mode. Use \fIaddr\fR as socket path or address. If
|
||||||
trace or when running an interactive client. If no \-l and \-P option is passed
|
\fIaddr\fR begins with / or . it will assumed a named socket, otherwise it
|
||||||
to the sever mode, the server will listen on any address using port 4576.
|
will be passed to getaddrinfo(3), which handles any kind of hostname, IPv4 or
|
||||||
.IP "\-S, \-\-sortby keyword"
|
IPv6 addresses. If this option is passed in conjunction with -t, mtrace will be
|
||||||
|
execute in server mode, otherwise in client mode.
|
||||||
|
.IP "\-s, \-\-sortby keyword"
|
||||||
Sort the output of the stack backtraces by keyword. Valid keywords are:
|
Sort the output of the stack backtraces by keyword. Valid keywords are:
|
||||||
|
|
||||||
.RS
|
.RS
|
||||||
@ -349,7 +330,11 @@ Sort by the pseudo time stamp counter. Each stack backtrace will get an increme
|
|||||||
Sort by number of bytes in use of all open allocations.
|
Sort by number of bytes in use of all open allocations.
|
||||||
.RE
|
.RE
|
||||||
.RE
|
.RE
|
||||||
.IP "\-u \fIusername"
|
.IP "\-t, \-\-trace"
|
||||||
|
Run \fBmtrace\fR in trace mode. In this mode all attached processes will run under
|
||||||
|
the control of \fBmtrace\fR and all dynamic memory function calls will be traced.
|
||||||
|
If this options is not given, \fBmtrace\fR will run in client mode.
|
||||||
|
.IP "\-u, \-\-user \fIusername\fR"
|
||||||
Run command with the userid, groupid and supplementary groups of
|
Run command with the userid, groupid and supplementary groups of
|
||||||
.IR username .
|
.IR username .
|
||||||
This option is only useful when running as root and enables the
|
This option is only useful when running as root and enables the
|
||||||
@ -358,7 +343,7 @@ correct execution of setuid and/or setgid binaries.
|
|||||||
Be verbose and display more details about what going on. This option can be
|
Be verbose and display more details about what going on. This option can be
|
||||||
repeated for a more detailed view.
|
repeated for a more detailed view.
|
||||||
.IP "\-V, \-\-version"
|
.IP "\-V, \-\-version"
|
||||||
Show the version number of mtrace and exit.
|
Show the version number of \fBmtrace\fR and exit.
|
||||||
.IP "\-w, \-\-wait"
|
.IP "\-w, \-\-wait"
|
||||||
This option stops the execution of the traced processes until a client is
|
This option stops the execution of the traced processes until a client is
|
||||||
connected to the server. So this option is only valid in server mode.
|
connected to the server. So this option is only valid in server mode.
|
||||||
@ -481,12 +466,12 @@ Start allocation tracing.
|
|||||||
Show allocation status.
|
Show allocation status.
|
||||||
|
|
||||||
.IP "stop \fIpid\fR"
|
.IP "stop \fIpid\fR"
|
||||||
Stop allocation tracing. Note that in this state the \fIscan\fR command can
|
Stop allocation tracing. Note that in this state a \fIscan\fR command can
|
||||||
not performed.
|
not performed.
|
||||||
|
|
||||||
.SH BUGS
|
.SH BUGS
|
||||||
It only works on Linux for X86, X86_64, ARM 32 and PowerPC 32. No Hardware
|
It only works on Linux for X86, X86_64, ARM 32 and PowerPC 32. No Hardware
|
||||||
Breakpoint support on ARM and PowerPC. No ARM Thumb support. See TODO file
|
Breakpoint support on ARM and PowerPC. No ARM Thumb support. See TODO file
|
||||||
for more open issues.
|
for more open issues.
|
||||||
.LP
|
.LP
|
||||||
.PP
|
.PP
|
||||||
@ -505,4 +490,5 @@ See mtrace.conf(5) for details on the syntax of this file.
|
|||||||
Stefani Seibold <stefani@seibold.net>
|
Stefani Seibold <stefani@seibold.net>
|
||||||
.SH "SEE ALSO"
|
.SH "SEE ALSO"
|
||||||
.BR mtrace.conf(5),
|
.BR mtrace.conf(5),
|
||||||
.BR ptrace(2)
|
.BR ptrace(2),
|
||||||
|
.BR perf(1)
|
||||||
|
|||||||
270
options.c
270
options.c
@ -46,16 +46,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIN_STACK 4
|
#define MIN_STACK 4
|
||||||
#define MAX_STACK 128
|
#define MAX_STACK 64
|
||||||
|
|
||||||
#define DEFAULT_STACK 15
|
#define DEFAULT_STACK 15
|
||||||
#define DEFAULT_PORT 4576
|
#define DEFAULT_PORT 4576
|
||||||
|
|
||||||
|
static char *sockdef;
|
||||||
|
|
||||||
struct options_t options;
|
struct options_t options;
|
||||||
|
|
||||||
static struct opt_F_t *opt_F_last;
|
static struct opt_F_t *opt_F_last;
|
||||||
static struct opt_p_t *opt_p_last;
|
static struct opt_p_t *opt_p_last;
|
||||||
static struct opt_b_t *opt_b_last;
|
static struct opt_b_t *opt_b_last;
|
||||||
|
static struct opt_O_t *opt_O_last;
|
||||||
|
|
||||||
static char *progname; /* Program name (`mtrace') */
|
static char *progname; /* Program name (`mtrace') */
|
||||||
|
|
||||||
@ -74,8 +77,7 @@ static void usage(void)
|
|||||||
"\n"
|
"\n"
|
||||||
" -a, --autoscan scan memory on exit of a traced program\n"
|
" -a, --autoscan scan memory on exit of a traced program\n"
|
||||||
" -b, --binpath=path binary search path (may be repeated)\n"
|
" -b, --binpath=path binary search path (may be repeated)\n"
|
||||||
" -c, --client=addr connect to socket (path or address)\n"
|
" -c, --cwd=path use as current working directory for traced process\n"
|
||||||
" -C, --cwd=path use as current working directory for traced process\n"
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
" -D, --debug=MASK enable debugging (see -Dh or --debug=help)\n"
|
" -D, --debug=MASK enable debugging (see -Dh or --debug=help)\n"
|
||||||
" -Dh, --debug=help show help on debugging\n"
|
" -Dh, --debug=help show help on debugging\n"
|
||||||
@ -86,15 +88,17 @@ static void usage(void)
|
|||||||
" -f, --follow-fork trace forked children\n"
|
" -f, --follow-fork trace forked children\n"
|
||||||
" -h, --help display this help and exit\n"
|
" -h, --help display this help and exit\n"
|
||||||
" -i, --interactive interactive client mode\n"
|
" -i, --interactive interactive client mode\n"
|
||||||
|
" -O, --omit=FILE do not place breakpoint in this file\n"
|
||||||
" -k, --kill abort mtrace on unexpected error conditon\n"
|
" -k, --kill abort mtrace on unexpected error conditon\n"
|
||||||
" -l, --listen listen on socket path or address in server mode\n"
|
" -l, --logfile use log file instead of socket connection\n"
|
||||||
" -n, --nocpp disable trace of c++ allocation operators (faster for libstdc++)\n"
|
" -n, --nocpp disable trace of c++ allocation operators (faster for libstdc++)\n"
|
||||||
" -o, --output=FILE write the trace output to file with given name\n"
|
" -o, --output=FILE write the trace output to file with given name\n"
|
||||||
" -p, --pid=PID attach to the process with the process ID pid (may be repeated)\n"
|
" -p, --pid=PID attach to the process with the process ID pid (may be repeated)\n"
|
||||||
" -P, --port=PORT socket port (default: " STR(DEFAULT_PORT) ")\n"
|
" -P, --port=PORT socket port (default: " STR(DEFAULT_PORT) ")\n"
|
||||||
" -s, --server server mode\n"
|
" -r, --remote=addr remote use address (path, address or host)\n"
|
||||||
" -S, --sort-by=type sort dump by type:\n"
|
" -s, --sort-by=type sort dump by type:\n"
|
||||||
" allocations, average, bytes-leaked, leaks, stacks, total, tsc, usage\n"
|
" allocations, average, bytes-leaked, leaks, stacks, total, tsc, usage\n"
|
||||||
|
" -t, --trace trace mode\n"
|
||||||
" -u, --user=USERNAME run command with the userid, groupid of username\n"
|
" -u, --user=USERNAME run command with the userid, groupid of username\n"
|
||||||
" -V, --version output version information and exit\n"
|
" -V, --version output version information and exit\n"
|
||||||
" -v, --verbose verbose mode (repeat for higher verbosity)\n"
|
" -v, --verbose verbose mode (repeat for higher verbosity)\n"
|
||||||
@ -228,8 +232,8 @@ static int parse_int(const char *optarg, char opt, int min, int max)
|
|||||||
{
|
{
|
||||||
char *endptr;
|
char *endptr;
|
||||||
long int l = strtol(optarg, &endptr, 0);
|
long int l = strtol(optarg, &endptr, 0);
|
||||||
if (l < min || (max != 0 && l > max)
|
|
||||||
|| *optarg == 0 || *endptr != 0) {
|
if (l < min || (max != 0 && l > max) || *optarg == 0 || *endptr != 0) {
|
||||||
const char *fmt = max != 0 ? "Invalid argument to -%c: '%s'. Use integer %d..%d.\n" : "Invalid argument to -%c: '%s'. Use integer >=%d.\n";
|
const char *fmt = max != 0 ? "Invalid argument to -%c: '%s'. Use integer %d..%d.\n" : "Invalid argument to -%c: '%s'. Use integer >=%d.\n";
|
||||||
fprintf(stderr, fmt, opt, optarg, min, max);
|
fprintf(stderr, fmt, opt, optarg, min, max);
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -240,6 +244,10 @@ static int parse_int(const char *optarg, char opt, int min, int max)
|
|||||||
char **process_options(int argc, char **argv)
|
char **process_options(int argc, char **argv)
|
||||||
{
|
{
|
||||||
char *output = NULL;
|
char *output = NULL;
|
||||||
|
char *cwd = NULL;
|
||||||
|
|
||||||
|
if (!sockdef)
|
||||||
|
asprintf(&sockdef, "/tmp/mtrace%u.sock", getuid());
|
||||||
|
|
||||||
progname = argv[0];
|
progname = argv[0];
|
||||||
|
|
||||||
@ -252,15 +260,17 @@ char **process_options(int argc, char **argv)
|
|||||||
options.interactive = 0;
|
options.interactive = 0;
|
||||||
options.verbose = 0;
|
options.verbose = 0;
|
||||||
options.wait = 0;
|
options.wait = 0;
|
||||||
options.client = NULL;
|
options.address = NULL;
|
||||||
|
options.trace = 0;
|
||||||
options.server = 0;
|
options.server = 0;
|
||||||
options.listen = NULL;
|
options.logfile = NULL;
|
||||||
options.user = NULL;
|
options.user = NULL;
|
||||||
options.command = NULL;
|
options.command = NULL;
|
||||||
options.cwd = -1;
|
options.cwd = -1;
|
||||||
options.opt_p = NULL;
|
options.opt_p = NULL;
|
||||||
options.opt_F = NULL;
|
options.opt_F = NULL;
|
||||||
options.opt_b = NULL;
|
options.opt_b = NULL;
|
||||||
|
options.opt_O = NULL;
|
||||||
options.sort_by = -1;
|
options.sort_by = -1;
|
||||||
options.debug = 0;
|
options.debug = 0;
|
||||||
options.kill = 0;
|
options.kill = 0;
|
||||||
@ -272,9 +282,8 @@ char **process_options(int argc, char **argv)
|
|||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{ "auto_scan", 0, 0, 'a' },
|
{ "auto_scan", 0, 0, 'a' },
|
||||||
{ "binpath", 1, 0, 'b' },
|
{ "binpath", 1, 0, 'b' },
|
||||||
{ "client", 1, 0, 'c' },
|
|
||||||
{ "config", 1, 0, 'F' },
|
{ "config", 1, 0, 'F' },
|
||||||
{ "cwd", 1, 0, 'C' },
|
{ "cwd", 1, 0, 'c' },
|
||||||
{ "debug", 1, 0, 'D' },
|
{ "debug", 1, 0, 'D' },
|
||||||
{ "depth", 1, 0, 'd' },
|
{ "depth", 1, 0, 'd' },
|
||||||
{ "help", 0, 0, 'h' },
|
{ "help", 0, 0, 'h' },
|
||||||
@ -282,22 +291,25 @@ char **process_options(int argc, char **argv)
|
|||||||
{ "follow-exec", 0, 0, 'e' },
|
{ "follow-exec", 0, 0, 'e' },
|
||||||
{ "interactive", 0, 0, 'i' },
|
{ "interactive", 0, 0, 'i' },
|
||||||
{ "kill", 0, 0, 'k' },
|
{ "kill", 0, 0, 'k' },
|
||||||
{ "listen", 1, 0, 'l' },
|
{ "logfile", 1, 0, 'l' },
|
||||||
{ "nocpp", 1, 0, 'n' },
|
{ "nocpp", 1, 0, 'n' },
|
||||||
{ "output", 1, 0, 'o' },
|
{ "output", 1, 0, 'o' },
|
||||||
|
{ "omit", 1, 0, 'O' },
|
||||||
{ "pid", 1, 0, 'p' },
|
{ "pid", 1, 0, 'p' },
|
||||||
{ "port", 1, 0, 'P' },
|
{ "port", 1, 0, 'P' },
|
||||||
{ "server", 0, 0, 's' },
|
{ "remote", 1, 0, 'r' },
|
||||||
{ "sort-by", 1, 0, 'S' },
|
{ "sort-by", 1, 0, 's' },
|
||||||
|
{ "trace", 0, 0, 't' },
|
||||||
{ "user", 1, 0, 'u' },
|
{ "user", 1, 0, 'u' },
|
||||||
{ "version", 0, 0, 'V' },
|
{ "version", 0, 0, 'V' },
|
||||||
{ "verbose", 0, 0, 'v' },
|
{ "verbose", 0, 0, 'v' },
|
||||||
{ "wait", 0, 0, 'w' },
|
{ "wait", 0, 0, 'w' },
|
||||||
{ 0, 0, 0, 0 }
|
{ 0, 0, 0, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
c = getopt_long(argc, argv,
|
c = getopt_long(argc, argv,
|
||||||
"+aefhiknsVvw"
|
"+aefhikLntVvw"
|
||||||
"b:c:C:D:F:l:o:p:P:u:d:S:",
|
"b:c:d:D:F:l:o:O:p:P:r:s:u:",
|
||||||
long_options,
|
long_options,
|
||||||
&option_index);
|
&option_index);
|
||||||
|
|
||||||
@ -328,15 +340,10 @@ char **process_options(int argc, char **argv)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'c':
|
case 'c':
|
||||||
options.client = optarg;
|
cwd = optarg;
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'd':
|
||||||
options.cwd = open(optarg, O_RDONLY|O_DIRECTORY);
|
options.bt_depth = parse_int(optarg, 'd', 1, 0);
|
||||||
|
|
||||||
if (options.cwd == -1) {
|
|
||||||
fprintf(stderr, "%s: `%s' %s\n", progname, optarg, strerror(errno));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'D':
|
case 'D':
|
||||||
{
|
{
|
||||||
@ -354,28 +361,52 @@ char **process_options(int argc, char **argv)
|
|||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'e':
|
||||||
|
options.follow_exec = 1;
|
||||||
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
options.follow = 1;
|
options.follow = 1;
|
||||||
break;
|
break;
|
||||||
case 'F':
|
case 'F':
|
||||||
if (add_opt_F(strdup(optarg)) == -1) {
|
if (add_opt_F(optarg) == -1) {
|
||||||
fprintf(stderr, "config file not found %s\n", optarg);
|
fprintf(stderr, "config file not found %s\n", optarg);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
|
|
||||||
usage();
|
usage();
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'i':
|
case 'i':
|
||||||
options.interactive = 1;
|
options.interactive = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'k':
|
||||||
|
options.kill = 1;
|
||||||
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
options.listen = optarg;
|
options.logfile = optarg;
|
||||||
break;
|
break;
|
||||||
case 'o':
|
case 'o':
|
||||||
output = optarg;
|
output = optarg;
|
||||||
break;
|
break;
|
||||||
|
case 'O':
|
||||||
|
{
|
||||||
|
struct opt_O_t *tmp = malloc(sizeof(*tmp));
|
||||||
|
|
||||||
|
if (!tmp) {
|
||||||
|
fprintf(stderr, "%s\n", strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
tmp->pathname = strdup(optarg);
|
||||||
|
tmp->next = NULL;
|
||||||
|
|
||||||
|
if (opt_O_last)
|
||||||
|
opt_O_last->next = tmp;
|
||||||
|
opt_O_last = tmp;
|
||||||
|
|
||||||
|
if (!options.opt_O)
|
||||||
|
options.opt_O = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'n':
|
case 'n':
|
||||||
options.nocpp = 1;
|
options.nocpp = 1;
|
||||||
break;
|
break;
|
||||||
@ -401,37 +432,10 @@ char **process_options(int argc, char **argv)
|
|||||||
case 'P':
|
case 'P':
|
||||||
options.port = optarg;
|
options.port = optarg;
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'r':
|
||||||
options.user = optarg;
|
options.address = optarg;
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
printf("mtrace version " PACKAGE_VERSION ".\n"
|
|
||||||
"Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>.\n"
|
|
||||||
"\n"
|
|
||||||
"This software was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich/Germany.\n"
|
|
||||||
"\n"
|
|
||||||
"This is free software; see the GNU General Public Licence\n"
|
|
||||||
"version 2 or later for copying conditions. There is NO warranty.\n");
|
|
||||||
exit(0);
|
|
||||||
case 'd':
|
|
||||||
options.bt_depth = parse_int(optarg, 'd', 1, 0);
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
options.follow_exec = 1;
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
options.kill = 1;
|
|
||||||
break;
|
|
||||||
case 'v':
|
|
||||||
options.verbose++;
|
|
||||||
break;
|
|
||||||
case 'w':
|
|
||||||
options.wait = 1;
|
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
options.server = 1;
|
|
||||||
break;
|
|
||||||
case 'S':
|
|
||||||
if (!strncmp(optarg, "allocations", 2))
|
if (!strncmp(optarg, "allocations", 2))
|
||||||
options.sort_by = OPT_SORT_ALLOCATIONS;
|
options.sort_by = OPT_SORT_ALLOCATIONS;
|
||||||
else
|
else
|
||||||
@ -460,6 +464,27 @@ char **process_options(int argc, char **argv)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
options.trace = 1;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
options.user = optarg;
|
||||||
|
break;
|
||||||
|
case 'V':
|
||||||
|
printf("mtrace version " PACKAGE_VERSION ".\n"
|
||||||
|
"Copyright (C) 2015 Stefani Seibold <stefani@seibold.net>.\n"
|
||||||
|
"\n"
|
||||||
|
"This software was sponsored by Rohde & Schwarz GmbH & Co. KG, Munich/Germany.\n"
|
||||||
|
"\n"
|
||||||
|
"This is free software; see the GNU General Public Licence\n"
|
||||||
|
"version 2 or later for copying conditions. There is NO warranty.\n");
|
||||||
|
exit(0);
|
||||||
|
case 'v':
|
||||||
|
options.verbose++;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
options.wait = 1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
@ -471,68 +496,118 @@ char **process_options(int argc, char **argv)
|
|||||||
if (argc > 0)
|
if (argc > 0)
|
||||||
options.command = search_for_command(argv[0]);
|
options.command = search_for_command(argv[0]);
|
||||||
|
|
||||||
if (options.sort_by == OPT_SORT_LEAKS || options.sort_by == OPT_SORT_BYTES_LEAKED)
|
|
||||||
options.auto_scan = 1;
|
|
||||||
|
|
||||||
if (!options.client && !options.opt_p && argc < 1) {
|
if (options.address && options.logfile) {
|
||||||
fprintf(stderr, "%s: too few arguments\n", progname);
|
fprintf(stderr, "%s: either logfile or remote address is valid\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!options.server && options.listen) {
|
if (options.trace) {
|
||||||
fprintf(stderr, "%s: listen mode can only valid in server mode\n", progname);
|
if (!options.opt_p && !options.command) {
|
||||||
err_usage();
|
fprintf(stderr, "%s: trace requires -p or executable\n", progname);
|
||||||
}
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
if (options.client && (options.opt_p || argc > 0)) {
|
if (options.auto_scan) {
|
||||||
fprintf(stderr, "%s: client mode does not require -p nor executable\n", progname);
|
fprintf(stderr, "%s: scan option can not passed in when trace mode\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.client && options.nocpp) {
|
if (options.sort_by != -1) {
|
||||||
fprintf(stderr, "%s: client mode does not require -n\n", progname);
|
fprintf(stderr, "%s: sort-by can not passed in trace mode\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.client && options.server) {
|
if (options.opt_b) {
|
||||||
fprintf(stderr, "%s: choose between client and server mode\n", progname);
|
fprintf(stderr, "%s: binpath can only used in client mode\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.opt_b && !options.client) {
|
if (options.address) {
|
||||||
fprintf(stderr, "%s: binpath can only used in client mode\n", progname);
|
if (!strcmp(options.address, "."))
|
||||||
err_usage();
|
options.address = sockdef;
|
||||||
|
|
||||||
|
options.server = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (options.opt_p || options.command) {
|
||||||
|
fprintf(stderr, "%s: client mode does not require -p nor executable\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.nocpp) {
|
||||||
|
fprintf(stderr, "%s: client mode does not require -n\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.user) {
|
||||||
|
fprintf(stderr, "%s: user can only passed in trace mode\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.address)
|
||||||
|
options.address = sockdef;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.interactive) {
|
if (options.interactive) {
|
||||||
if ((!options.client && !options.opt_p) || options.command) {
|
if (options.server) {
|
||||||
fprintf(stderr, "%s: interactive mode can only invoked in -p or -c mode\n", progname);
|
fprintf(stderr, "%s: interactive mode not available in server mode\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
output = NULL;
|
|
||||||
|
|
||||||
if (options.auto_scan)
|
if (options.trace) {
|
||||||
|
if (options.command) {
|
||||||
|
fprintf(stderr, "%s: cannot execute process and interactive console at the same time in trace mode\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.opt_p) {
|
||||||
|
fprintf(stderr, "%s: interactive console requieres -p in trace mode\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (options.auto_scan) {
|
||||||
fprintf(stderr, "%s: auto scan ignored in interactive mode\n", progname);
|
fprintf(stderr, "%s: auto scan ignored in interactive mode\n", progname);
|
||||||
|
options.auto_scan = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.sort_by != -1) {
|
||||||
|
fprintf(stderr, "%s: sort-by ignored in interactive mode\n", progname);
|
||||||
|
options.sort_by = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.auto_scan && options.server) {
|
if (output) {
|
||||||
fprintf(stderr, "%s: scan option can not passed in -s mode\n", progname);
|
if (options.interactive) {
|
||||||
err_usage();
|
fprintf(stderr, "%s: output not valid in interactive mode\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.logfile) {
|
||||||
|
fprintf(stderr, "%s: either logfile or output is valid\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.server) {
|
||||||
|
fprintf(stderr, "%s: output not valid in server mode\n", progname);
|
||||||
|
err_usage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.port) {
|
if (options.port) {
|
||||||
if (!options.client && !options.server) {
|
if (!options.address) {
|
||||||
fprintf(stderr, "%s: Port only valid in client or server mode \n", progname);
|
fprintf(stderr, "%s: port only valid in client or trace mode\n", progname);
|
||||||
err_usage();
|
err_usage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
options.port = STR(DEFAULT_PORT);
|
options.port = STR(DEFAULT_PORT);
|
||||||
|
|
||||||
if (options.sort_by != -1 && options.server) {
|
if (options.sort_by == OPT_SORT_LEAKS || options.sort_by == OPT_SORT_BYTES_LEAKED)
|
||||||
fprintf(stderr, "%s: sort-by can not passed in -s mode\n", progname);
|
options.auto_scan = 1;
|
||||||
err_usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.bt_depth < MIN_STACK)
|
if (options.bt_depth < MIN_STACK)
|
||||||
options.bt_depth = MIN_STACK;
|
options.bt_depth = MIN_STACK;
|
||||||
@ -554,6 +629,15 @@ char **process_options(int argc, char **argv)
|
|||||||
fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
|
fcntl(fileno(options.output), F_SETFD, FD_CLOEXEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cwd) {
|
||||||
|
options.cwd = open(cwd, O_RDONLY|O_DIRECTORY);
|
||||||
|
|
||||||
|
if (options.cwd == -1) {
|
||||||
|
fprintf(stderr, "%s: `%s' %s\n", progname, optarg, strerror(errno));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return &argv[0];
|
return &argv[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
options.h
13
options.h
@ -55,6 +55,11 @@ struct opt_b_t {
|
|||||||
struct opt_b_t *next;
|
struct opt_b_t *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct opt_O_t {
|
||||||
|
char *pathname;
|
||||||
|
struct opt_O_t *next;
|
||||||
|
};
|
||||||
|
|
||||||
struct options_t {
|
struct options_t {
|
||||||
int auto_scan; /* scan memory on every exit of a trace program */
|
int auto_scan; /* scan memory on every exit of a trace program */
|
||||||
int bt_depth; /* how may levels of stack frames to show */
|
int bt_depth; /* how may levels of stack frames to show */
|
||||||
@ -62,10 +67,11 @@ struct options_t {
|
|||||||
int follow_exec; /* follow exec system calls */
|
int follow_exec; /* follow exec system calls */
|
||||||
int interactive; /* interactive mode */
|
int interactive; /* interactive mode */
|
||||||
FILE *output; /* output to a specific file */
|
FILE *output; /* output to a specific file */
|
||||||
int server; /* server mode flag */
|
int trace; /* trace mode flag */
|
||||||
int kill; /* kill on errors */
|
int kill; /* kill on errors */
|
||||||
char *listen; /* server listen on socket path or address */
|
int server; /* true for server listen */
|
||||||
char *client; /* connect to socket path or address */
|
char *logfile; /* logfile path */
|
||||||
|
char *address; /* connect to socket path or address */
|
||||||
char *user; /* -u: username to run command as */
|
char *user; /* -u: username to run command as */
|
||||||
int verbose; /* verbose mode */
|
int verbose; /* verbose mode */
|
||||||
int wait; /* wait for client connection */
|
int wait; /* wait for client connection */
|
||||||
@ -75,6 +81,7 @@ struct options_t {
|
|||||||
struct opt_p_t *opt_p; /* attach to process with a given pid */
|
struct opt_p_t *opt_p; /* attach to process with a given pid */
|
||||||
struct opt_F_t *opt_F; /* alternate configuration file(s) */
|
struct opt_F_t *opt_F; /* alternate configuration file(s) */
|
||||||
struct opt_b_t *opt_b; /* binary search path(s) */
|
struct opt_b_t *opt_b; /* binary search path(s) */
|
||||||
|
struct opt_O_t *opt_O; /* omits path list */
|
||||||
int sort_by; /* sort dump in non interative and non server mode */
|
int sort_by; /* sort dump in non interative and non server mode */
|
||||||
int debug; /* debug */
|
int debug; /* debug */
|
||||||
int nocpp; /* disable trace of c++ allocation operators */
|
int nocpp; /* disable trace of c++ allocation operators */
|
||||||
|
|||||||
153
report.c
153
report.c
@ -25,6 +25,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
#include "backtrace.h"
|
#include "backtrace.h"
|
||||||
@ -38,25 +41,32 @@
|
|||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
static int report_alloc64(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, int depth)
|
static int report_alloc64(struct task *task, enum mt_operation op, unsigned long ptr, unsigned long size, unsigned int depth, struct library_symbol *libsym)
|
||||||
{
|
{
|
||||||
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));
|
||||||
|
|
||||||
alloc->ptr = (uint64_t)ptr;
|
alloc->ptr = (uint64_t)ptr;
|
||||||
alloc->size = (uint64_t)size;
|
alloc->size = (uint64_t)size;
|
||||||
|
|
||||||
if (depth && backtrace_init_unwind(task) >= 0) {
|
if (depth) {
|
||||||
do {
|
alloc->data[i++] = libsym->addr;
|
||||||
alloc->data[i] = (uint64_t)backtrace_get_ip(task);
|
|
||||||
if (!alloc->data[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
++i;
|
if (backtrace_init_unwind(task) >= 0) {
|
||||||
|
while(i < depth) {
|
||||||
|
if (backtrace_location_type(task) != LIBTYPE_LOADER) {
|
||||||
|
alloc->data[i] = (uint64_t)backtrace_get_ip(task);
|
||||||
|
|
||||||
if (backtrace_step(task) < 0)
|
if (!alloc->data[i])
|
||||||
break;
|
break;
|
||||||
} while(i < depth);
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backtrace_step(task) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_breakpoint(task, task->event.e_un.breakpoint);
|
skip_breakpoint(task, task->event.e_un.breakpoint);
|
||||||
@ -64,7 +74,7 @@ static int report_alloc64(struct task *task, enum mt_operation op, unsigned long
|
|||||||
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint64_t));
|
return server_send_msg(op, task->leader->pid, task->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)
|
static int 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));
|
||||||
@ -72,17 +82,24 @@ static int report_alloc32(struct task *task, enum mt_operation op, unsigned long
|
|||||||
alloc->ptr = (uint32_t)ptr;
|
alloc->ptr = (uint32_t)ptr;
|
||||||
alloc->size = (uint32_t)size;
|
alloc->size = (uint32_t)size;
|
||||||
|
|
||||||
if (depth && backtrace_init_unwind(task) >= 0) {
|
if (depth) {
|
||||||
do {
|
alloc->data[i++] = libsym->addr;
|
||||||
alloc->data[i] = (uint32_t)backtrace_get_ip(task);
|
|
||||||
if (!alloc->data[i])
|
|
||||||
break;
|
|
||||||
|
|
||||||
++i;
|
if (backtrace_init_unwind(task) >= 0) {
|
||||||
|
while(i < depth) {
|
||||||
|
if (backtrace_location_type(task) != LIBTYPE_LOADER) {
|
||||||
|
alloc->data[i] = (uint32_t)backtrace_get_ip(task);
|
||||||
|
|
||||||
if (backtrace_step(task) < 0)
|
if (!alloc->data[i])
|
||||||
break;
|
break;
|
||||||
} while(i < depth);
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (backtrace_step(task) < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
skip_breakpoint(task, task->event.e_un.breakpoint);
|
skip_breakpoint(task, task->event.e_un.breakpoint);
|
||||||
@ -90,7 +107,7 @@ static int report_alloc32(struct task *task, enum mt_operation op, unsigned long
|
|||||||
return server_send_msg(op, task->leader->pid, task->pid, alloc, sizeof(*alloc) + i * sizeof(uint32_t));
|
return server_send_msg(op, task->leader->pid, task->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)
|
static int 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 0;
|
||||||
@ -101,9 +118,9 @@ static int report_alloc(struct task *task, enum mt_operation op, unsigned long p
|
|||||||
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);
|
return report_alloc64(task, op, ptr, size, depth, libsym);
|
||||||
else
|
else
|
||||||
return report_alloc32(task, op, ptr, size, depth);
|
return report_alloc32(task, op, ptr, size, depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _null(struct task *task, struct library_symbol *libsym)
|
static int _null(struct task *task, struct library_symbol *libsym)
|
||||||
@ -119,7 +136,7 @@ static int _report_malloc(struct task *task, struct library_symbol *libsym)
|
|||||||
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_MALLOC, ret, size, options.bt_depth);
|
return report_alloc(task, MT_MALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_free(struct task *task, struct library_symbol *libsym)
|
static int report_free(struct task *task, struct library_symbol *libsym)
|
||||||
@ -129,7 +146,7 @@ static int report_free(struct task *task, struct library_symbol *libsym)
|
|||||||
|
|
||||||
unsigned long addr = fetch_param(task, 0);
|
unsigned long addr = fetch_param(task, 0);
|
||||||
|
|
||||||
return report_alloc(task, MT_FREE, addr, 0, 0);
|
return report_alloc(task, MT_FREE, addr, 0, 0, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_realloc(struct task *task, struct library_symbol *libsym)
|
static int _report_realloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -142,9 +159,9 @@ static int _report_realloc(struct task *task, struct library_symbol *libsym)
|
|||||||
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);
|
return report_alloc(task, MT_REALLOC, ret, size, options.bt_depth, libsym);
|
||||||
else
|
else
|
||||||
return report_alloc(task, MT_REALLOC_FAILED, addr, 1, options.bt_depth);
|
return report_alloc(task, MT_REALLOC_FAILED, addr, 1, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_realloc(struct task *task, struct library_symbol *libsym)
|
static int report_realloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -155,7 +172,7 @@ static int report_realloc(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_REALLOC_ENTER, addr, size, options.bt_depth);
|
return report_alloc(task, MT_REALLOC_ENTER, addr, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_calloc(struct task *task, struct library_symbol *libsym)
|
static int _report_calloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -166,7 +183,7 @@ static int _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);
|
return report_alloc(task, MT_MALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mmap(struct task *task, struct library_symbol *libsym)
|
static int _report_mmap(struct task *task, struct library_symbol *libsym)
|
||||||
@ -181,7 +198,7 @@ static int _report_mmap(struct task *task, struct library_symbol *libsym)
|
|||||||
|
|
||||||
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);
|
return report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mmap64(struct task *task, struct library_symbol *libsym)
|
static int _report_mmap64(struct task *task, struct library_symbol *libsym)
|
||||||
@ -211,7 +228,7 @@ 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);
|
return report_alloc(task, MT_MMAP64, ret, size.l, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_munmap(struct task *task, struct library_symbol *libsym)
|
static int report_munmap(struct task *task, struct library_symbol *libsym)
|
||||||
@ -222,7 +239,7 @@ static int report_munmap(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);
|
return report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_memalign(struct task *task, struct library_symbol *libsym)
|
static int _report_memalign(struct task *task, struct library_symbol *libsym)
|
||||||
@ -233,7 +250,7 @@ static int _report_memalign(struct task *task, struct library_symbol *libsym)
|
|||||||
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);
|
return report_alloc(task, MT_MEMALIGN, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_posix_memalign(struct task *task, struct library_symbol *libsym)
|
static int _report_posix_memalign(struct task *task, struct library_symbol *libsym)
|
||||||
@ -260,7 +277,7 @@ 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);
|
return 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 int _report_aligned_alloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -271,7 +288,7 @@ static int _report_aligned_alloc(struct task *task, struct library_symbol *libsy
|
|||||||
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);
|
return report_alloc(task, MT_ALIGNED_ALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_valloc(struct task *task, struct library_symbol *libsym)
|
static int _report_valloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -282,7 +299,7 @@ static int _report_valloc(struct task *task, struct library_symbol *libsym)
|
|||||||
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);
|
return report_alloc(task, MT_VALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_pvalloc(struct task *task, struct library_symbol *libsym)
|
static int _report_pvalloc(struct task *task, struct library_symbol *libsym)
|
||||||
@ -293,7 +310,7 @@ static int _report_pvalloc(struct task *task, struct library_symbol *libsym)
|
|||||||
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);
|
return report_alloc(task, MT_PVALLOC, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int report_mremap(struct task *task, struct library_symbol *libsym)
|
static int report_mremap(struct task *task, struct library_symbol *libsym)
|
||||||
@ -301,7 +318,7 @@ static int 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);
|
return report_alloc(task, MT_MUNMAP, addr, size, 0, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _report_mremap(struct task *task, struct library_symbol *libsym)
|
static int _report_mremap(struct task *task, struct library_symbol *libsym)
|
||||||
@ -309,33 +326,33 @@ static int _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);
|
return report_alloc(task, MT_MMAP, ret, size, options.bt_depth, libsym);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct function flist[] = {
|
static const struct function flist[] = {
|
||||||
{ "malloc", 0, 2, NULL, _report_malloc },
|
{ "malloc", "malloc", 0, NULL, _report_malloc },
|
||||||
{ "free", 0, 3, report_free, NULL },
|
{ "free", "free", 0, report_free, NULL },
|
||||||
{ "realloc", 0, 4, report_realloc, _report_realloc },
|
{ "realloc", "realloc", 0, report_realloc, _report_realloc },
|
||||||
{ "calloc", 0, 5, NULL, _report_calloc },
|
{ "calloc", "calloc", 0, NULL, _report_calloc },
|
||||||
{ "posix_memalign", 0, 6, NULL, _report_posix_memalign },
|
{ "posix_memalign", "posix_memalign", 0, NULL, _report_posix_memalign },
|
||||||
{ "mmap", 0, 7, NULL, _report_mmap },
|
{ "mmap", "mmap", 0, NULL, _report_mmap },
|
||||||
{ "mmap64", 1, 8, NULL, _report_mmap64 },
|
{ "mmap64", "mmap64", 1, NULL, _report_mmap64 },
|
||||||
{ "munmap", 0, 9, report_munmap, _null },
|
{ "munmap", "munmap", 0, report_munmap, _null },
|
||||||
{ "memalign", 0, 10, NULL, _report_memalign },
|
{ "memalign", "memalign", 0, NULL, _report_memalign },
|
||||||
{ "aligned_alloc", 1, 11, NULL, _report_aligned_alloc },
|
{ "aligned_alloc", "aligned_alloc", 1, NULL, _report_aligned_alloc },
|
||||||
{ "valloc", 1, 12, NULL, _report_valloc },
|
{ "valloc", "valloc", 1, NULL, _report_valloc },
|
||||||
{ "pvalloc", 1, 13, NULL, _report_pvalloc },
|
{ "pvalloc", "pvalloc", 1, NULL, _report_pvalloc },
|
||||||
{ "mremap", 0, 14, report_mremap, _report_mremap },
|
{ "mremap", "mremap", 0, report_mremap, _report_mremap },
|
||||||
{ "cfree", 1, 15, report_free, NULL },
|
{ "cfree", "cfree", 1, report_free, NULL },
|
||||||
|
|
||||||
{ "_Znwm", 1, 17, NULL, _report_malloc }, /* operator new(unsigned long) */
|
{ "new(unsigned long)", "_Znwm", 1, NULL, _report_malloc },
|
||||||
{ "_Znam", 1, 18, NULL, _report_malloc }, /* operator new[](unsigned long) */
|
{ "new[](unsigned long)", "_Znam", 1, NULL, _report_malloc },
|
||||||
{ "_ZnwmRKSt9nothrow_t", 1, 19, NULL, _report_malloc }, /* operator new(unsigned long, std::nothrow_t const&) */
|
{ "new(unsigned long, std::nothrow_t const&)", "_ZnwmRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||||
{ "_ZnamRKSt9nothrow_t", 1, 20, NULL, _report_malloc }, /* operator new[](unsigned long, std::nothrow_t const& */
|
{ "new[](unsigned long, std::nothrow_t const&)", "_ZnamRKSt9nothrow_t", 1, NULL, _report_malloc },
|
||||||
{ "_ZdlPv", 1, 21, report_free, NULL }, /* operator delete(void*) */
|
{ "delete(void*)", "_ZdlPv", 1, report_free, NULL },
|
||||||
{ "_ZdaPv", 1, 22, report_free, NULL }, /* operator delete[](void*) */
|
{ "delete[](void*)", "_ZdaPv", 1, report_free, NULL },
|
||||||
{ "_ZdlPvRKSt9nothrow_t", 1, 23, report_free, NULL }, /* operator delete(void*, std::nothrow_t const&) */
|
{ "delete(void*, std::nothrow_t const&)", "_ZdlPvRKSt9nothrow_t", 1, report_free, NULL },
|
||||||
{ "_ZdaPvRKSt9nothrow_t", 1, 24, report_free, NULL }, /* operator delete[](void*, std::nothrow_t const&) */
|
{ "delete[](void*, std::nothrow_t const&)", "_ZdaPvRKSt9nothrow_t", 1, report_free, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct function *flist_matches_symbol(const char *sym_name)
|
const struct function *flist_matches_symbol(const char *sym_name)
|
||||||
@ -354,14 +371,14 @@ const struct function *flist_matches_symbol(const char *sym_name)
|
|||||||
|
|
||||||
int _report_map(struct task *task, struct library *lib, enum mt_operation op)
|
int _report_map(struct task *task, struct library *lib, enum mt_operation op)
|
||||||
{
|
{
|
||||||
size_t len = strlen(lib->filename) + 1;
|
struct libref *libref = lib->libref;
|
||||||
|
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->offset = libref->load_offset;
|
||||||
|
payload->size = libref->load_size;
|
||||||
|
|
||||||
payload->addr = lib->load_addr;
|
memcpy(payload->filename, libref->filename, len);
|
||||||
payload->offset = lib->load_offset;
|
|
||||||
payload->size = lib->load_size;
|
|
||||||
|
|
||||||
memcpy(payload->filename, lib->filename, len);
|
|
||||||
|
|
||||||
return server_send_msg(op, task->pid, 0, payload, sizeof(struct mt_map_payload) + len);
|
return server_send_msg(op, task->pid, 0, payload, sizeof(struct mt_map_payload) + len);
|
||||||
}
|
}
|
||||||
|
|||||||
4
report.h
4
report.h
@ -26,12 +26,12 @@
|
|||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
|
||||||
struct function {
|
struct function {
|
||||||
|
/* symbol name */
|
||||||
|
const char *demangled_name;
|
||||||
/* symbol name */
|
/* symbol name */
|
||||||
const char *name;
|
const char *name;
|
||||||
/* level for aliased symbol */
|
/* level for aliased symbol */
|
||||||
unsigned int level;
|
unsigned int level;
|
||||||
/* minimum number of hw breakpoints for using a hw bp */
|
|
||||||
unsigned int hw_bp_min;
|
|
||||||
/* report when function is entered */
|
/* report when function is entered */
|
||||||
int (*report_in)(struct task *task, struct library_symbol *libsym);
|
int (*report_in)(struct task *task, struct library_symbol *libsym);
|
||||||
/* report when function is exited */
|
/* report when function is exited */
|
||||||
|
|||||||
87
server.c
87
server.c
@ -30,6 +30,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/sysinfo.h>
|
#include <sys/sysinfo.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
|
||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
#include "breakpoint.h"
|
#include "breakpoint.h"
|
||||||
@ -83,10 +84,13 @@ int server_connected(void)
|
|||||||
static void server_close(void)
|
static void server_close(void)
|
||||||
{
|
{
|
||||||
if (server_connected()) {
|
if (server_connected()) {
|
||||||
shutdown(server_fd, SHUT_RDWR);
|
if (!options.logfile)
|
||||||
|
shutdown(server_fd, SHUT_RDWR);
|
||||||
|
|
||||||
close(server_fd);
|
close(server_fd);
|
||||||
server_fd = -1;
|
server_fd = -1;
|
||||||
each_process(&stop_trace);
|
each_process(&stop_trace);
|
||||||
|
each_pid(&fix_about_exit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,10 +98,11 @@ int server_poll(void)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
|
|
||||||
if (command_pending) {
|
if (command_pending) {
|
||||||
ret = server_handle_command();
|
ret = server_handle_command();
|
||||||
|
|
||||||
if (options.server)
|
if (options.trace)
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
command_pending = 0;
|
command_pending = 0;
|
||||||
@ -119,10 +124,15 @@ int server_handle_command(void)
|
|||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct mt_msg cmd;
|
struct mt_msg cmd;
|
||||||
void *payload = NULL;
|
void *payload;
|
||||||
struct task *task;
|
struct task *task;
|
||||||
unsigned int mode = server_mode;
|
unsigned int mode;
|
||||||
|
|
||||||
|
if (options.logfile)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
payload = NULL;
|
||||||
|
mode = server_mode;
|
||||||
server_mode = MODE_NONE;
|
server_mode = MODE_NONE;
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
@ -154,7 +164,7 @@ int server_handle_command(void)
|
|||||||
}
|
}
|
||||||
server_close();
|
server_close();
|
||||||
|
|
||||||
return options.server ? 0: -1;
|
return options.trace ? 0: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cmd.payload_len) {
|
if (cmd.payload_len) {
|
||||||
@ -250,27 +260,25 @@ int server_start(void)
|
|||||||
if (!thread)
|
if (!thread)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
listen_fd = bind_to(options.listen, options.port);
|
server_mode = MODE_NONE;
|
||||||
|
|
||||||
|
listen_fd = bind_to(options.address, options.port);
|
||||||
if (listen_fd < 0)
|
if (listen_fd < 0)
|
||||||
fatal("colud not bind socket: %s:%s", options.listen, options.port);
|
fatal("could not bind socket: %s", options.address);
|
||||||
|
|
||||||
if (listen(listen_fd, 1) < 0)
|
if (listen(listen_fd, 1) < 0)
|
||||||
fatal("listen (%s)", strerror(errno));
|
fatal("listen (%s)", strerror(errno));
|
||||||
|
|
||||||
if (options.wait) {
|
if (options.wait) {
|
||||||
fprintf(stderr, "waiting for client connection...\n");
|
fprintf(stderr, "waiting for client connection... ");
|
||||||
|
|
||||||
server_fd = TEMP_FAILURE_RETRY(accept(listen_fd, NULL, 0));
|
server_fd = TEMP_FAILURE_RETRY(accept(listen_fd, NULL, 0));
|
||||||
if (server_fd < 0)
|
if (server_fd < 0)
|
||||||
fatal("accept (%s)", strerror(errno));
|
fatal("accept (%s)", strerror(errno));
|
||||||
|
|
||||||
|
fprintf(stderr, "connected!\n");
|
||||||
|
server_mode = MODE_ACCEPTED;
|
||||||
report_info(1);
|
report_info(1);
|
||||||
report_processes();
|
|
||||||
|
|
||||||
each_process(&start_trace);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
each_process(&stop_trace);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sem_init(&sem, 0, 1);
|
sem_init(&sem, 0, 1);
|
||||||
@ -308,6 +316,9 @@ int server_start_pair(void)
|
|||||||
{
|
{
|
||||||
int sv[2];
|
int sv[2];
|
||||||
|
|
||||||
|
server_mode = MODE_NONE;
|
||||||
|
listen_fd = -1;
|
||||||
|
|
||||||
thread = thread_new();
|
thread = thread_new();
|
||||||
if (!thread)
|
if (!thread)
|
||||||
return -1;
|
return -1;
|
||||||
@ -332,20 +343,45 @@ 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, uint32_t tid, const void *payload, unsigned int payload_len)
|
||||||
{
|
{
|
||||||
|
if (options.logfile) {
|
||||||
|
struct iovec io[2];
|
||||||
|
struct mt_msg mt_msg;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
mt_msg.operation = op;
|
||||||
|
mt_msg.pid = pid;
|
||||||
|
mt_msg.tid = tid;
|
||||||
|
mt_msg.payload_len = payload_len;
|
||||||
|
|
||||||
|
io[0].iov_base = &mt_msg;
|
||||||
|
io[0].iov_len = sizeof(mt_msg);
|
||||||
|
|
||||||
|
io[1].iov_base = (void *)payload;
|
||||||
|
io[1].iov_len = payload_len;
|
||||||
|
|
||||||
|
ret = writev(server_fd, io, ARRAY_SIZE(io));
|
||||||
|
|
||||||
|
if ((size_t)ret != io[0].iov_len + io[1].iov_len)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return sock_send_msg(server_fd, op, pid, tid, payload, payload_len);
|
return sock_send_msg(server_fd, op, pid, tid, payload, payload_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
int server_stop(void)
|
int server_stop(void)
|
||||||
{
|
{
|
||||||
thread_cancel(thread);
|
|
||||||
if (thread)
|
|
||||||
thread_join(thread);
|
|
||||||
|
|
||||||
server_close();
|
server_close();
|
||||||
|
|
||||||
if (listen_fd != -1) {
|
if (listen_fd != -1) {
|
||||||
if (is_named(options.listen))
|
thread_cancel(thread);
|
||||||
unlink(options.listen);
|
if (thread)
|
||||||
|
thread_join(thread);
|
||||||
|
|
||||||
|
if (is_named(options.address))
|
||||||
|
unlink(options.address);
|
||||||
|
|
||||||
close(listen_fd);
|
close(listen_fd);
|
||||||
listen_fd = -1;
|
listen_fd = -1;
|
||||||
}
|
}
|
||||||
@ -353,3 +389,14 @@ int server_stop(void)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int server_logfile(void)
|
||||||
|
{
|
||||||
|
listen_fd = -1;
|
||||||
|
|
||||||
|
server_fd = open(options.logfile, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
|
||||||
|
if (server_fd == -1)
|
||||||
|
fatal("could not open logfile: %s", options.logfile);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
1
server.h
1
server.h
@ -34,6 +34,7 @@ int server_handle_command(void);
|
|||||||
int server_connected(void);
|
int server_connected(void);
|
||||||
int server_stop(void);
|
int server_stop(void);
|
||||||
int server_poll(void);
|
int server_poll(void);
|
||||||
|
int server_logfile(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@ -176,12 +176,12 @@ static inline int access_mem(struct dwarf_addr_space *as, arch_addr_t addr, void
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if (as) {
|
if (as) {
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct library *lib = c->lib;
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
if (addr < ARCH_ADDR_T(lib->image_addr))
|
if (addr < ARCH_ADDR_T(libref->image_addr))
|
||||||
fatal("invalid access mem: addr %#lx < %p", addr, lib->image_addr);
|
fatal("invalid access mem: addr %#lx < %p", addr, libref->image_addr);
|
||||||
if (addr >= ARCH_ADDR_T(lib->image_addr + lib->load_size))
|
if (addr >= ARCH_ADDR_T(libref->image_addr + libref->load_size))
|
||||||
fatal("invalid access mem: addr %#lx >= %p", addr, lib->image_addr + lib->load_size);
|
fatal("invalid access mem: addr %#lx >= %p", addr, libref->image_addr + libref->load_size);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -506,8 +506,8 @@ static int arm_exidx_extract(struct dwarf_addr_space *as, arch_addr_t entry, uin
|
|||||||
static unsigned long arm_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip, void *exidx_data, unsigned long exidx_len)
|
static unsigned long arm_search_unwind_table(struct dwarf_addr_space *as, arch_addr_t ip, void *exidx_data, unsigned long exidx_len)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct library *lib = c->lib;
|
struct libref *libref = c->libref;
|
||||||
unsigned long map_offset = (unsigned long)lib->image_addr + lib->load_offset - lib->load_addr;
|
unsigned long map_offset = (unsigned long)libref->image_addr + libref->load_offset - libref->load_addr;
|
||||||
unsigned long lo, hi, e, f;
|
unsigned long lo, hi, e, f;
|
||||||
arch_addr_t val;
|
arch_addr_t val;
|
||||||
|
|
||||||
@ -542,12 +542,12 @@ static unsigned long arm_search_unwind_table(struct dwarf_addr_space *as, arch_a
|
|||||||
static int arm_exidx_step(struct dwarf_addr_space *as)
|
static int arm_exidx_step(struct dwarf_addr_space *as)
|
||||||
{
|
{
|
||||||
struct dwarf_cursor *c = &as->cursor;
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
struct library *lib = c->lib;
|
struct libref *libref = c->libref;
|
||||||
arch_addr_t old_ip, old_cfa, entry;
|
arch_addr_t old_ip, old_cfa, entry;
|
||||||
uint8_t buf[32];
|
uint8_t buf[32];
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!lib)
|
if (!libref)
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
|
|
||||||
old_ip = c->ip;
|
old_ip = c->ip;
|
||||||
@ -556,7 +556,7 @@ static int arm_exidx_step(struct dwarf_addr_space *as)
|
|||||||
/* mark PC unsaved */
|
/* mark PC unsaved */
|
||||||
c->loc[DWARF_ARM_PC] = DWARF_NULL_LOC;
|
c->loc[DWARF_ARM_PC] = DWARF_NULL_LOC;
|
||||||
|
|
||||||
entry = arm_search_unwind_table(as, c->ip, lib->exidx_data, lib->exidx_len);
|
entry = arm_search_unwind_table(as, c->ip, libref->exidx_data, libref->exidx_len);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return -DWARF_ENOINFO;
|
return -DWARF_ENOINFO;
|
||||||
|
|
||||||
@ -646,3 +646,8 @@ int dwarf_arch_step(struct dwarf_addr_space *as)
|
|||||||
return -DWARF_EBADFRAME;
|
return -DWARF_EBADFRAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -72,3 +72,11 @@ int backtrace_step(struct task *task)
|
|||||||
return dwarf_step(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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|||||||
@ -269,3 +269,8 @@ unsigned int dwarf_to_regnum(unsigned int num)
|
|||||||
return ~0;
|
return ~0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -413,22 +413,22 @@ static void linkmap_add(struct task *task, struct lt_r_debug_64 *dbg)
|
|||||||
)
|
)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
struct library *lib = library_new();
|
struct libref *libref = libref_new(LIBTYPE_LIB);
|
||||||
|
|
||||||
if (!lib) {
|
if (!libref) {
|
||||||
fprintf(stderr, "Couldn't instance library object %s\n", lib_name);
|
fprintf(stderr, "Couldn't instance library object %s\n", lib_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elf_read_library(task, lib, lib_name, rlm.l_addr) < 0) {
|
if (elf_read_library(task, libref, lib_name, rlm.l_addr) < 0) {
|
||||||
library_destroy(task, lib);
|
libref_delete(libref);
|
||||||
fprintf(stderr, "Couldn't load ELF object %s\n", lib_name);
|
fprintf(stderr, "Couldn't load ELF object %s\n", lib_name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
lib->key = ARCH_ADDR_T(rlm.l_addr);
|
libref->key = ARCH_ADDR_T(rlm.l_addr);
|
||||||
|
|
||||||
library_add(task, lib);
|
library_add(task, libref);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -113,13 +113,16 @@ int sock_send_msg(int fd, enum mt_operation op, uint32_t pid, uint32_t tid, cons
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sock_unix(const char *path, struct sock_u_descr *descr)
|
static int sock_unix(const char *path, struct sock_u_descr *descr, int create)
|
||||||
{
|
{
|
||||||
struct stat statbuf;
|
struct stat statbuf;
|
||||||
|
|
||||||
if (stat(path, &statbuf) >= 0) {
|
if (stat(path, &statbuf) >= 0) {
|
||||||
if (!S_ISSOCK(statbuf.st_mode))
|
if (!S_ISSOCK(statbuf.st_mode))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
if (create)
|
||||||
|
unlink(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
descr->addr.sun_family = AF_UNIX;
|
descr->addr.sun_family = AF_UNIX;
|
||||||
@ -160,7 +163,7 @@ int connect_to(const char *node, const char *service)
|
|||||||
if (*node == '/' || *node == '.') {
|
if (*node == '/' || *node == '.') {
|
||||||
struct sock_u_descr descr;
|
struct sock_u_descr descr;
|
||||||
|
|
||||||
sfd = sock_unix(node, &descr);
|
sfd = sock_unix(node, &descr, 0);
|
||||||
if (sfd == -1)
|
if (sfd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -201,7 +204,7 @@ int bind_to(const char *node, const char *service)
|
|||||||
if (is_named(node)) {
|
if (is_named(node)) {
|
||||||
struct sock_u_descr descr;
|
struct sock_u_descr descr;
|
||||||
|
|
||||||
sfd = sock_unix(node, &descr);
|
sfd = sock_unix(node, &descr, 1);
|
||||||
if (sfd == -1)
|
if (sfd == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -218,6 +221,9 @@ int bind_to(const char *node, const char *service)
|
|||||||
if (sfd == -1)
|
if (sfd == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)))
|
||||||
|
fatal("setsockopt (%s)", strerror(errno));
|
||||||
|
|
||||||
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
|
if (bind(sfd, rp->ai_addr, rp->ai_addrlen) == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -228,9 +234,6 @@ int bind_to(const char *node, const char *service)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)))
|
|
||||||
fatal("setsockopt (%s)", strerror(errno));
|
|
||||||
|
|
||||||
return sfd;
|
return sfd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -37,6 +37,7 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
|
||||||
#ifdef HAVE_LIBSELINUX
|
#ifdef HAVE_LIBSELINUX
|
||||||
#include <selinux/selinux.h>
|
#include <selinux/selinux.h>
|
||||||
@ -124,7 +125,7 @@ static int child_event(struct task *task, enum event_type ev)
|
|||||||
int pid = data;
|
int pid = data;
|
||||||
|
|
||||||
if (!pid2task(pid)) {
|
if (!pid2task(pid)) {
|
||||||
struct task *child = task_new(pid, 0);
|
struct task *child = task_new(pid);
|
||||||
|
|
||||||
if (!child)
|
if (!child)
|
||||||
return -1;
|
return -1;
|
||||||
@ -235,7 +236,7 @@ static void process_event(struct task *task, int status)
|
|||||||
if (stop_signal == 0)
|
if (stop_signal == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (stop_signal != SIGTRAP && stop_signal != SIGSEGV && stop_signal != SIGILL)
|
if (stop_signal != SIGTRAP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (fetch_context(task) == -1) {
|
if (fetch_context(task) == -1) {
|
||||||
@ -251,14 +252,15 @@ 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) {
|
||||||
/* todo: check if this was really a hw bp */
|
if (get_hw_bp_state(task, i))
|
||||||
bp = task->hw_bp[i];
|
bp = task->hw_bp[i];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bp) {
|
if (bp) {
|
||||||
assert(bp->type != SW_BP);
|
assert(bp->type != BP_SW);
|
||||||
assert(bp->hw_bp_slot == i);
|
assert(bp->hw_bp_slot == i);
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (options.verbose > 1)
|
||||||
@ -268,9 +270,15 @@ static void process_event(struct task *task, int status)
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
bp = breakpoint_find(leader, ip - DECR_PC_AFTER_BREAK);
|
bp = breakpoint_find(leader, ip - DECR_PC_AFTER_BREAK);
|
||||||
if (!bp)
|
if (!bp) {
|
||||||
|
task->event.type = EVENT_NONE;
|
||||||
|
continue_task(task, 0);
|
||||||
return;
|
return;
|
||||||
assert(bp->type == SW_BP);
|
}
|
||||||
|
#if HW_BREAKPOINTS > 0
|
||||||
|
assert(bp->type != BP_HW_SCRATCH);
|
||||||
|
assert(bp->hw == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (options.verbose > 1)
|
if (options.verbose > 1)
|
||||||
++leader->num_sw_bp;
|
++leader->num_sw_bp;
|
||||||
@ -284,7 +292,7 @@ static void process_event(struct task *task, int status)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
task->event.type = EVENT_BREAKPOINT;
|
task->event.type = EVENT_BREAKPOINT;
|
||||||
task->event.e_un.breakpoint = breakpoint_ref(bp);
|
task->event.e_un.breakpoint = breakpoint_get(bp);
|
||||||
|
|
||||||
debug(DEBUG_EVENT, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr);
|
debug(DEBUG_EVENT, "BREAKPOINT: pid=%d, addr=%#lx", task->pid, task->event.e_un.breakpoint->addr);
|
||||||
|
|
||||||
@ -344,7 +352,6 @@ int untrace_task(struct task *task, int signum)
|
|||||||
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;
|
||||||
goto skip;
|
goto skip;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
signum = fix_signal(task, signum);
|
signum = fix_signal(task, signum);
|
||||||
@ -525,7 +532,7 @@ struct task *wait_event(void)
|
|||||||
|
|
||||||
task = pid2task(pid);
|
task = pid2task(pid);
|
||||||
if (!task) {
|
if (!task) {
|
||||||
task = task_new(pid, 0);
|
task = task_new(pid);
|
||||||
|
|
||||||
if (task)
|
if (task)
|
||||||
trace_setup(task, status, SIGSTOP);
|
trace_setup(task, status, SIGSTOP);
|
||||||
@ -552,16 +559,53 @@ void wait_event_wakeup(void)
|
|||||||
pthread_mutex_unlock(&mutex);
|
pthread_mutex_unlock(&mutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef HAVE_PROCESS_VM_READV
|
||||||
|
static ssize_t process_vm_readv(pid_t pid, const struct iovec *local_iov, unsigned long liovcnt, const struct iovec *remote_iov, unsigned long riovcnt, unsigned long flags)
|
||||||
|
{
|
||||||
|
#ifdef __NR_process_vm_readv
|
||||||
|
return syscall(__NR_process_vm_readv, pid, local_iov, liovcnt, remote_iov, riovcnt, flags);
|
||||||
|
#else
|
||||||
|
errno = ENOSYS;
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t len)
|
ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t len)
|
||||||
{
|
{
|
||||||
|
static int process_vm_call_nosys;
|
||||||
|
ssize_t num_bytes;
|
||||||
|
size_t n;
|
||||||
union {
|
union {
|
||||||
long a;
|
long a;
|
||||||
char c[sizeof(long)];
|
char c[sizeof(long)];
|
||||||
} a;
|
} a;
|
||||||
|
|
||||||
ssize_t num_bytes = 0;
|
if (len > sizeof(a) && !process_vm_call_nosys) {
|
||||||
size_t n = sizeof(a.a);
|
struct iovec local[1];
|
||||||
|
struct iovec remote[1];
|
||||||
|
|
||||||
|
local[0].iov_base = dst;
|
||||||
|
local[0].iov_len = len;
|
||||||
|
remote[0].iov_base = (void *)addr;
|
||||||
|
remote[0].iov_len = len;
|
||||||
|
|
||||||
|
num_bytes = process_vm_readv(task->pid, local, 1, remote, 1, 0);
|
||||||
|
if (num_bytes != -1)
|
||||||
|
return num_bytes;
|
||||||
|
|
||||||
|
if (errno != EFAULT) {
|
||||||
|
if (errno != ENOSYS) {
|
||||||
|
fprintf(stderr, "%s pid=%d process_vm_readv: %s\n", __FUNCTION__, task->pid, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
process_vm_call_nosys = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num_bytes = 0;
|
||||||
|
n = sizeof(a.a);
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
@ -589,13 +633,15 @@ ssize_t copy_from_proc(struct task *task, arch_addr_t addr, void *dst, size_t le
|
|||||||
|
|
||||||
ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_t len)
|
ssize_t copy_to_proc(struct task *task, arch_addr_t addr, const void *src, size_t len)
|
||||||
{
|
{
|
||||||
|
ssize_t num_bytes;
|
||||||
|
size_t n;
|
||||||
union {
|
union {
|
||||||
long a;
|
long a;
|
||||||
char c[sizeof(long)];
|
char c[sizeof(long)];
|
||||||
} a;
|
} a;
|
||||||
|
|
||||||
ssize_t num_bytes = 0;
|
num_bytes = 0;
|
||||||
size_t n = sizeof(a.a);
|
n = sizeof(a.a);
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
if (n > len) {
|
if (n > len) {
|
||||||
|
|||||||
@ -37,6 +37,21 @@
|
|||||||
#define BP_RW 2
|
#define BP_RW 2
|
||||||
#define BP_W 4
|
#define BP_W 4
|
||||||
|
|
||||||
|
int get_hw_bp_state(struct task *task, unsigned int n)
|
||||||
|
{
|
||||||
|
long ret;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
ret = ptrace(PTRACE_PEEKUSER, task->pid, offsetof(struct user, u_debugreg[6]), 0);
|
||||||
|
if (ret == -1 && errno) {
|
||||||
|
if (errno != ESRCH)
|
||||||
|
fprintf(stderr, "PTRACE_PEEKUSER u_debugreg[6] pid=%d %s\n", task->pid, strerror(errno));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (ret & (1 << n)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int _apply_hw_bp(struct task *task, uint32_t dr7)
|
static int _apply_hw_bp(struct task *task, uint32_t dr7)
|
||||||
{
|
{
|
||||||
long ret;
|
long ret;
|
||||||
|
|||||||
@ -28,6 +28,7 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
#define BREAKPOINT_VALUE { 0xcc }
|
#define BREAKPOINT_VALUE { 0xcc }
|
||||||
#define BREAKPOINT_LENGTH 1
|
#define BREAKPOINT_LENGTH 1
|
||||||
@ -40,8 +41,21 @@
|
|||||||
#ifdef __x86_64__
|
#ifdef __x86_64__
|
||||||
#define MT_ELFCLASS2 ELFCLASS64
|
#define MT_ELFCLASS2 ELFCLASS64
|
||||||
#define MT_ELF_MACHINE2 EM_X86_64
|
#define MT_ELF_MACHINE2 EM_X86_64
|
||||||
|
|
||||||
|
#ifndef __NR_process_vm_readv
|
||||||
|
#define __NR_process_vm_readv 310
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#else /* __x86_64__ */
|
||||||
|
|
||||||
|
#ifndef __NR_process_vm_readv
|
||||||
|
#define __NR_process_vm_readv 347
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __x86_64__ */
|
||||||
|
|
||||||
|
#define GUESS_CALLER
|
||||||
|
|
||||||
#define HW_BREAKPOINTS 4
|
#define HW_BREAKPOINTS 4
|
||||||
|
|
||||||
#define TASK_HAVE_PROCESS_DATA
|
#define TASK_HAVE_PROCESS_DATA
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#include "backend.h"
|
#include "backend.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "dwarf.h"
|
#include "dwarf.h"
|
||||||
|
#include "library.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
|
||||||
struct arch_reg {
|
struct arch_reg {
|
||||||
@ -266,7 +267,7 @@ int dwarf_arch_step(struct dwarf_addr_space *as)
|
|||||||
c->loc[arch_reg->bp] = DWARF_MEM_LOC(rbp);
|
c->loc[arch_reg->bp] = DWARF_MEM_LOC(rbp);
|
||||||
c->loc[arch_reg->ip] = DWARF_MEM_LOC(rbp + DWARF_ADDR_SIZE(as));
|
c->loc[arch_reg->ip] = DWARF_MEM_LOC(rbp + DWARF_ADDR_SIZE(as));
|
||||||
c->cfa = rbp + DWARF_ADDR_SIZE(as) * 2;
|
c->cfa = rbp + DWARF_ADDR_SIZE(as) * 2;
|
||||||
c->use_prev_instr = 1;
|
c->use_prev_instr = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,3 +305,45 @@ int dwarf_arch_map_reg(struct dwarf_addr_space *as, unsigned int reg)
|
|||||||
return dwarf_to_regnum_map32[reg];
|
return dwarf_to_regnum_map32[reg];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct call_op {
|
||||||
|
unsigned int off;
|
||||||
|
unsigned int len;
|
||||||
|
unsigned char *mask;
|
||||||
|
unsigned char *op;
|
||||||
|
} call_op[] =
|
||||||
|
{
|
||||||
|
{ 5, 1, (unsigned char [1]){ 0xff }, (unsigned char [1]){ 0xe8 } }, /* call */
|
||||||
|
{ 3, 2, (unsigned char [2]){ 0xff, 0xff }, (unsigned char [2]){ 0xff, 0x14 } }, /* call *(sp) */
|
||||||
|
{ 2, 2, (unsigned char [2]){ 0xff, 0xfc }, (unsigned char [2]){ 0xff, 0x10 } }, /* call *(reg) */
|
||||||
|
{ 4, 2, (unsigned char [2]){ 0xff, 0xff }, (unsigned char [2]){ 0xff, 0x54 } }, /* call *off8(reg, idx, scale) */
|
||||||
|
{ 3, 2, (unsigned char [2]){ 0xff, 0xfc }, (unsigned char [2]){ 0xff, 0x50 } }, /* call *off8 */
|
||||||
|
{ 7, 2, (unsigned char [2]){ 0xff, 0xff }, (unsigned char [2]){ 0xff, 0x94 } }, /* call *off32(reg, idx, scale) */
|
||||||
|
{ 6, 2, (unsigned char [2]){ 0xff, 0xfc }, (unsigned char [2]){ 0xff, 0x90 } }, /* call *off32 */
|
||||||
|
{ 2, 2, (unsigned char [2]){ 0xff, 0xfc }, (unsigned char [2]){ 0xff, 0xd0 } }, /* call *reg */
|
||||||
|
{ 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int dwarf_arch_check_call(struct dwarf_addr_space *as, arch_addr_t ip)
|
||||||
|
{
|
||||||
|
static struct call_op *p;
|
||||||
|
struct dwarf_cursor *c = &as->cursor;
|
||||||
|
struct libref *libref = c->libref;
|
||||||
|
|
||||||
|
for(p = call_op; p->len; ++p) {
|
||||||
|
if (ip - ARCH_ADDR_T(libref->load_addr) >= p->off) {
|
||||||
|
unsigned int i;
|
||||||
|
unsigned char *addr = libref->image_addr + ip - p->off - libref->load_addr;
|
||||||
|
|
||||||
|
for(i = 0; i < call_op[i].len; ++i) {
|
||||||
|
if ((addr[i] & p->mask[i]) != p->op[i])
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == p->len)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
60
task.c
60
task.c
@ -42,6 +42,7 @@
|
|||||||
#include "library.h"
|
#include "library.h"
|
||||||
#include "mtelf.h"
|
#include "mtelf.h"
|
||||||
#include "report.h"
|
#include "report.h"
|
||||||
|
#include "server.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
@ -130,7 +131,7 @@ static int leader_setup(struct task *leader)
|
|||||||
return backtrace_init(leader);
|
return backtrace_init(leader);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int task_init(struct task *task, int attached)
|
static int task_init(struct task *task)
|
||||||
{
|
{
|
||||||
pid_t tgid;
|
pid_t tgid;
|
||||||
|
|
||||||
@ -163,7 +164,7 @@ static int task_init(struct task *task, int attached)
|
|||||||
list_add_tail(&task->task_list, &task->leader->task_list);
|
list_add_tail(&task->task_list, &task->leader->task_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
task->attached = attached;
|
task->attached = 1;
|
||||||
|
|
||||||
if (arch_task_init(task) < 0)
|
if (arch_task_init(task) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
@ -171,6 +172,8 @@ static int task_init(struct task *task, int attached)
|
|||||||
if (os_task_init(task) < 0)
|
if (os_task_init(task) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
breakpoint_hw_destroy(task);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,6 +189,8 @@ static int leader_cleanup(struct task *leader)
|
|||||||
breakpoint_clear_all(leader);
|
breakpoint_clear_all(leader);
|
||||||
backtrace_destroy(leader);
|
backtrace_destroy(leader);
|
||||||
|
|
||||||
|
list_del(&leader->leader_list);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +199,6 @@ static void leader_release(struct task *leader)
|
|||||||
if (!leader_cleanup(leader))
|
if (!leader_cleanup(leader))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
list_del(&leader->leader_list);
|
|
||||||
free(leader);
|
free(leader);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,7 +224,7 @@ static void task_destroy(struct task *task)
|
|||||||
leader_release(leader);
|
leader_release(leader);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct task *task_new(pid_t pid, int traced)
|
struct task *task_new(pid_t pid)
|
||||||
{
|
{
|
||||||
struct task *task = malloc(sizeof(*task));
|
struct task *task = malloc(sizeof(*task));
|
||||||
|
|
||||||
@ -230,16 +234,19 @@ struct task *task_new(pid_t pid, int traced)
|
|||||||
memset(task, 0, sizeof(*task));
|
memset(task, 0, sizeof(*task));
|
||||||
|
|
||||||
task->pid = pid;
|
task->pid = pid;
|
||||||
task->traced = traced;
|
task->traced = 0;
|
||||||
task->stopped = traced;
|
task->stopped = 0;
|
||||||
task->was_stopped = 0;
|
task->was_stopped = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(&task->task_list);
|
INIT_LIST_HEAD(&task->task_list);
|
||||||
INIT_LIST_HEAD(&task->leader_list);
|
INIT_LIST_HEAD(&task->leader_list);
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
INIT_LIST_HEAD(&task->hw_bp_list);
|
||||||
|
#endif
|
||||||
|
|
||||||
library_setup(task);
|
library_setup(task);
|
||||||
|
|
||||||
if (task_init(task, 1) < 0)
|
if (task_init(task) < 0)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
init_event(task);
|
init_event(task);
|
||||||
@ -257,7 +264,7 @@ static void remove_task_cb(struct task *task, void *data)
|
|||||||
if (task != data) {
|
if (task != data) {
|
||||||
debug(DEBUG_FUNCTION, "clear pid=%d from leader pid=%d", task->pid, task->leader->pid);
|
debug(DEBUG_FUNCTION, "clear pid=%d from leader pid=%d", task->pid, task->leader->pid);
|
||||||
|
|
||||||
remove_task(task);
|
task_destroy(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -265,21 +272,23 @@ int process_exec(struct task *task)
|
|||||||
{
|
{
|
||||||
struct task *leader = task->leader;
|
struct task *leader = task->leader;
|
||||||
|
|
||||||
leader->threads_stopped--;
|
|
||||||
|
|
||||||
breakpoint_disable_all(leader);
|
|
||||||
each_task(leader, &remove_task_cb, leader);
|
each_task(leader, &remove_task_cb, leader);
|
||||||
|
breakpoint_disable_all(leader);
|
||||||
|
|
||||||
os_task_destroy(leader);
|
os_task_destroy(leader);
|
||||||
arch_task_destroy(leader);
|
arch_task_destroy(leader);
|
||||||
leader_cleanup(leader);
|
leader_cleanup(leader);
|
||||||
|
|
||||||
if (task_init(leader, 0) < 0)
|
assert(leader->threads == 0);
|
||||||
|
|
||||||
|
if (task_init(leader) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
assert(leader->leader == leader);
|
if (server_connected())
|
||||||
|
task->attached = 0;
|
||||||
|
|
||||||
leader->threads_stopped++;
|
assert(leader->leader == leader);
|
||||||
|
assert(leader->threads_stopped == 1);
|
||||||
|
|
||||||
if (leader_setup(leader) < 0)
|
if (leader_setup(leader) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -311,7 +320,7 @@ struct task *task_create(const char *command, char **argv)
|
|||||||
_exit(EXIT_FAILURE);
|
_exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
task = task_new(pid, 0);
|
task = task_new(pid);
|
||||||
if (!task)
|
if (!task)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
@ -321,6 +330,9 @@ struct task *task_create(const char *command, char **argv)
|
|||||||
if (trace_set_options(task) < 0)
|
if (trace_set_options(task) < 0)
|
||||||
goto fail2;
|
goto fail2;
|
||||||
|
|
||||||
|
if (server_connected())
|
||||||
|
task->attached = 0;
|
||||||
|
|
||||||
if (leader_setup(task) < 0)
|
if (leader_setup(task) < 0)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
@ -344,6 +356,7 @@ int task_clone(struct task *task, struct task *newtask)
|
|||||||
assert(newtask->backtrace == NULL);
|
assert(newtask->backtrace == NULL);
|
||||||
|
|
||||||
newtask->is_64bit = task->is_64bit;
|
newtask->is_64bit = task->is_64bit;
|
||||||
|
newtask->attached = task->attached;
|
||||||
|
|
||||||
breakpoint_hw_clone(newtask);
|
breakpoint_hw_clone(newtask);
|
||||||
|
|
||||||
@ -374,6 +387,7 @@ int task_fork(struct task *task, struct task *newtask)
|
|||||||
|
|
||||||
newtask->libsym = task->libsym;
|
newtask->libsym = task->libsym;
|
||||||
newtask->context = task->context;
|
newtask->context = task->context;
|
||||||
|
newtask->attached = task->attached;
|
||||||
|
|
||||||
if (task->breakpoint)
|
if (task->breakpoint)
|
||||||
newtask->breakpoint = breakpoint_find(newtask, newtask->breakpoint->addr);
|
newtask->breakpoint = breakpoint_find(newtask, newtask->breakpoint->addr);
|
||||||
@ -381,7 +395,7 @@ int task_fork(struct task *task, struct task *newtask)
|
|||||||
newtask->breakpoint = NULL;
|
newtask->breakpoint = NULL;
|
||||||
|
|
||||||
if (task->skip_bp)
|
if (task->skip_bp)
|
||||||
newtask->skip_bp = breakpoint_ref(breakpoint_find(newtask, newtask->skip_bp->addr));
|
newtask->skip_bp = breakpoint_get(breakpoint_find(newtask, newtask->skip_bp->addr));
|
||||||
else
|
else
|
||||||
newtask->skip_bp = NULL;
|
newtask->skip_bp = NULL;
|
||||||
|
|
||||||
@ -401,7 +415,7 @@ fail:
|
|||||||
|
|
||||||
void task_reset_bp(struct task *task)
|
void task_reset_bp(struct task *task)
|
||||||
{
|
{
|
||||||
breakpoint_unref(task->skip_bp);
|
breakpoint_put(task->skip_bp);
|
||||||
|
|
||||||
task->breakpoint = NULL;
|
task->breakpoint = NULL;
|
||||||
task->skip_bp = NULL;
|
task->skip_bp = NULL;
|
||||||
@ -413,7 +427,7 @@ static struct task *open_one_pid(pid_t pid)
|
|||||||
|
|
||||||
debug(DEBUG_PROCESS, "pid=%d", pid);
|
debug(DEBUG_PROCESS, "pid=%d", pid);
|
||||||
|
|
||||||
task = task_new(pid, 0);
|
task = task_new(pid);
|
||||||
if (task == NULL)
|
if (task == NULL)
|
||||||
goto fail1;
|
goto fail1;
|
||||||
|
|
||||||
@ -425,7 +439,7 @@ static struct task *open_one_pid(pid_t pid)
|
|||||||
|
|
||||||
return task;
|
return task;
|
||||||
fail2:
|
fail2:
|
||||||
remove_task(task);
|
task_destroy(task);
|
||||||
fail1:
|
fail1:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -513,14 +527,6 @@ fail1:
|
|||||||
remove_proc(leader);
|
remove_proc(leader);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct task *get_first_process(void)
|
|
||||||
{
|
|
||||||
if (list_empty(&list_of_leaders))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return container_of(list_of_leaders.next, struct task, leader_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void each_process(void (*cb)(struct task *task))
|
void each_process(void (*cb)(struct task *task))
|
||||||
{
|
{
|
||||||
struct list_head *it, *next;
|
struct list_head *it, *next;
|
||||||
|
|||||||
25
task.h
25
task.h
@ -56,6 +56,7 @@ struct task {
|
|||||||
unsigned int is_64bit:1;
|
unsigned int is_64bit:1;
|
||||||
unsigned int attached:1;
|
unsigned int attached:1;
|
||||||
unsigned int deleted:1;
|
unsigned int deleted:1;
|
||||||
|
unsigned int about_exit:1;
|
||||||
|
|
||||||
struct breakpoint *breakpoint;
|
struct breakpoint *breakpoint;
|
||||||
struct library_symbol *libsym;
|
struct library_symbol *libsym;
|
||||||
@ -75,9 +76,6 @@ 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;
|
||||||
|
|
||||||
/* array of addresses of hw breakpoints */
|
|
||||||
struct breakpoint *hw_bp[HW_BREAKPOINTS];
|
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
||||||
@ -99,16 +97,26 @@ struct task {
|
|||||||
/* set in leader: number of threads including the leader */
|
/* set in leader: number of threads including the leader */
|
||||||
unsigned int threads;
|
unsigned int threads;
|
||||||
|
|
||||||
/* only used in leader: bit mask for used hw breakpoints */
|
|
||||||
unsigned long hw_bp_mask;
|
|
||||||
|
|
||||||
/* struct task chaining. */
|
/* struct task chaining. */
|
||||||
struct list_head leader_list;
|
struct list_head leader_list;
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 1
|
||||||
|
/* set in leader: list of hw breakpoints */
|
||||||
|
struct list_head hw_bp_list;
|
||||||
|
|
||||||
|
/* set in leader: number of registered hw breakpoints */
|
||||||
|
unsigned long hw_bp_num;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if HW_BREAKPOINTS > 0
|
||||||
|
/* array of active hw breakpoints */
|
||||||
|
struct breakpoint *hw_bp[HW_BREAKPOINTS];
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int process_exec(struct task *task);
|
int process_exec(struct task *task);
|
||||||
|
|
||||||
struct task *task_new(pid_t pid, int traced);
|
struct task *task_new(pid_t pid);
|
||||||
|
|
||||||
struct task *task_create(const char *command, char **argv);
|
struct task *task_create(const char *command, char **argv);
|
||||||
|
|
||||||
@ -125,9 +133,6 @@ int task_fork(struct task *task, struct task *newtask);
|
|||||||
/* reset all breakpoints for task */
|
/* reset all breakpoints for task */
|
||||||
void task_reset_bp(struct task *task);
|
void task_reset_bp(struct task *task);
|
||||||
|
|
||||||
/* get first process of leader list */
|
|
||||||
struct task *get_first_process(void);
|
|
||||||
|
|
||||||
/* Iterate through the leader tasks that mtrace currently traces. */
|
/* Iterate through the leader tasks that mtrace currently traces. */
|
||||||
void each_process(void (*cb)(struct task *task));
|
void each_process(void (*cb)(struct task *task));
|
||||||
|
|
||||||
|
|||||||
18
trace.c
18
trace.c
@ -48,7 +48,7 @@ int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
|||||||
if (task->event.type != EVENT_NONE)
|
if (task->event.type != EVENT_NONE)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if (bp->enabled && bp->type == SW_BP) {
|
if (bp->enabled && !bp->hw) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
breakpoint_disable(task, bp);
|
breakpoint_disable(task, bp);
|
||||||
@ -56,8 +56,8 @@ int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
|||||||
breakpoint_enable(task, bp);
|
breakpoint_enable(task, bp);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
breakpoint_unref(task->skip_bp);
|
breakpoint_put(task->skip_bp);
|
||||||
task->skip_bp = breakpoint_ref(bp);
|
task->skip_bp = breakpoint_get(bp);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -67,6 +67,15 @@ int skip_breakpoint(struct task *task, struct breakpoint *bp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void fix_about_exit(struct task *task)
|
||||||
|
{
|
||||||
|
if (task->about_exit) {
|
||||||
|
task->about_exit = 0;
|
||||||
|
|
||||||
|
continue_task(task, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void detach_task(struct task *task)
|
void detach_task(struct task *task)
|
||||||
{
|
{
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
@ -77,10 +86,11 @@ void detach_task(struct task *task)
|
|||||||
sig = task->event.e_un.signum;
|
sig = task->event.e_un.signum;
|
||||||
else
|
else
|
||||||
if (task->event.type == EVENT_BREAKPOINT)
|
if (task->event.type == EVENT_BREAKPOINT)
|
||||||
breakpoint_unref(task->event.e_un.breakpoint);
|
breakpoint_put(task->event.e_un.breakpoint);
|
||||||
|
|
||||||
remove_event(task);
|
remove_event(task);
|
||||||
breakpoint_hw_destroy(task);
|
breakpoint_hw_destroy(task);
|
||||||
|
fix_about_exit(task);
|
||||||
untrace_task(task, sig);
|
untrace_task(task, sig);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
trace.h
1
trace.h
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "forward.h"
|
#include "forward.h"
|
||||||
|
|
||||||
|
void fix_about_exit(struct task *task);
|
||||||
void detach_task(struct task *task);
|
void detach_task(struct task *task);
|
||||||
void detach_proc(struct task *leader);
|
void detach_proc(struct task *leader);
|
||||||
int skip_breakpoint(struct task *task, struct breakpoint *bp);
|
int skip_breakpoint(struct task *task, struct breakpoint *bp);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user