summaryrefslogtreecommitdiff
path: root/sysdeps
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2013-01-15 08:32:18 -0800
committerAnas Nashif <anas.nashif@intel.com>2013-01-15 08:32:18 -0800
commit689b9dbb8d7f88ab91e7741932ed000b6e49be9a (patch)
tree463f5a1df8b2d35644c260e7bf6c8e0a26198af1 /sysdeps
parent59749d048d9e452f049f9151735b5256756919c3 (diff)
downloadltrace-689b9dbb8d7f88ab91e7741932ed000b6e49be9a.tar.gz
ltrace-689b9dbb8d7f88ab91e7741932ed000b6e49be9a.tar.bz2
ltrace-689b9dbb8d7f88ab91e7741932ed000b6e49be9a.zip
Imported Upstream version 0.7.2upstream/0.7.2
Diffstat (limited to 'sysdeps')
-rw-r--r--sysdeps/Makefile.am29
-rw-r--r--sysdeps/Makefile.in602
-rw-r--r--sysdeps/README25
-rw-r--r--sysdeps/linux-gnu/Makefile60
-rw-r--r--sysdeps/linux-gnu/Makefile.am46
-rw-r--r--sysdeps/linux-gnu/Makefile.in692
-rw-r--r--sysdeps/linux-gnu/alpha/Makefile10
-rw-r--r--sysdeps/linux-gnu/alpha/Makefile.am34
-rw-r--r--sysdeps/linux-gnu/alpha/Makefile.in528
-rw-r--r--sysdeps/linux-gnu/alpha/arch.h21
-rw-r--r--sysdeps/linux-gnu/alpha/plt.c21
-rw-r--r--sysdeps/linux-gnu/alpha/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/alpha/regs.c21
-rw-r--r--sysdeps/linux-gnu/alpha/signalent.h20
-rw-r--r--sysdeps/linux-gnu/alpha/syscallent.h20
-rw-r--r--sysdeps/linux-gnu/alpha/trace.c29
-rw-r--r--sysdeps/linux-gnu/arch_mksyscallent17
-rw-r--r--sysdeps/linux-gnu/arch_syscallent.h1
-rw-r--r--sysdeps/linux-gnu/arm/Makefile10
-rw-r--r--sysdeps/linux-gnu/arm/Makefile.am36
-rw-r--r--sysdeps/linux-gnu/arm/Makefile.in531
-rw-r--r--sysdeps/linux-gnu/arm/arch.h26
-rw-r--r--sysdeps/linux-gnu/arm/arch_syscallent.h20
-rw-r--r--sysdeps/linux-gnu/arm/breakpoint.c73
-rw-r--r--sysdeps/linux-gnu/arm/plt.c40
-rw-r--r--sysdeps/linux-gnu/arm/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/arm/regs.c37
-rw-r--r--sysdeps/linux-gnu/arm/signalent.h20
-rw-r--r--sysdeps/linux-gnu/arm/syscallent.h20
-rw-r--r--sysdeps/linux-gnu/arm/trace.c67
-rw-r--r--sysdeps/linux-gnu/breakpoint.c137
-rw-r--r--sysdeps/linux-gnu/cris/Makefile.am34
-rw-r--r--sysdeps/linux-gnu/cris/Makefile.in528
-rw-r--r--sysdeps/linux-gnu/cris/arch.h27
-rw-r--r--sysdeps/linux-gnu/cris/plt.c34
-rw-r--r--sysdeps/linux-gnu/cris/ptrace.h21
-rw-r--r--sysdeps/linux-gnu/cris/regs.c58
-rw-r--r--sysdeps/linux-gnu/cris/signalent.h52
-rw-r--r--sysdeps/linux-gnu/cris/syscallent.h345
-rw-r--r--sysdeps/linux-gnu/cris/trace.c93
-rw-r--r--sysdeps/linux-gnu/events.c310
-rw-r--r--sysdeps/linux-gnu/events.h41
-rw-r--r--sysdeps/linux-gnu/i386/Makefile10
-rw-r--r--sysdeps/linux-gnu/i386/arch.h6
-rw-r--r--sysdeps/linux-gnu/i386/plt.c12
-rw-r--r--sysdeps/linux-gnu/i386/ptrace.h1
-rw-r--r--sysdeps/linux-gnu/i386/regs.c40
-rw-r--r--sysdeps/linux-gnu/i386/syscallent.h317
-rw-r--r--sysdeps/linux-gnu/i386/trace.c85
-rw-r--r--sysdeps/linux-gnu/ia64/Makefile10
-rw-r--r--sysdeps/linux-gnu/ia64/Makefile.am36
-rw-r--r--sysdeps/linux-gnu/ia64/Makefile.in533
-rw-r--r--sysdeps/linux-gnu/ia64/arch.h25
-rw-r--r--sysdeps/linux-gnu/ia64/breakpoint.c39
-rw-r--r--sysdeps/linux-gnu/ia64/fetch.c502
-rw-r--r--sysdeps/linux-gnu/ia64/plt.c93
-rw-r--r--sysdeps/linux-gnu/ia64/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/ia64/regs.c35
-rw-r--r--sysdeps/linux-gnu/ia64/signalent.h20
-rw-r--r--sysdeps/linux-gnu/ia64/syscallent.h20
-rw-r--r--sysdeps/linux-gnu/ia64/trace.c181
-rw-r--r--sysdeps/linux-gnu/m68k/Makefile10
-rw-r--r--sysdeps/linux-gnu/m68k/Makefile.am35
-rw-r--r--sysdeps/linux-gnu/m68k/Makefile.in530
-rw-r--r--sysdeps/linux-gnu/m68k/arch.h23
-rw-r--r--sysdeps/linux-gnu/m68k/fetch.c239
-rw-r--r--sysdeps/linux-gnu/m68k/plt.c24
-rw-r--r--sysdeps/linux-gnu/m68k/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/m68k/regs.c21
-rw-r--r--sysdeps/linux-gnu/m68k/signalent.h20
-rw-r--r--sysdeps/linux-gnu/m68k/syscallent.h116
-rw-r--r--sysdeps/linux-gnu/m68k/trace.c66
-rw-r--r--sysdeps/linux-gnu/mipsel/Doxyfile18
-rw-r--r--sysdeps/linux-gnu/mipsel/Makefile22
-rw-r--r--sysdeps/linux-gnu/mipsel/Makefile.am38
-rw-r--r--sysdeps/linux-gnu/mipsel/Makefile.in532
-rw-r--r--sysdeps/linux-gnu/mipsel/arch.h62
-rw-r--r--sysdeps/linux-gnu/mipsel/mipsel.h24
-rw-r--r--sysdeps/linux-gnu/mipsel/plt.c363
-rw-r--r--sysdeps/linux-gnu/mipsel/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/mipsel/regs.c23
-rw-r--r--sysdeps/linux-gnu/mipsel/signalent.h84
-rw-r--r--sysdeps/linux-gnu/mipsel/syscallent.h609
-rw-r--r--sysdeps/linux-gnu/mipsel/trace.c276
-rwxr-xr-xsysdeps/linux-gnu/mksignalent17
-rwxr-xr-xsysdeps/linux-gnu/mksyscallent18
-rw-r--r--sysdeps/linux-gnu/mksyscallent_s39018
-rw-r--r--sysdeps/linux-gnu/os.h25
-rw-r--r--sysdeps/linux-gnu/ppc/Makefile10
-rw-r--r--sysdeps/linux-gnu/ppc/Makefile.am36
-rw-r--r--sysdeps/linux-gnu/ppc/Makefile.in531
-rw-r--r--sysdeps/linux-gnu/ppc/arch.h100
-rw-r--r--sysdeps/linux-gnu/ppc/fetch.c436
-rw-r--r--sysdeps/linux-gnu/ppc/insn.h45
-rw-r--r--sysdeps/linux-gnu/ppc/plt.c1046
-rw-r--r--sysdeps/linux-gnu/ppc/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/ppc/regs.c31
-rw-r--r--sysdeps/linux-gnu/ppc/signalent.h20
-rw-r--r--sysdeps/linux-gnu/ppc/syscallent.h108
-rw-r--r--sysdeps/linux-gnu/ppc/trace.c275
-rw-r--r--sysdeps/linux-gnu/proc.c704
-rw-r--r--sysdeps/linux-gnu/s390/Makefile13
-rw-r--r--sysdeps/linux-gnu/s390/Makefile.am39
-rw-r--r--sysdeps/linux-gnu/s390/Makefile.in534
-rw-r--r--sysdeps/linux-gnu/s390/arch.h35
-rw-r--r--sysdeps/linux-gnu/s390/fetch.c289
-rw-r--r--sysdeps/linux-gnu/s390/plt.c22
-rw-r--r--sysdeps/linux-gnu/s390/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/s390/regs.c25
-rw-r--r--sysdeps/linux-gnu/s390/signalent.h20
-rw-r--r--sysdeps/linux-gnu/s390/signalent1.h20
-rw-r--r--sysdeps/linux-gnu/s390/syscallent.h20
-rw-r--r--sysdeps/linux-gnu/s390/syscallent1.h20
-rw-r--r--sysdeps/linux-gnu/s390/syscalls31.h21
-rw-r--r--sysdeps/linux-gnu/s390/syscalls64.h21
-rw-r--r--sysdeps/linux-gnu/s390/trace.c143
-rw-r--r--sysdeps/linux-gnu/signalent1.h1
-rw-r--r--sysdeps/linux-gnu/sparc/Makefile9
-rw-r--r--sysdeps/linux-gnu/sparc/Makefile.am34
-rw-r--r--sysdeps/linux-gnu/sparc/Makefile.in528
-rw-r--r--sysdeps/linux-gnu/sparc/arch.h21
-rw-r--r--sysdeps/linux-gnu/sparc/plt.c21
-rw-r--r--sysdeps/linux-gnu/sparc/ptrace.h20
-rw-r--r--sysdeps/linux-gnu/sparc/regs.c22
-rw-r--r--sysdeps/linux-gnu/sparc/signalent.h20
-rw-r--r--sysdeps/linux-gnu/sparc/syscallent.h20
-rw-r--r--sysdeps/linux-gnu/sparc/trace.c36
-rw-r--r--sysdeps/linux-gnu/syscallent1.h1
-rw-r--r--sysdeps/linux-gnu/trace-defs.h92
-rw-r--r--sysdeps/linux-gnu/trace.c1235
-rw-r--r--sysdeps/linux-gnu/trace.h121
-rw-r--r--sysdeps/linux-gnu/x86/Makefile.am37
-rw-r--r--sysdeps/linux-gnu/x86/Makefile.in532
-rw-r--r--sysdeps/linux-gnu/x86/arch.h36
-rw-r--r--sysdeps/linux-gnu/x86/fetch.c849
-rw-r--r--sysdeps/linux-gnu/x86/plt.c34
-rw-r--r--sysdeps/linux-gnu/x86/ptrace.h21
-rw-r--r--sysdeps/linux-gnu/x86/regs.c116
-rw-r--r--sysdeps/linux-gnu/x86/signalent.h (renamed from sysdeps/linux-gnu/x86_64/signalent.h)20
-rw-r--r--sysdeps/linux-gnu/x86/signalent1.h (renamed from sysdeps/linux-gnu/i386/signalent.h)20
-rw-r--r--sysdeps/linux-gnu/x86/syscallent.h370
-rw-r--r--sysdeps/linux-gnu/x86/syscallent1.h333
-rw-r--r--sysdeps/linux-gnu/x86/trace.c191
-rw-r--r--sysdeps/linux-gnu/x86_64/Makefile9
-rw-r--r--sysdeps/linux-gnu/x86_64/arch.h12
-rw-r--r--sysdeps/linux-gnu/x86_64/ffcheck.c0
-rw-r--r--sysdeps/linux-gnu/x86_64/plt.c12
-rw-r--r--sysdeps/linux-gnu/x86_64/ptrace.h1
-rw-r--r--sysdeps/linux-gnu/x86_64/regs.c54
-rw-r--r--sysdeps/linux-gnu/x86_64/signalent1.h1
-rw-r--r--sysdeps/linux-gnu/x86_64/syscallent.h256
-rw-r--r--sysdeps/linux-gnu/x86_64/syscallent1.h1
-rw-r--r--sysdeps/linux-gnu/x86_64/trace.c144
-rw-r--r--sysdeps/sysdep.h66
154 files changed, 17748 insertions, 2166 deletions
diff --git a/sysdeps/Makefile.am b/sysdeps/Makefile.am
new file mode 100644
index 0000000..36f93c1
--- /dev/null
+++ b/sysdeps/Makefile.am
@@ -0,0 +1,29 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+DIST_SUBDIRS = \
+ linux-gnu
+
+SUBDIRS = \
+ $(HOST_OS)
+
+noinst_HEADERS = \
+ sysdep.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/Makefile.in b/sysdeps/Makefile.in
new file mode 100644
index 0000000..d072917
--- /dev/null
+++ b/sysdeps/Makefile.in
@@ -0,0 +1,602 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps
+DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+SOURCES =
+DIST_SOURCES =
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+HEADERS = $(noinst_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+DIST_SUBDIRS = \
+ linux-gnu
+
+SUBDIRS = \
+ $(HOST_OS)
+
+noinst_HEADERS = \
+ sysdep.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-recursive
+
+.SUFFIXES:
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -f Makefile
+distclean-am: clean-am distclean-generic distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-generic mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ ctags ctags-recursive distclean distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs installdirs-am maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/README b/sysdeps/README
index ce033ef..db51c9e 100644
--- a/sysdeps/README
+++ b/sysdeps/README
@@ -7,26 +7,5 @@ first target, and must remove "sysdep.o" in this dir.
Files "sysdep.h", "signalent.h" and "syscallent.h" must be present
inside the directory after invoking the first target of the Makefile.
------------
-"sysdep.o" must export the following functions:
-
-Event * next_event(void);
-void continue_after_breakpoint(Process * proc, Breakpoint * sbp, int delete_it);
-void continue_after_signal(pid_t pid, int signum);
-void continue_enabling_breakpoint(pid_t pid, Breakpoint * sbp);
-void continue_process(pid_t pid);
-void enable_breakpoint(pid_t pid, Breakpoint * sbp);
-void disable_breakpoint(pid_t pid, Breakpoint * sbp);
-int fork_p(int sysnum);
-int exec_p(int sysnum);
-int syscall_p(Process * proc, int status, int * sysnum);
-void * get_instruction_pointer(pid_t pid);
-void * get_stack_pointer(pid_t pid);
-void * get_return_addr(pid_t pid, void * stack_pointer);
-long gimme_arg(enum tof type, Process * proc, arg_type_info*);
-int umovestr(Process * proc, void * addr, int len, void * laddr);
-int umovelong(Process * proc, void * addr, long * result);
-char * pid2name(pid_t pid);
-void trace_me(void);
-int trace_pid(pid_t pid);
-void untrace_pid(pid_t pid);
+See the file "backend.h" for description of backend interfaces, which
+have to be provided by "sysdep.o".
diff --git a/sysdeps/linux-gnu/Makefile b/sysdeps/linux-gnu/Makefile
deleted file mode 100644
index eb1ec60..0000000
--- a/sysdeps/linux-gnu/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-ARCH := $(shell uname -m | sed \
- -e s/i.86/i386/ \
- -e s/sun4u/sparc64/ \
- -e s/sparc64/sparc/ \
- -e s/arm.*/arm/ \
- -e s/sa110/arm/ \
- -e s/ppc64/ppc/ \
- -e s/s390x/s390/ \
- )
-
-CPPFLAGS += -I$(TOPDIR)/sysdeps/linux-gnu/$(ARCH)
-
-OBJ = events.o trace.o proc.o breakpoint.o
-
-all: sysdep.h signalent.h syscallent.h arch_syscallent.h signalent1.h syscallent1.h ../sysdep.o
-
-sysdep.h: $(ARCH)/arch.h
- cat $(ARCH)/arch.h > sysdep.h
-
-signalent.h:
- cp $(ARCH)/signalent.h signalent.h
-signalent1.h:
- if [ -f $(ARCH)/signalent1.h ]; then \
- cp $(ARCH)/signalent1.h signalent1.h; \
- else \
- > signalent1.h; \
- fi
-
-syscallent.h:
- cp $(ARCH)/syscallent.h syscallent.h
-
-syscallent1.h:
- if [ -f $(ARCH)/syscallent1.h ]; then \
- cp $(ARCH)/syscallent1.h syscallent1.h; \
- else \
- > syscallent1.h; \
- fi
-
-arch_syscallent.h:
- if [ -f $(ARCH)/arch_syscallent.h ]; then \
- cp $(ARCH)/arch_syscallent.h arch_syscallent.h; \
- else \
- > arch_syscallent.h; \
- fi
-
-../sysdep.o: os.o $(ARCH)/arch.o
- $(CC) -nostdlib -r -o ../sysdep.o os.o $(ARCH)/arch.o
-
-os.o: $(OBJ)
- $(CC) -nostdlib -r -o os.o $(OBJ)
-
-$(ARCH)/arch.o: dummy
- $(MAKE) -C $(ARCH)
-
-clean:
- $(MAKE) -C $(ARCH) clean
- rm -f $(OBJ) sysdep.h signalent.h signalent1.h syscallent.h arch_syscallent.h
- rm -f syscallent1.h os.o sysdep.o ../sysdep.o
-
-dummy:
diff --git a/sysdeps/linux-gnu/Makefile.am b/sysdeps/linux-gnu/Makefile.am
new file mode 100644
index 0000000..bfa67d6
--- /dev/null
+++ b/sysdeps/linux-gnu/Makefile.am
@@ -0,0 +1,46 @@
+# This file is part of ltrace.
+# Copyright (C) 2010,2012 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+DIST_SUBDIRS = alpha arm cris ia64 m68k mipsel ppc s390 sparc x86
+
+SUBDIRS = \
+ $(HOST_CPU)
+
+noinst_LTLIBRARIES = \
+ ../libos.la
+
+___libos_la_SOURCES = \
+ events.c \
+ trace.c \
+ proc.c \
+ breakpoint.c
+
+___libos_la_LIBADD = \
+ libcpu.la
+
+noinst_HEADERS = arch_syscallent.h signalent1.h syscallent1.h trace.h \
+ trace-defs.h events.h os.h
+
+EXTRA_DIST = \
+ arch_mksyscallent \
+ mksignalent \
+ mksyscallent \
+ mksyscallent_s390
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/Makefile.in b/sysdeps/linux-gnu/Makefile.in
new file mode 100644
index 0000000..e00136b
--- /dev/null
+++ b/sysdeps/linux-gnu/Makefile.in
@@ -0,0 +1,692 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010,2012 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu
+DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libos_la_DEPENDENCIES = libcpu.la
+am____libos_la_OBJECTS = events.lo trace.lo proc.lo breakpoint.lo
+___libos_la_OBJECTS = $(am____libos_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libos_la_SOURCES)
+DIST_SOURCES = $(___libos_la_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-dvi-recursive install-exec-recursive \
+ install-html-recursive install-info-recursive \
+ install-pdf-recursive install-ps-recursive install-recursive \
+ installcheck-recursive installdirs-recursive pdf-recursive \
+ ps-recursive uninstall-recursive
+HEADERS = $(noinst_HEADERS)
+RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
+ distclean-recursive maintainer-clean-recursive
+AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
+ $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
+ distdir
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+am__relativize = \
+ dir0=`pwd`; \
+ sed_first='s,^\([^/]*\)/.*$$,\1,'; \
+ sed_rest='s,^[^/]*/*,,'; \
+ sed_last='s,^.*/\([^/]*\)$$,\1,'; \
+ sed_butlast='s,/*[^/]*$$,,'; \
+ while test -n "$$dir1"; do \
+ first=`echo "$$dir1" | sed -e "$$sed_first"`; \
+ if test "$$first" != "."; then \
+ if test "$$first" = ".."; then \
+ dir2=`echo "$$dir0" | sed -e "$$sed_last"`/"$$dir2"; \
+ dir0=`echo "$$dir0" | sed -e "$$sed_butlast"`; \
+ else \
+ first2=`echo "$$dir2" | sed -e "$$sed_first"`; \
+ if test "$$first2" = "$$first"; then \
+ dir2=`echo "$$dir2" | sed -e "$$sed_rest"`; \
+ else \
+ dir2="../$$dir2"; \
+ fi; \
+ dir0="$$dir0"/"$$first"; \
+ fi; \
+ fi; \
+ dir1=`echo "$$dir1" | sed -e "$$sed_rest"`; \
+ done; \
+ reldir="$$dir2"
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+DIST_SUBDIRS = alpha arm cris ia64 m68k mipsel ppc s390 sparc x86
+SUBDIRS = \
+ $(HOST_CPU)
+
+noinst_LTLIBRARIES = \
+ ../libos.la
+
+___libos_la_SOURCES = \
+ events.c \
+ trace.c \
+ proc.c \
+ breakpoint.c
+
+___libos_la_LIBADD = \
+ libcpu.la
+
+noinst_HEADERS = arch_syscallent.h signalent1.h syscallent1.h trace.h \
+ trace-defs.h events.h os.h
+
+EXTRA_DIST = \
+ arch_mksyscallent \
+ mksignalent \
+ mksyscallent \
+ mksyscallent_s390
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libos.la: $(___libos_la_OBJECTS) $(___libos_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libos_la_OBJECTS) $(___libos_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/breakpoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/events.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+$(RECURSIVE_CLEAN_TARGETS):
+ @fail= failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || ($(am__cd) $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ set "$$@" "$$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(MKDIR_P) "$(distdir)/$$subdir" \
+ || exit 1; \
+ fi; \
+ done
+ @list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ dir1=$$subdir; dir2="$(distdir)/$$subdir"; \
+ $(am__relativize); \
+ new_distdir=$$reldir; \
+ dir1=$$subdir; dir2="$(top_distdir)"; \
+ $(am__relativize); \
+ new_top_distdir=$$reldir; \
+ echo " (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) top_distdir="$$new_top_distdir" distdir="$$new_distdir" \\"; \
+ echo " am__remove_distdir=: am__skip_length_check=: am__skip_mode_fix=: distdir)"; \
+ ($(am__cd) $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$new_top_distdir" \
+ distdir="$$new_distdir" \
+ am__remove_distdir=: \
+ am__skip_length_check=: \
+ am__skip_mode_fix=: \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-recursive
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs: installdirs-recursive
+installdirs-am:
+install: install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+html-am:
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-recursive
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-recursive
+
+install-html-am:
+
+install-info: install-info-recursive
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-recursive
+
+install-pdf-am:
+
+install-ps: install-ps-recursive
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) ctags-recursive \
+ install-am install-strip tags-recursive
+
+.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
+ all all-am check check-am clean clean-generic clean-libtool \
+ clean-noinstLTLIBRARIES ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ installdirs-am maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-recursive \
+ uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/alpha/Makefile b/sysdeps/linux-gnu/alpha/Makefile
deleted file mode 100644
index 60d7531..0000000
--- a/sysdeps/linux-gnu/alpha/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/alpha/Makefile.am b/sysdeps/linux-gnu/alpha/Makefile.am
new file mode 100644
index 0000000..5c6ecc2
--- /dev/null
+++ b/sysdeps/linux-gnu/alpha/Makefile.am
@@ -0,0 +1,34 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/alpha/Makefile.in b/sysdeps/linux-gnu/alpha/Makefile.in
new file mode 100644
index 0000000..99a5886
--- /dev/null
+++ b/sysdeps/linux-gnu/alpha/Makefile.in
@@ -0,0 +1,528 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/alpha
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/alpha/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/alpha/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/alpha/arch.h b/sysdeps/linux-gnu/alpha/arch.h
index 1107b5f..0696621 100644
--- a/sysdeps/linux-gnu/alpha/arch.h
+++ b/sysdeps/linux-gnu/alpha/arch.h
@@ -1,6 +1,27 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#define BREAKPOINT_VALUE { 0x80, 0x00, 0x00, 0x00 }
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 4
+#define ARCH_ENDIAN_LITTLE
#define LT_ELFCLASS ELFCLASS64
#define LT_ELF_MACHINE EM_ALPHA
diff --git a/sysdeps/linux-gnu/alpha/plt.c b/sysdeps/linux-gnu/alpha/plt.c
index 83337b2..c7ce9fe 100644
--- a/sysdeps/linux-gnu/alpha/plt.c
+++ b/sysdeps/linux-gnu/alpha/plt.c
@@ -1,4 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
+#include "proc.h"
#include "common.h"
GElf_Addr
diff --git a/sysdeps/linux-gnu/alpha/ptrace.h b/sysdeps/linux-gnu/alpha/ptrace.h
index c3cbcb6..ad7e0d6 100644
--- a/sysdeps/linux-gnu/alpha/ptrace.h
+++ b/sysdeps/linux-gnu/alpha/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/alpha/regs.c b/sysdeps/linux-gnu/alpha/regs.c
index 9554e48..0b46afd 100644
--- a/sysdeps/linux-gnu/alpha/regs.c
+++ b/sysdeps/linux-gnu/alpha/regs.c
@@ -1,9 +1,30 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
diff --git a/sysdeps/linux-gnu/alpha/signalent.h b/sysdeps/linux-gnu/alpha/signalent.h
index c2a6170..e9588fa 100644
--- a/sysdeps/linux-gnu/alpha/signalent.h
+++ b/sysdeps/linux-gnu/alpha/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/alpha/syscallent.h b/sysdeps/linux-gnu/alpha/syscallent.h
index 7cacc8c..9a24315 100644
--- a/sysdeps/linux-gnu/alpha/syscallent.h
+++ b/sysdeps/linux-gnu/alpha/syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"osf_syscall", /* 0, not implemented */
"exit", /* 1 */
"fork", /* 2 */
diff --git a/sysdeps/linux-gnu/alpha/trace.c b/sysdeps/linux-gnu/alpha/trace.c
index e4d4063..a7c5e59 100644
--- a/sysdeps/linux-gnu/alpha/trace.c
+++ b/sysdeps/linux-gnu/alpha/trace.c
@@ -1,3 +1,24 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
@@ -6,6 +27,7 @@
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#include "debug.h"
@@ -47,7 +69,8 @@ syscall_p(Process *proc, int status, int *sysnum) {
}
long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
+gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info)
+{
if (arg_num == -1) { /* return value */
return ptrace(PTRACE_PEEKUSER, proc->pid, 0 /* REG_R0 */ , 0);
}
@@ -69,7 +92,3 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
}
return 0;
}
-
-void
-save_register_args(enum tof type, Process *proc) {
-}
diff --git a/sysdeps/linux-gnu/arch_mksyscallent b/sysdeps/linux-gnu/arch_mksyscallent
index 853d62d..ce79e26 100644
--- a/sysdeps/linux-gnu/arch_mksyscallent
+++ b/sysdeps/linux-gnu/arch_mksyscallent
@@ -1,4 +1,21 @@
#!/usr/bin/awk -f
+# This file is part of ltrace.
+# Copyright (C) 2008 Juan Cespedes
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
# hack expression to generate arch_syscallent.h from <asm/unistd.h>
# It reads from stdin and writes to stdout
diff --git a/sysdeps/linux-gnu/arch_syscallent.h b/sysdeps/linux-gnu/arch_syscallent.h
new file mode 100644
index 0000000..74d8e19
--- /dev/null
+++ b/sysdeps/linux-gnu/arch_syscallent.h
@@ -0,0 +1 @@
+/* This file is intentionally left blank */
diff --git a/sysdeps/linux-gnu/arm/Makefile b/sysdeps/linux-gnu/arm/Makefile
deleted file mode 100644
index f55ba48..0000000
--- a/sysdeps/linux-gnu/arm/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o breakpoint.o
-
-all: arch.o
-
-arch.o: $(OBJ) arch.h
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/arm/Makefile.am b/sysdeps/linux-gnu/arm/Makefile.am
new file mode 100644
index 0000000..385424c
--- /dev/null
+++ b/sysdeps/linux-gnu/arm/Makefile.am
@@ -0,0 +1,36 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ breakpoint.c \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ arch_syscallent.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/arm/Makefile.in b/sysdeps/linux-gnu/arm/Makefile.in
new file mode 100644
index 0000000..ad6475d
--- /dev/null
+++ b/sysdeps/linux-gnu/arm/Makefile.in
@@ -0,0 +1,531 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/arm
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = breakpoint.lo plt.lo regs.lo trace.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ breakpoint.c \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ arch_syscallent.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/arm/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/arm/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/breakpoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/arm/arch.h b/sysdeps/linux-gnu/arm/arch.h
index 8f2dfb3..291443a 100644
--- a/sysdeps/linux-gnu/arm/arch.h
+++ b/sysdeps/linux-gnu/arm/arch.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 1998,2004,2008 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#define ARCH_HAVE_ENABLE_BREAKPOINT 1
#define ARCH_HAVE_DISABLE_BREAKPOINT 1
@@ -6,6 +26,12 @@
#define THUMB_BREAKPOINT_VALUE { 0x01, 0xde }
#define THUMB_BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_LITTLE
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_ARM
+
+#define ARCH_HAVE_BREAKPOINT_DATA
+struct arch_breakpoint_data {
+ int thumb_mode;
+};
diff --git a/sysdeps/linux-gnu/arm/arch_syscallent.h b/sysdeps/linux-gnu/arm/arch_syscallent.h
index ce1e844..f5bb295 100644
--- a/sysdeps/linux-gnu/arm/arch_syscallent.h
+++ b/sysdeps/linux-gnu/arm/arch_syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2008 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"0", /* 0 */
"breakpoint", /* 1 */
"cacheflush", /* 2 */
diff --git a/sysdeps/linux-gnu/arm/breakpoint.c b/sysdeps/linux-gnu/arm/breakpoint.c
index 4c20260..5748401 100644
--- a/sysdeps/linux-gnu/arm/breakpoint.c
+++ b/sysdeps/linux-gnu/arm/breakpoint.c
@@ -23,14 +23,16 @@
*/
#include <sys/ptrace.h>
+#include <sys/types.h>
+
#include "config.h"
-#include "arch.h"
-#include "options.h"
-#include "output.h"
+#include "breakpoint.h"
#include "debug.h"
+#include "proc.h"
void
-arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) {
+arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
unsigned int i, j;
const unsigned char break_insn[] = BREAKPOINT_VALUE;
const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
@@ -38,40 +40,79 @@ arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) {
debug(1, "arch_enable_breakpoint(%d,%p)", pid, sbp->addr);
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
- long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
- unsigned char *bytes = (unsigned char *)&a;
+ union _ { long l; unsigned char b[SIZEOF_LONG]; };
+ union _ orig, current;
+ unsigned char *bytes = current.b;
+ for (j = 0; j < sizeof(long); j++) {
+ orig.b[j] = sbp->orig_value[i * sizeof(long) + j];
+ }
+ current.l = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
- debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d",
+ current.l, orig.l, sbp->arch.thumb_mode);
for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
sbp->orig_value[i * sizeof(long) + j] = bytes[j];
- if (!sbp->thumb_mode) {
+ if (!sbp->arch.thumb_mode) {
bytes[j] = break_insn[i * sizeof(long) + j];
}
else if (j < THUMB_BREAKPOINT_LENGTH) {
bytes[j] = thumb_break_insn[i * sizeof(long) + j];
}
}
- ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long),
+ (void *)current.l);
}
}
void
-arch_disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
+arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
+{
unsigned int i, j;
- const unsigned char break_insn[] = BREAKPOINT_VALUE;
- const unsigned char thumb_break_insn[] = THUMB_BREAKPOINT_VALUE;
debug(1, "arch_disable_breakpoint(%d,%p)", pid, sbp->addr);
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
- long a = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
- unsigned char *bytes = (unsigned char *)&a;
+ union _ { long l; unsigned char b[SIZEOF_LONG]; };
+ union _ orig, current;
+ unsigned char *bytes = current.b;
+ for (j = 0; j < sizeof(long); j++) {
+ orig.b[j] = sbp->orig_value[i * sizeof(long) + j];
+ }
+ current.l = ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long), 0);
- debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d", a, *(long *)&sbp->orig_value, sbp->thumb_mode);
+ debug(2, "current = 0x%lx, orig_value = 0x%lx, thumb_mode = %d",
+ current.l, orig.l, sbp->arch.thumb_mode);
for (j = 0; j < sizeof(long) && i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
bytes[j] = sbp->orig_value[i * sizeof(long) + j];
}
- ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long),
+ (void *)current.l);
}
}
+
+int
+arch_breakpoint_init(struct Process *proc, struct breakpoint *sbp)
+{
+ /* XXX That uintptr_t cast is there temporarily until
+ * arch_addr_t becomes integral type. */
+ int thumb_mode = ((uintptr_t)sbp->addr) & 1;
+ if (thumb_mode)
+ sbp->addr = (void *)((uintptr_t)sbp->addr & ~1);
+ sbp->arch.thumb_mode = thumb_mode | proc->thumb_mode;
+ /* XXX This doesn't seem like it belongs here. */
+ proc->thumb_mode = 0;
+ return 0;
+}
+
+void
+arch_breakpoint_destroy(struct breakpoint *sbp)
+{
+}
+
+int
+arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
+{
+ retp->arch.thumb_mode = sbp->arch.thumb_mode;
+ return 0;
+}
diff --git a/sysdeps/linux-gnu/arm/plt.c b/sysdeps/linux-gnu/arm/plt.c
index bd92a63..1b97705 100644
--- a/sysdeps/linux-gnu/arm/plt.c
+++ b/sysdeps/linux-gnu/arm/plt.c
@@ -1,9 +1,45 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Zach Welch, CodeSourcery
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
-#include "common.h"
+
+#include "proc.h"
+#include "library.h"
+#include "ltrace-elf.h"
+
+static int
+arch_plt_entry_has_stub(struct ltelf *lte, size_t off) {
+ uint16_t op = *(uint16_t *)((char *)lte->relplt->d_buf + off);
+ return op == 0x4778;
+}
GElf_Addr
arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- return lte->plt_addr + 20 + ndx * 12;
+ size_t start = lte->relplt->d_size + 12;
+ size_t off = start + 20, i;
+ for (i = 0; i < ndx; i++)
+ off += arch_plt_entry_has_stub(lte, off) ? 16 : 12;
+ if (arch_plt_entry_has_stub(lte, off))
+ off += 4;
+ return lte->plt_addr + off - start;
}
void *
diff --git a/sysdeps/linux-gnu/arm/ptrace.h b/sysdeps/linux-gnu/arm/ptrace.h
index 52215bc..41106d8 100644
--- a/sysdeps/linux-gnu/arm/ptrace.h
+++ b/sysdeps/linux-gnu/arm/ptrace.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
#include <asm/ptrace.h>
diff --git a/sysdeps/linux-gnu/arm/regs.c b/sysdeps/linux-gnu/arm/regs.c
index 2488b0a..484de7f 100644
--- a/sysdeps/linux-gnu/arm/regs.c
+++ b/sysdeps/linux-gnu/arm/regs.c
@@ -1,9 +1,31 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
@@ -14,9 +36,9 @@
# define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
-#define off_pc 60
-#define off_lr 56
-#define off_sp 52
+#define off_pc ((void *)60)
+#define off_lr ((void *)56)
+#define off_sp ((void *)52)
void *
get_instruction_pointer(Process *proc) {
@@ -39,13 +61,20 @@ void *
get_return_addr(Process *proc, void *stack_pointer) {
long addr = ptrace(PTRACE_PEEKUSER, proc->pid, off_lr, 0);
+ /* Remember & unset the thumb mode bit. XXX This is really a
+ * bit of a hack, as we assume that the following
+ * insert_breakpoint call will be related to this address.
+ * This interface should really be get_return_breakpoint, or
+ * maybe install_return_breakpoint. */
proc->thumb_mode = addr & 1;
if (proc->thumb_mode)
addr &= ~1;
+
return (void *)addr;
}
void
set_return_addr(Process *proc, void *addr) {
- ptrace(PTRACE_POKEUSER, proc->pid, off_lr, addr);
+ long iaddr = (int)addr | proc->thumb_mode;
+ ptrace(PTRACE_POKEUSER, proc->pid, off_lr, (void *)iaddr);
}
diff --git a/sysdeps/linux-gnu/arm/signalent.h b/sysdeps/linux-gnu/arm/signalent.h
index 0afb004..4c28c9d 100644
--- a/sysdeps/linux-gnu/arm/signalent.h
+++ b/sysdeps/linux-gnu/arm/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/arm/syscallent.h b/sysdeps/linux-gnu/arm/syscallent.h
index 4113234..3b9bcfd 100644
--- a/sysdeps/linux-gnu/arm/syscallent.h
+++ b/sysdeps/linux-gnu/arm/syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"restart_syscall", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
diff --git a/sysdeps/linux-gnu/arm/trace.c b/sysdeps/linux-gnu/arm/trace.c
index 10f7cc4..c528cfb 100644
--- a/sysdeps/linux-gnu/arm/trace.c
+++ b/sysdeps/linux-gnu/arm/trace.c
@@ -1,3 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1998,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <string.h>
@@ -7,6 +29,7 @@
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#include "output.h"
#include "ptrace.h"
@@ -19,10 +42,10 @@
# define PTRACE_POKEUSER PTRACE_POKEUSR
#endif
-#define off_r0 0
-#define off_r7 28
-#define off_ip 48
-#define off_pc 60
+#define off_r0 ((void *)0)
+#define off_r7 ((void *)28)
+#define off_ip ((void *)48)
+#define off_pc ((void *)60)
void
get_arch_dep(Process *proc) {
@@ -44,12 +67,15 @@ syscall_p(Process *proc, int status, int *sysnum) {
if (WIFSTOPPED(status)
&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
/* get the user's pc (plus 8) */
- int pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
+ unsigned pc = ptrace(PTRACE_PEEKUSER, proc->pid, off_pc, 0);
+ pc = pc - 4;
/* fetch the SWI instruction */
- int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
+ unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid,
+ (void *)pc, 0);
int ip = ptrace(PTRACE_PEEKUSER, proc->pid, off_ip, 0);
- if (insn == 0xef000000 || insn == 0x0f000000) {
+ if (insn == 0xef000000 || insn == 0x0f000000
+ || (insn & 0xffff0000) == 0xdf000000) {
/* EABI syscall */
*sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, off_r7, 0);
} else if ((insn & 0xfff00000) == 0xef900000) {
@@ -61,8 +87,9 @@ syscall_p(Process *proc, int status, int *sysnum) {
* are coming from a signal handler, so the current
* PC does not point to the instruction just after the
* "swi" one. */
- output_line(proc, "unexpected instruction 0x%x at %p", insn, pc - 4);
- return -1;
+ output_line(proc, "unexpected instruction 0x%x at %p",
+ insn, pc);
+ return 0;
}
if ((*sysnum & 0xf0000) == 0xf0000) {
/* arch-specific syscall */
@@ -77,7 +104,8 @@ syscall_p(Process *proc, int status, int *sysnum) {
}
long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
+gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info)
+{
proc_archdep *a = (proc_archdep *) proc->arch_ptr;
if (arg_num == -1) { /* return value */
@@ -91,8 +119,8 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
return a->regs.uregs[arg_num];
if (a->valid && type == LT_TOF_FUNCTIONR)
return a->func_arg[arg_num];
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
- 0);
+ return ptrace(PTRACE_PEEKUSER, proc->pid,
+ (void *)(4 * arg_num), 0);
} else {
return ptrace(PTRACE_PEEKDATA, proc->pid,
proc->stack_pointer + 4 * (arg_num - 4),
@@ -104,8 +132,8 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
return a->regs.uregs[arg_num];
if (a->valid && type == LT_TOF_SYSCALLR)
return a->sysc_arg[arg_num];
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num,
- 0);
+ return ptrace(PTRACE_PEEKUSER, proc->pid,
+ (void *)(4 * arg_num), 0);
} else {
return ptrace(PTRACE_PEEKDATA, proc->pid,
proc->stack_pointer + 4 * (arg_num - 5),
@@ -118,14 +146,3 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
return 0;
}
-
-void
-save_register_args(enum tof type, Process *proc) {
- proc_archdep *a = (proc_archdep *) proc->arch_ptr;
- if (a->valid) {
- if (type == LT_TOF_FUNCTION)
- memcpy(a->func_arg, a->regs.uregs, sizeof(a->func_arg));
- else
- memcpy(a->sysc_arg, a->regs.uregs, sizeof(a->sysc_arg));
- }
-}
diff --git a/sysdeps/linux-gnu/breakpoint.c b/sysdeps/linux-gnu/breakpoint.c
index 5ca131a..fe336b1 100644
--- a/sysdeps/linux-gnu/breakpoint.c
+++ b/sysdeps/linux-gnu/breakpoint.c
@@ -1,39 +1,62 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2006 Ian Wienand
+ * Copyright (C) 2002,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/ptrace.h>
+#include <errno.h>
#include <string.h>
+#include <stdio.h>
#include "common.h"
-#include "arch.h"
-
-static unsigned char break_insn[] = BREAKPOINT_VALUE;
+#include "backend.h"
+#include "sysdep.h"
+#include "breakpoint.h"
+#include "proc.h"
+#include "library.h"
#ifdef ARCH_HAVE_ENABLE_BREAKPOINT
-extern void arch_enable_breakpoint(pid_t, Breakpoint *);
-void
-enable_breakpoint(pid_t pid, Breakpoint *sbp) {
- if (sbp->libsym) {
- debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
- } else {
- debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
- }
- arch_enable_breakpoint(pid, sbp);
-}
-#else
+extern void arch_enable_breakpoint(pid_t, struct breakpoint *);
+#else /* ARCH_HAVE_ENABLE_BREAKPOINT */
void
-enable_breakpoint(pid_t pid, Breakpoint *sbp) {
+arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
+ static unsigned char break_insn[] = BREAKPOINT_VALUE;
unsigned int i, j;
- if (sbp->libsym) {
- debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
- } else {
- debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
- }
+ debug(DEBUG_PROCESS,
+ "arch_enable_breakpoint: pid=%d, addr=%p, symbol=%s",
+ pid, sbp->addr, breakpoint_name(sbp));
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
- long a =
- ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
- 0);
+ long a = ptrace(PTRACE_PEEKTEXT, pid,
+ sbp->addr + i * sizeof(long), 0);
+ if (a == -1 && errno) {
+ fprintf(stderr, "enable_breakpoint"
+ " pid=%d, addr=%p, symbol=%s: %s\n",
+ pid, sbp->addr, breakpoint_name(sbp),
+ strerror(errno));
+ return;
+ }
for (j = 0;
j < sizeof(long)
&& i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
@@ -42,37 +65,48 @@ enable_breakpoint(pid_t pid, Breakpoint *sbp) {
sbp->orig_value[i * sizeof(long) + j] = bytes[j];
bytes[j] = break_insn[i * sizeof(long) + j];
}
- ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ a = ptrace(PTRACE_POKETEXT, pid,
+ sbp->addr + i * sizeof(long), a);
+ if (a == -1) {
+ fprintf(stderr, "enable_breakpoint"
+ " pid=%d, addr=%p, symbol=%s: %s\n",
+ pid, sbp->addr, breakpoint_name(sbp),
+ strerror(errno));
+ return;
+ }
}
}
#endif /* ARCH_HAVE_ENABLE_BREAKPOINT */
-#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
-extern void arch_disable_breakpoint(pid_t, const Breakpoint *sbp);
void
-disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
- if (sbp->libsym) {
- debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
- } else {
- debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
- }
- arch_disable_breakpoint(pid, sbp);
+enable_breakpoint(Process *proc, struct breakpoint *sbp)
+{
+ debug(DEBUG_PROCESS, "enable_breakpoint: pid=%d, addr=%p, symbol=%s",
+ proc->pid, sbp->addr, breakpoint_name(sbp));
+ arch_enable_breakpoint(proc->pid, sbp);
}
-#else
+
+#ifdef ARCH_HAVE_DISABLE_BREAKPOINT
+extern void arch_disable_breakpoint(pid_t, const struct breakpoint *sbp);
+#else /* ARCH_HAVE_DISABLE_BREAKPOINT */
void
-disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
+arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
+{
unsigned int i, j;
- if (sbp->libsym) {
- debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s", pid, sbp->addr, sbp->libsym->name);
- } else {
- debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p", pid, sbp->addr);
- }
+ debug(DEBUG_PROCESS,
+ "arch_disable_breakpoint: pid=%d, addr=%p, symbol=%s",
+ pid, sbp->addr, breakpoint_name(sbp));
for (i = 0; i < 1 + ((BREAKPOINT_LENGTH - 1) / sizeof(long)); i++) {
- long a =
- ptrace(PTRACE_PEEKTEXT, pid, sbp->addr + i * sizeof(long),
- 0);
+ long a = ptrace(PTRACE_PEEKTEXT, pid,
+ sbp->addr + i * sizeof(long), 0);
+ if (a == -1 && errno) {
+ fprintf(stderr,
+ "disable_breakpoint pid=%d, addr=%p: %s\n",
+ pid, sbp->addr, strerror(errno));
+ return;
+ }
for (j = 0;
j < sizeof(long)
&& i * sizeof(long) + j < BREAKPOINT_LENGTH; j++) {
@@ -80,7 +114,22 @@ disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
bytes[j] = sbp->orig_value[i * sizeof(long) + j];
}
- ptrace(PTRACE_POKETEXT, pid, sbp->addr + i * sizeof(long), a);
+ a = ptrace(PTRACE_POKETEXT, pid,
+ sbp->addr + i * sizeof(long), a);
+ if (a == -1 && errno) {
+ fprintf(stderr,
+ "disable_breakpoint pid=%d, addr=%p: %s\n",
+ pid, sbp->addr, strerror(errno));
+ return;
+ }
}
}
#endif /* ARCH_HAVE_DISABLE_BREAKPOINT */
+
+void
+disable_breakpoint(Process *proc, struct breakpoint *sbp)
+{
+ debug(DEBUG_PROCESS, "disable_breakpoint: pid=%d, addr=%p, symbol=%s",
+ proc->pid, sbp->addr, breakpoint_name(sbp));
+ arch_disable_breakpoint(proc->pid, sbp);
+}
diff --git a/sysdeps/linux-gnu/cris/Makefile.am b/sysdeps/linux-gnu/cris/Makefile.am
new file mode 100644
index 0000000..30cb0fd
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/Makefile.am
@@ -0,0 +1,34 @@
+# This file is part of ltrace.
+# Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/cris/Makefile.in b/sysdeps/linux-gnu/cris/Makefile.in
new file mode 100644
index 0000000..c978410
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/Makefile.in
@@ -0,0 +1,528 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/cris
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/cris/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/cris/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/cris/arch.h b/sysdeps/linux-gnu/cris/arch.h
new file mode 100644
index 0000000..099dc3f
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/arch.h
@@ -0,0 +1,27 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define BREAKPOINT_VALUE { 0x38, 0xe9 }
+#define BREAKPOINT_LENGTH 2
+#define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_LITTLE
+
+#define LT_ELFCLASS ELFCLASS32
+#define LT_ELF_MACHINE EM_CRIS
diff --git a/sysdeps/linux-gnu/cris/plt.c b/sysdeps/linux-gnu/cris/plt.c
new file mode 100644
index 0000000..427ae93
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/plt.c
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <gelf.h>
+#include "proc.h"
+#include "common.h"
+#include "library.h"
+
+GElf_Addr arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
+{
+ return lte->plt_addr + 0x20 + (ndx * 26);
+}
+
+void *sym2addr(Process *proc, struct library_symbol *sym)
+{
+ return sym->enter_addr;
+}
diff --git a/sysdeps/linux-gnu/cris/ptrace.h b/sysdeps/linux-gnu/cris/ptrace.h
new file mode 100644
index 0000000..8f04f16
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/ptrace.h
@@ -0,0 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/cris/regs.c b/sysdeps/linux-gnu/cris/regs.c
new file mode 100644
index 0000000..7028b9e
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/regs.c
@@ -0,0 +1,58 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+
+#include "proc.h"
+#include "common.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+void *get_instruction_pointer(Process *proc)
+{
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_PPC, 0);
+}
+
+void set_instruction_pointer(Process *proc, void *addr)
+{
+ ptrace(PTRACE_POKEUSER, proc->pid, 4 * PT_PPC, addr);
+}
+
+void *get_stack_pointer(Process *proc)
+{
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_USP, 0);
+}
+
+void *get_return_addr(Process *proc, void *stack_pointer)
+{
+ return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_SRP, 0);
+}
diff --git a/sysdeps/linux-gnu/cris/signalent.h b/sysdeps/linux-gnu/cris/signalent.h
new file mode 100644
index 0000000..71cedbe
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/signalent.h
@@ -0,0 +1,52 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "SIG_0", /* 0 */
+ "SIGHUP", /* 1 */
+ "SIGINT", /* 2 */
+ "SIGQUIT", /* 3 */
+ "SIGILL", /* 4 */
+ "SIGTRAP", /* 5 */
+ "SIGABRT", /* 6 */
+ "SIGBUS", /* 7 */
+ "SIGFPE", /* 8 */
+ "SIGKILL", /* 9 */
+ "SIGUSR1", /* 10 */
+ "SIGSEGV", /* 11 */
+ "SIGUSR2", /* 12 */
+ "SIGPIPE", /* 13 */
+ "SIGALRM", /* 14 */
+ "SIGTERM", /* 15 */
+ "SIGSTKFLT", /* 16 */
+ "SIGCHLD", /* 17 */
+ "SIGCONT", /* 18 */
+ "SIGSTOP", /* 19 */
+ "SIGTSTP", /* 20 */
+ "SIGTTIN", /* 21 */
+ "SIGTTOU", /* 22 */
+ "SIGURG", /* 23 */
+ "SIGXCPU", /* 24 */
+ "SIGXFSZ", /* 25 */
+ "SIGVTALRM", /* 26 */
+ "SIGPROF", /* 27 */
+ "SIGWINCH", /* 28 */
+ "SIGIO", /* 29 */
+ "SIGPWR", /* 30 */
+ "SIGSYS", /* 31 */
diff --git a/sysdeps/linux-gnu/cris/syscallent.h b/sysdeps/linux-gnu/cris/syscallent.h
new file mode 100644
index 0000000..7a7d1ca
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/syscallent.h
@@ -0,0 +1,345 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+"0", /* 0 */
+ "exit",
+"fork",
+"read",
+"write",
+"open",
+"close",
+"waitpid",
+"creat",
+"link",
+"unlink",
+"execve",
+"chdir",
+"time",
+"mknod",
+"chmod",
+"lchown",
+"break",
+"oldstat",
+"lseek",
+"getpid",
+"mount",
+"umount",
+"setuid",
+"getuid",
+"stime",
+"ptrace",
+"alarm",
+"oldfstat",
+"pause",
+"utime",
+"stty",
+"gtty",
+"access",
+"nice",
+"ftime",
+"sync",
+"kill",
+"rename",
+"mkdir",
+"rmdir",
+"dup",
+"pipe",
+"times",
+"prof",
+"brk",
+"setgid",
+"getgid",
+"signal",
+"geteuid",
+"getegid",
+"acct",
+"umount2",
+"lock",
+"ioctl",
+"fcntl",
+"mpx",
+"setpgid",
+"ulimit",
+"oldolduname",
+"umask",
+"chroot",
+"ustat",
+"dup2",
+"getppid",
+"getpgrp",
+"setsid",
+"sigaction",
+"sgetmask",
+"ssetmask",
+"setreuid",
+"setregid",
+"sigsuspend",
+"sigpending",
+"sethostname",
+"setrlimit",
+"getrlimit",
+"getrusage",
+"gettimeofday",
+"settimeofday",
+"getgroups",
+"setgroups",
+"select",
+"symlink",
+"oldlstat",
+"readlink",
+"uselib",
+"swapon",
+"reboot",
+"readdir",
+"mmap",
+"munmap",
+"truncate",
+"ftruncate",
+"fchmod",
+"fchown",
+"getpriority",
+"setpriority",
+"profil",
+"statfs",
+"fstatfs",
+"ioperm",
+"socketcall",
+"syslog",
+"setitimer",
+"getitimer",
+"stat",
+"lstat",
+"fstat",
+"olduname",
+"iopl",
+"vhangup",
+"idle",
+"vm86",
+"wait4",
+"swapoff",
+"sysinfo",
+"ipc",
+"fsync",
+"sigreturn",
+"clone",
+"setdomainname",
+"uname",
+"modify_ldt",
+"adjtimex",
+"mprotect",
+"sigprocmask",
+"create_module",
+"init_module",
+"delete_module",
+"get_kernel_syms",
+"quotactl",
+"getpgid",
+"fchdir",
+"bdflush",
+"sysfs",
+"personality",
+"afs_syscall",
+"setfsuid",
+"setfsgid",
+"_llseek",
+"getdents",
+"_newselect",
+"flock",
+"msync",
+"readv",
+"writev",
+"getsid",
+"fdatasync",
+"_sysctl",
+"mlock",
+"munlock",
+"mlockall",
+"munlockall",
+"sched_setparam",
+"sched_getparam",
+"sched_setscheduler",
+"sched_getscheduler",
+"sched_yield",
+"sched_get_priority_max",
+"sched_get_priority_min",
+"sched_rr_get_interval",
+"nanosleep",
+"mremap",
+"setresuid",
+"getresuid",
+"invalid",
+"query_module",
+"poll",
+"nfsservctl",
+"setresgid",
+"getresgid",
+"prctl",
+"rt_sigreturn",
+"rt_sigaction",
+"rt_sigprocmask",
+"rt_sigpending",
+"rt_sigtimedwait",
+"rt_sigqueueinfo",
+"rt_sigsuspend",
+"pread64",
+"pwrite64",
+"chown",
+"getcwd",
+"capget",
+"capset",
+"sigaltstack",
+"sendfile",
+"getpmsg",
+"putpmsg",
+"vfork",
+"ugetrlimit",
+"mmap2",
+"truncate64",
+"ftruncate64",
+"stat64",
+"lstat64",
+"fstat64",
+"lchown32",
+"getuid32",
+"getgid32",
+"geteuid32",
+"getegid32",
+"setreuid32",
+"setregid32",
+"getgroups32",
+"setgroups32",
+"fchown32",
+"setresuid32",
+"getresuid32",
+"setresgid32",
+"getresgid32",
+"chown32",
+"setuid32",
+"setgid32",
+"setfsuid32",
+"setfsgid32",
+"pivot_root",
+"mincore",
+"madvise",
+"getdents64",
+"fcntl64",
+"invalid",
+"invalid",
+"gettid",
+"readahead",
+"setxattr",
+"lsetxattr",
+"fsetxattr",
+"getxattr",
+"lgetxattr",
+"fgetxattr",
+"listxattr",
+"llistxattr",
+"flistxattr",
+"removexattr",
+"lremovexattr",
+"fremovexattr",
+"tkill",
+"sendfile64",
+"futex",
+"sched_setaffinity",
+"sched_getaffinity",
+"set_thread_area",
+"get_thread_area",
+"io_setup",
+"io_destroy",
+"io_getevents",
+"io_submit",
+"io_cancel",
+"fadvise64",
+"invalid",
+"exit_group",
+"lookup_dcookie",
+"epoll_create",
+"epoll_ctl",
+"epoll_wait",
+"remap_file_pages",
+"set_tid_address",
+"timer_create",
+"timer_settime",
+"timer_gettime",
+"timer_getoverrun",
+"timer_delete",
+"clock_settime",
+"clock_gettime",
+"clock_getres",
+"clock_nanosleep",
+"statfs64",
+"fstatfs64",
+"tgkill",
+"utimes",
+"fadvise64_64",
+"vserver",
+"mbind",
+"get_mempolicy",
+"set_mempolicy",
+"mq_open",
+"mq_unlink",
+"mq_timedsend",
+"mq_timedreceive",
+"mq_notify",
+"mq_getsetattr",
+"kexec_load",
+"waitid",
+"invalid",
+"add_key",
+"request_key",
+"keyctl",
+"ioprio_set",
+"ioprio_get",
+"inotify_init",
+"inotify_add_watch",
+"inotify_rm_watch",
+"migrate_pages",
+"openat",
+"mkdirat",
+"mknodat",
+"fchownat",
+"futimesat",
+"fstatat64",
+"unlinkat",
+"renameat",
+"linkat",
+"symlinkat",
+"readlinkat",
+"fchmodat",
+"faccessat",
+"pselect6",
+"ppoll",
+"unshare",
+"set_robust_list",
+"get_robust_list",
+"splice",
+"sync_file_range",
+"tee",
+"vmsplice",
+"move_pages",
+"getcpu",
+"epoll_pwait",
+"utimensat",
+"signalfd",
+"timerfd",
+"eventfd",
+"fallocate",
diff --git a/sysdeps/linux-gnu/cris/trace.c b/sysdeps/linux-gnu/cris/trace.c
new file mode 100644
index 0000000..98cb7d8
--- /dev/null
+++ b/sysdeps/linux-gnu/cris/trace.c
@@ -0,0 +1,93 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Edgar E. Iglesias
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/ptrace.h>
+#include <asm/ptrace.h>
+#include <elf.h>
+
+#include "proc.h"
+#include "common.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+void get_arch_dep(Process *proc)
+{
+}
+
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
+ */
+#define SYSCALL_INSN 0xe93d
+int syscall_p(Process *proc, int status, int *sysnum)
+{
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
+ long pc = (long)get_instruction_pointer(proc);
+ unsigned int insn =
+ (int)ptrace(PTRACE_PEEKTEXT, proc->pid, pc - sizeof(long),
+ 0);
+
+ if ((insn >> 16) == SYSCALL_INSN) {
+ *sysnum =
+ (int)ptrace(PTRACE_PEEKUSER, proc->pid,
+ sizeof(long) * PT_R9, 0);
+ if (proc->callstack_depth > 0
+ && proc->callstack[proc->callstack_depth -
+ 1].is_syscall) {
+ return 2;
+ }
+ return 1;
+ }
+ }
+ return 0;
+}
+
+long gimme_arg(enum tof type, Process *proc, int arg_num,
+ struct arg_type_info *info)
+{
+ int pid = proc->pid;
+
+ if (arg_num == -1) { /* return value */
+ return ptrace(PTRACE_PEEKUSER, pid, PT_R10 * 4, 0);
+ } else if (arg_num < 6) {
+ int pt_arg[6] =
+ {
+ PT_ORIG_R10, PT_R11, PT_R12, PT_R13, PT_MOF,
+ PT_SRP
+ };
+ return ptrace(PTRACE_PEEKUSER, pid, pt_arg[arg_num] * 4, 0);
+ } else {
+ return ptrace(PTRACE_PEEKDATA, pid,
+ proc->stack_pointer + 4 * (arg_num - 6), 0);
+ }
+ return 0;
+}
diff --git a/sysdeps/linux-gnu/events.c b/sysdeps/linux-gnu/events.c
index a1e2a14..077a656 100644
--- a/sysdeps/linux-gnu/events.c
+++ b/sysdeps/linux-gnu/events.c
@@ -1,31 +1,163 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2007,2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1998,2001,2004,2007,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#define _GNU_SOURCE 1
-#include <stdlib.h>
+#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <assert.h>
#include <errno.h>
#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <sys/ptrace.h>
+#include <unistd.h>
-#include "common.h"
+#include "backend.h"
+#include "breakpoint.h"
+#include "debug.h"
+#include "events.h"
+#include "proc.h"
+#include "linux-gnu/trace-defs.h"
static Event event;
+/* A queue of events that we missed while enabling the
+ * breakpoint in one of tasks. */
+static Event * delayed_events = NULL;
+static Event * end_delayed_events = NULL;
+
+static enum callback_status
+first (Process * proc, void * data)
+{
+ return CBS_STOP;
+}
+
+void
+enque_event(Event * event)
+{
+ debug(DEBUG_FUNCTION, "%d: queuing event %d for later",
+ event->proc->pid, event->type);
+ Event * ne = malloc(sizeof(*ne));
+ if (ne == NULL) {
+ fprintf(stderr, "event will be missed: %s\n", strerror(errno));
+ return;
+ }
+
+ *ne = *event;
+ ne->next = NULL;
+ if (end_delayed_events == NULL) {
+ assert(delayed_events == NULL);
+ end_delayed_events = delayed_events = ne;
+ }
+ else {
+ assert(delayed_events != NULL);
+ end_delayed_events = end_delayed_events->next = ne;
+ }
+}
+
Event *
-next_event(void) {
+each_qd_event(enum ecb_status (*pred)(Event *, void *), void * data)
+{
+ Event * prev = delayed_events;
+ Event * event;
+ for (event = prev; event != NULL; ) {
+ switch ((*pred)(event, data)) {
+ case ecb_cont:
+ prev = event;
+ event = event->next;
+ continue;
+
+ case ecb_deque:
+ debug(DEBUG_FUNCTION, "dequeuing event %d for %d",
+ event->type,
+ event->proc != NULL ? event->proc->pid : -1);
+ /*
+ printf("dequeuing event %d for %d\n", event->type,
+ event->proc != NULL ? event->proc->pid : -1) ;
+ */
+ if (end_delayed_events == event)
+ end_delayed_events = prev;
+ if (delayed_events == event)
+ delayed_events = event->next;
+ else
+ prev->next = event->next;
+ if (delayed_events == NULL)
+ end_delayed_events = NULL;
+ /* fall-through */
+
+ case ecb_yield:
+ return event;
+ }
+ }
+
+ return NULL;
+}
+
+static enum ecb_status
+event_process_not_reenabling(Event * event, void * data)
+{
+ if (event->proc == NULL
+ || event->proc->leader == NULL
+ || event->proc->leader->event_handler == NULL)
+ return ecb_deque;
+ else
+ return ecb_cont;
+}
+
+static Event *
+next_qd_event(void)
+{
+ return each_qd_event(&event_process_not_reenabling, NULL);
+}
+
+int linux_in_waitpid = 0;
+
+Event *
+next_event(void)
+{
pid_t pid;
int status;
int tmp;
int stop_signal;
debug(DEBUG_FUNCTION, "next_event()");
- if (!list_of_processes) {
+ Event * ev;
+ if ((ev = next_qd_event()) != NULL) {
+ event = *ev;
+ free(ev);
+ return &event;
+ }
+
+ if (!each_process(NULL, &first, NULL)) {
debug(DEBUG_EVENT, "event: No more traced programs: exiting");
exit(0);
}
+
+ linux_in_waitpid = 1;
pid = waitpid(-1, &status, __WALL);
+ linux_in_waitpid = 0;
+
if (pid == -1) {
if (errno == ECHILD) {
debug(DEBUG_EVENT, "event: No more traced programs: exiting");
@@ -40,26 +172,84 @@ next_event(void) {
}
event.proc = pid2proc(pid);
if (!event.proc || event.proc->state == STATE_BEING_CREATED) {
+ /* Work around (presumably) a bug on some kernels,
+ * where we are seeing a waitpid event even though the
+ * process is still reported to be running. Wait for
+ * the tracing stop to propagate. But don't get stuck
+ * here forever.
+ *
+ * We need the process in T, because there's a lot of
+ * ptracing going on all over the place, and these
+ * calls fail when the process is not in T.
+ *
+ * N.B. This was observed on RHEL 5 Itanium, but I'm
+ * turning this on globally, to save some poor soul
+ * down the road (which could well be me a year from
+ * now) the pain of figuring this out all over again.
+ * Petr Machata 2011-11-22. */
+ int i = 0;
+ for (; i < 100 && process_status(pid) != ps_tracing_stop; ++i) {
+ debug(2, "waiting for %d to stop", pid);
+ usleep(10000);
+ }
event.type = EVENT_NEW;
event.e_un.newpid = pid;
debug(DEBUG_EVENT, "event: NEW: pid=%d", pid);
return &event;
}
get_arch_dep(event.proc);
- event.proc->instruction_pointer = NULL;
debug(3, "event from pid %u", pid);
- if (event.proc->breakpoints_enabled == -1) {
- enable_all_breakpoints(event.proc);
- event.type = EVENT_NONE;
- trace_set_options(event.proc, event.proc->pid);
- continue_process(event.proc->pid);
- debug(DEBUG_EVENT, "event: NONE: pid=%d (enabling breakpoints)", pid);
+ Process *leader = event.proc->leader;
+
+ /* The process should be stopped after the waitpid call. But
+ * when the whole thread group is terminated, we see
+ * individual tasks spontaneously transitioning from 't' to
+ * 'R' and 'Z'. Calls to ptrace fail and /proc/pid/status may
+ * not even be available anymore, so we can't check in
+ * advance. So we just drop the error checking around ptrace
+ * calls. We check for termination ex post when it fails,
+ * suppress the event, and let the event loop collect the
+ * termination in the next iteration. */
+#define CHECK_PROCESS_TERMINATED \
+ do { \
+ int errno_save = errno; \
+ switch (process_stopped(pid)) \
+ case 0: \
+ case -1: { \
+ debug(DEBUG_EVENT, \
+ "process not stopped, is it terminating?"); \
+ event.type = EVENT_NONE; \
+ continue_process(event.proc->pid); \
+ return &event; \
+ } \
+ errno = errno_save; \
+ } while (0)
+
+ event.proc->instruction_pointer = (void *)(uintptr_t)-1;
+
+ /* Check for task termination now, before we have a need to
+ * call CHECK_PROCESS_TERMINATED later. That would suppress
+ * the event that we are processing. */
+ if (WIFSIGNALED(status)) {
+ event.type = EVENT_EXIT_SIGNAL;
+ event.e_un.signum = WTERMSIG(status);
+ debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
return &event;
}
- if (opt_i) {
- event.proc->instruction_pointer =
- get_instruction_pointer(event.proc);
+ if (WIFEXITED(status)) {
+ event.type = EVENT_EXIT;
+ event.e_un.ret_val = WEXITSTATUS(status);
+ debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
+ return &event;
}
+
+ event.proc->instruction_pointer = get_instruction_pointer(event.proc);
+ if (event.proc->instruction_pointer == (void *)(uintptr_t)-1) {
+ CHECK_PROCESS_TERMINATED;
+ if (errno != 0)
+ perror("get_instruction_pointer");
+ }
+
switch (syscall_p(event.proc, status, &tmp)) {
case 1:
event.type = EVENT_SYSCALL;
@@ -82,36 +272,30 @@ next_event(void) {
debug(DEBUG_EVENT, "event: ARCH_SYSRET: pid=%d, sysnum=%d", pid, tmp);
return &event;
case -1:
- event.type = EVENT_NONE;
- continue_process(event.proc->pid);
- debug(DEBUG_EVENT, "event: NONE: pid=%d (syscall_p returned -1)", pid);
- return &event;
+ CHECK_PROCESS_TERMINATED;
+ if (errno != 0)
+ perror("syscall_p");
}
- if (WIFSTOPPED(status) && ((status>>16 == PTRACE_EVENT_FORK) || (status>>16 == PTRACE_EVENT_VFORK) || (status>>16 == PTRACE_EVENT_CLONE))) {
- unsigned long data;
- ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
- event.type = EVENT_CLONE;
- event.e_un.newpid = data;
- debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d", pid, (int)data);
- return &event;
+ if (WIFSTOPPED(status)) {
+ int what = status >> 16;
+ if (what == PTRACE_EVENT_VFORK
+ || what == PTRACE_EVENT_FORK
+ || what == PTRACE_EVENT_CLONE) {
+ unsigned long data;
+ event.type = what == PTRACE_EVENT_VFORK
+ ? EVENT_VFORK : EVENT_CLONE;
+ ptrace(PTRACE_GETEVENTMSG, pid, NULL, &data);
+ event.e_un.newpid = data;
+ debug(DEBUG_EVENT, "event: CLONE: pid=%d, newpid=%d",
+ pid, (int)data);
+ return &event;
+ }
}
if (WIFSTOPPED(status) && (status>>16 == PTRACE_EVENT_EXEC)) {
event.type = EVENT_EXEC;
debug(DEBUG_EVENT, "event: EXEC: pid=%d", pid);
return &event;
}
- if (WIFEXITED(status)) {
- event.type = EVENT_EXIT;
- event.e_un.ret_val = WEXITSTATUS(status);
- debug(DEBUG_EVENT, "event: EXIT: pid=%d, status=%d", pid, event.e_un.ret_val);
- return &event;
- }
- if (WIFSIGNALED(status)) {
- event.type = EVENT_EXIT_SIGNAL;
- event.e_un.signum = WTERMSIG(status);
- debug(DEBUG_EVENT, "event: EXIT_SIGNAL: pid=%d, signum=%d", pid, event.e_un.signum);
- return &event;
- }
if (!WIFSTOPPED(status)) {
/* should never happen */
event.type = EVENT_NONE;
@@ -122,22 +306,19 @@ next_event(void) {
stop_signal = WSTOPSIG(status);
/* On some targets, breakpoints are signalled not using
- SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. Check
- for these. (TODO: is this true?) */
- if (stop_signal == SIGSEGV
- || stop_signal == SIGILL
-#ifdef SIGEMT
- || stop_signal == SIGEMT
-#endif
- ) {
- if (!event.proc->instruction_pointer) {
- event.proc->instruction_pointer =
- get_instruction_pointer(event.proc);
- }
+ SIGTRAP, but also with SIGILL, SIGSEGV or SIGEMT. SIGEMT
+ is not defined on Linux, but check for the others.
- if (address2bpstruct(event.proc, event.proc->instruction_pointer))
+ N.B. see comments in GDB's infrun.c for details. I've
+ actually seen this on an Itanium machine on RHEL 5, I don't
+ remember the exact kernel version anymore. ia64-sigill.s
+ in the test suite tests this. Petr Machata 2011-06-08. */
+ void * break_address
+ = event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
+ if ((stop_signal == SIGSEGV || stop_signal == SIGILL)
+ && leader != NULL
+ && address2bpstruct(leader, break_address))
stop_signal = SIGTRAP;
- }
if (stop_signal != (SIGTRAP | event.proc->tracesysgood)
&& stop_signal != SIGTRAP) {
@@ -150,12 +331,25 @@ next_event(void) {
/* last case [by exhaustion] */
event.type = EVENT_BREAKPOINT;
- if (!event.proc->instruction_pointer) {
- event.proc->instruction_pointer =
- get_instruction_pointer(event.proc);
- }
- event.e_un.brk_addr =
- event.proc->instruction_pointer - DECR_PC_AFTER_BREAK;
+ event.e_un.brk_addr = break_address;
debug(DEBUG_EVENT, "event: BREAKPOINT: pid=%d, addr=%p", pid, event.e_un.brk_addr);
+
return &event;
}
+
+static enum ecb_status
+event_for_proc(struct Event *event, void *data)
+{
+ if (event->proc == data)
+ return ecb_deque;
+ else
+ return ecb_cont;
+}
+
+void
+delete_events_for(struct Process *proc)
+{
+ struct Event *event;
+ while ((event = each_qd_event(&event_for_proc, proc)) != NULL)
+ free(event);
+}
diff --git a/sysdeps/linux-gnu/events.h b/sysdeps/linux-gnu/events.h
new file mode 100644
index 0000000..3802aff
--- /dev/null
+++ b/sysdeps/linux-gnu/events.h
@@ -0,0 +1,41 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef SYSDEPS_LINUX_GNU_EVENTS_H
+#define SYSDEPS_LINUX_GNU_EVENTS_H
+
+#include "forward.h"
+
+/* Declarations for event que functions. */
+
+enum ecb_status {
+ ecb_cont, /* The iteration should continue. */
+ ecb_yield, /* The iteration should stop, yielding this
+ * event. */
+ ecb_deque, /* Like ecb_stop, but the event should be removed
+ * from the queue. */
+};
+
+struct Event *each_qd_event(enum ecb_status (*cb)(struct Event *event,
+ void *data), void *data);
+void delete_events_for(struct Process * proc);
+void enque_event(struct Event *event);
+
+#endif /* SYSDEPS_LINUX_GNU_EVENTS_H */
diff --git a/sysdeps/linux-gnu/i386/Makefile b/sysdeps/linux-gnu/i386/Makefile
deleted file mode 100644
index 60d7531..0000000
--- a/sysdeps/linux-gnu/i386/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/i386/arch.h b/sysdeps/linux-gnu/i386/arch.h
deleted file mode 100644
index dc7383f..0000000
--- a/sysdeps/linux-gnu/i386/arch.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#define BREAKPOINT_VALUE {0xcc}
-#define BREAKPOINT_LENGTH 1
-#define DECR_PC_AFTER_BREAK 1
-
-#define LT_ELFCLASS ELFCLASS32
-#define LT_ELF_MACHINE EM_386
diff --git a/sysdeps/linux-gnu/i386/plt.c b/sysdeps/linux-gnu/i386/plt.c
deleted file mode 100644
index b53ff44..0000000
--- a/sysdeps/linux-gnu/i386/plt.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <gelf.h>
-#include "common.h"
-
-GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- return lte->plt_addr + (ndx + 1) * 16;
-}
-
-void *
-sym2addr(Process *proc, struct library_symbol *sym) {
- return sym->enter_addr;
-}
diff --git a/sysdeps/linux-gnu/i386/ptrace.h b/sysdeps/linux-gnu/i386/ptrace.h
deleted file mode 100644
index c3cbcb6..0000000
--- a/sysdeps/linux-gnu/i386/ptrace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/i386/regs.c b/sysdeps/linux-gnu/i386/regs.c
deleted file mode 100644
index 6777f17..0000000
--- a/sysdeps/linux-gnu/i386/regs.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
-
-#include "common.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void *
-get_instruction_pointer(Process *proc) {
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EIP, 0);
-}
-
-void
-set_instruction_pointer(Process *proc, void *addr) {
- ptrace(PTRACE_POKEUSER, proc->pid, 4 * EIP, (long)addr);
-}
-
-void *
-get_stack_pointer(Process *proc) {
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, 4 * UESP, 0);
-}
-
-void *
-get_return_addr(Process *proc, void *stack_pointer) {
- return (void *)ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0);
-}
-
-void
-set_return_addr(Process *proc, void *addr) {
- ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, (long)addr);
-}
diff --git a/sysdeps/linux-gnu/i386/syscallent.h b/sysdeps/linux-gnu/i386/syscallent.h
deleted file mode 100644
index 8f4c887..0000000
--- a/sysdeps/linux-gnu/i386/syscallent.h
+++ /dev/null
@@ -1,317 +0,0 @@
- "restart_syscall", /* 0 */
- "exit", /* 1 */
- "fork", /* 2 */
- "read", /* 3 */
- "write", /* 4 */
- "open", /* 5 */
- "close", /* 6 */
- "waitpid", /* 7 */
- "creat", /* 8 */
- "link", /* 9 */
- "unlink", /* 10 */
- "execve", /* 11 */
- "chdir", /* 12 */
- "time", /* 13 */
- "mknod", /* 14 */
- "chmod", /* 15 */
- "lchown", /* 16 */
- "break", /* 17 */
- "oldstat", /* 18 */
- "lseek", /* 19 */
- "getpid", /* 20 */
- "mount", /* 21 */
- "umount", /* 22 */
- "setuid", /* 23 */
- "getuid", /* 24 */
- "stime", /* 25 */
- "ptrace", /* 26 */
- "alarm", /* 27 */
- "oldfstat", /* 28 */
- "pause", /* 29 */
- "utime", /* 30 */
- "stty", /* 31 */
- "gtty", /* 32 */
- "access", /* 33 */
- "nice", /* 34 */
- "ftime", /* 35 */
- "sync", /* 36 */
- "kill", /* 37 */
- "rename", /* 38 */
- "mkdir", /* 39 */
- "rmdir", /* 40 */
- "dup", /* 41 */
- "pipe", /* 42 */
- "times", /* 43 */
- "prof", /* 44 */
- "brk", /* 45 */
- "setgid", /* 46 */
- "getgid", /* 47 */
- "signal", /* 48 */
- "geteuid", /* 49 */
- "getegid", /* 50 */
- "acct", /* 51 */
- "umount2", /* 52 */
- "lock", /* 53 */
- "ioctl", /* 54 */
- "fcntl", /* 55 */
- "mpx", /* 56 */
- "setpgid", /* 57 */
- "ulimit", /* 58 */
- "oldolduname", /* 59 */
- "umask", /* 60 */
- "chroot", /* 61 */
- "ustat", /* 62 */
- "dup2", /* 63 */
- "getppid", /* 64 */
- "getpgrp", /* 65 */
- "setsid", /* 66 */
- "sigaction", /* 67 */
- "sgetmask", /* 68 */
- "ssetmask", /* 69 */
- "setreuid", /* 70 */
- "setregid", /* 71 */
- "sigsuspend", /* 72 */
- "sigpending", /* 73 */
- "sethostname", /* 74 */
- "setrlimit", /* 75 */
- "getrlimit", /* 76 */
- "getrusage", /* 77 */
- "gettimeofday", /* 78 */
- "settimeofday", /* 79 */
- "getgroups", /* 80 */
- "setgroups", /* 81 */
- "select", /* 82 */
- "symlink", /* 83 */
- "oldlstat", /* 84 */
- "readlink", /* 85 */
- "uselib", /* 86 */
- "swapon", /* 87 */
- "reboot", /* 88 */
- "readdir", /* 89 */
- "mmap", /* 90 */
- "munmap", /* 91 */
- "truncate", /* 92 */
- "ftruncate", /* 93 */
- "fchmod", /* 94 */
- "fchown", /* 95 */
- "getpriority", /* 96 */
- "setpriority", /* 97 */
- "profil", /* 98 */
- "statfs", /* 99 */
- "fstatfs", /* 100 */
- "ioperm", /* 101 */
- "socketcall", /* 102 */
- "syslog", /* 103 */
- "setitimer", /* 104 */
- "getitimer", /* 105 */
- "stat", /* 106 */
- "lstat", /* 107 */
- "fstat", /* 108 */
- "olduname", /* 109 */
- "iopl", /* 110 */
- "vhangup", /* 111 */
- "idle", /* 112 */
- "vm86old", /* 113 */
- "wait4", /* 114 */
- "swapoff", /* 115 */
- "sysinfo", /* 116 */
- "ipc", /* 117 */
- "fsync", /* 118 */
- "sigreturn", /* 119 */
- "clone", /* 120 */
- "setdomainname", /* 121 */
- "uname", /* 122 */
- "modify_ldt", /* 123 */
- "adjtimex", /* 124 */
- "mprotect", /* 125 */
- "sigprocmask", /* 126 */
- "create_module", /* 127 */
- "init_module", /* 128 */
- "delete_module", /* 129 */
- "get_kernel_syms", /* 130 */
- "quotactl", /* 131 */
- "getpgid", /* 132 */
- "fchdir", /* 133 */
- "bdflush", /* 134 */
- "sysfs", /* 135 */
- "personality", /* 136 */
- "afs_syscall", /* 137 */
- "setfsuid", /* 138 */
- "setfsgid", /* 139 */
- "_llseek", /* 140 */
- "getdents", /* 141 */
- "_newselect", /* 142 */
- "flock", /* 143 */
- "msync", /* 144 */
- "readv", /* 145 */
- "writev", /* 146 */
- "getsid", /* 147 */
- "fdatasync", /* 148 */
- "_sysctl", /* 149 */
- "mlock", /* 150 */
- "munlock", /* 151 */
- "mlockall", /* 152 */
- "munlockall", /* 153 */
- "sched_setparam", /* 154 */
- "sched_getparam", /* 155 */
- "sched_setscheduler", /* 156 */
- "sched_getscheduler", /* 157 */
- "sched_yield", /* 158 */
- "sched_get_priority_max", /* 159 */
- "sched_get_priority_min", /* 160 */
- "sched_rr_get_interval", /* 161 */
- "nanosleep", /* 162 */
- "mremap", /* 163 */
- "setresuid", /* 164 */
- "getresuid", /* 165 */
- "vm86", /* 166 */
- "query_module", /* 167 */
- "poll", /* 168 */
- "nfsservctl", /* 169 */
- "setresgid", /* 170 */
- "getresgid", /* 171 */
- "prctl", /* 172 */
- "rt_sigreturn", /* 173 */
- "rt_sigaction", /* 174 */
- "rt_sigprocmask", /* 175 */
- "rt_sigpending", /* 176 */
- "rt_sigtimedwait", /* 177 */
- "rt_sigqueueinfo", /* 178 */
- "rt_sigsuspend", /* 179 */
- "pread64", /* 180 */
- "pwrite64", /* 181 */
- "chown", /* 182 */
- "getcwd", /* 183 */
- "capget", /* 184 */
- "capset", /* 185 */
- "sigaltstack", /* 186 */
- "sendfile", /* 187 */
- "getpmsg", /* 188 */
- "putpmsg", /* 189 */
- "vfork", /* 190 */
- "ugetrlimit", /* 191 */
- "mmap2", /* 192 */
- "truncate64", /* 193 */
- "ftruncate64", /* 194 */
- "stat64", /* 195 */
- "lstat64", /* 196 */
- "fstat64", /* 197 */
- "lchown32", /* 198 */
- "getuid32", /* 199 */
- "getgid32", /* 200 */
- "geteuid32", /* 201 */
- "getegid32", /* 202 */
- "setreuid32", /* 203 */
- "setregid32", /* 204 */
- "getgroups32", /* 205 */
- "setgroups32", /* 206 */
- "fchown32", /* 207 */
- "setresuid32", /* 208 */
- "getresuid32", /* 209 */
- "setresgid32", /* 210 */
- "getresgid32", /* 211 */
- "chown32", /* 212 */
- "setuid32", /* 213 */
- "setgid32", /* 214 */
- "setfsuid32", /* 215 */
- "setfsgid32", /* 216 */
- "pivot_root", /* 217 */
- "mincore", /* 218 */
- "madvise1", /* 219 */
- "getdents64", /* 220 */
- "fcntl64", /* 221 */
- "222", /* 222 */
- "223", /* 223 */
- "gettid", /* 224 */
- "readahead", /* 225 */
- "setxattr", /* 226 */
- "lsetxattr", /* 227 */
- "fsetxattr", /* 228 */
- "getxattr", /* 229 */
- "lgetxattr", /* 230 */
- "fgetxattr", /* 231 */
- "listxattr", /* 232 */
- "llistxattr", /* 233 */
- "flistxattr", /* 234 */
- "removexattr", /* 235 */
- "lremovexattr", /* 236 */
- "fremovexattr", /* 237 */
- "tkill", /* 238 */
- "sendfile64", /* 239 */
- "futex", /* 240 */
- "sched_setaffinity", /* 241 */
- "sched_getaffinity", /* 242 */
- "set_thread_area", /* 243 */
- "get_thread_area", /* 244 */
- "io_setup", /* 245 */
- "io_destroy", /* 246 */
- "io_getevents", /* 247 */
- "io_submit", /* 248 */
- "io_cancel", /* 249 */
- "fadvise64", /* 250 */
- "251", /* 251 */
- "exit_group", /* 252 */
- "lookup_dcookie", /* 253 */
- "epoll_create", /* 254 */
- "epoll_ctl", /* 255 */
- "epoll_wait", /* 256 */
- "remap_file_pages", /* 257 */
- "set_tid_address", /* 258 */
- "timer_create", /* 259 */
- "260", /* 260 */
- "261", /* 261 */
- "262", /* 262 */
- "263", /* 263 */
- "264", /* 264 */
- "265", /* 265 */
- "266", /* 266 */
- "267", /* 267 */
- "statfs64", /* 268 */
- "fstatfs64", /* 269 */
- "tgkill", /* 270 */
- "utimes", /* 271 */
- "fadvise64_64", /* 272 */
- "vserver", /* 273 */
- "mbind", /* 274 */
- "get_mempolicy", /* 275 */
- "set_mempolicy", /* 276 */
- "mq_open", /* 277 */
- "278", /* 278 */
- "279", /* 279 */
- "280", /* 280 */
- "281", /* 281 */
- "282", /* 282 */
- "kexec_load", /* 283 */
- "waitid", /* 284 */
- "285", /* 285 */
- "add_key", /* 286 */
- "request_key", /* 287 */
- "keyctl", /* 288 */
- "ioprio_set", /* 289 */
- "ioprio_get", /* 290 */
- "inotify_init", /* 291 */
- "inotify_add_watch", /* 292 */
- "inotify_rm_watch", /* 293 */
- "migrate_pages", /* 294 */
- "openat", /* 295 */
- "mkdirat", /* 296 */
- "mknodat", /* 297 */
- "fchownat", /* 298 */
- "futimesat", /* 299 */
- "fstatat64", /* 300 */
- "unlinkat", /* 301 */
- "renameat", /* 302 */
- "linkat", /* 303 */
- "symlinkat", /* 304 */
- "readlinkat", /* 305 */
- "fchmodat", /* 306 */
- "faccessat", /* 307 */
- "pselect6", /* 308 */
- "ppoll", /* 309 */
- "unshare", /* 310 */
- "set_robust_list", /* 311 */
- "get_robust_list", /* 312 */
- "splice", /* 313 */
- "sync_file_range", /* 314 */
- "tee", /* 315 */
- "vmsplice", /* 316 */
diff --git a/sysdeps/linux-gnu/i386/trace.c b/sysdeps/linux-gnu/i386/trace.c
deleted file mode 100644
index 76f1105..0000000
--- a/sysdeps/linux-gnu/i386/trace.c
+++ /dev/null
@@ -1,85 +0,0 @@
-#include "config.h"
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
-
-#include "common.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void
-get_arch_dep(Process *proc) {
-}
-
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
- */
-int
-syscall_p(Process *proc, int status, int *sysnum) {
- if (WIFSTOPPED(status)
- && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
- *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ORIG_EAX, 0);
-
- if (proc->callstack_depth > 0 &&
- proc->callstack[proc->callstack_depth - 1].is_syscall &&
- proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) {
- return 2;
- }
-
- if (*sysnum >= 0) {
- return 1;
- }
- }
- return 0;
-}
-
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EAX, 0);
- }
-
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- return ptrace(PTRACE_PEEKTEXT, proc->pid,
- proc->stack_pointer + 4 * (arg_num + 1), 0);
- } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
-#if 0
- switch (arg_num) {
- case 0:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EBX, 0);
- case 1:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ECX, 0);
- case 2:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDX, 0);
- case 3:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * ESI, 0);
- case 4:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * EDI, 0);
- default:
- fprintf(stderr,
- "gimme_arg called with wrong arguments\n");
- exit(2);
- }
-#else
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0);
-#endif
- } else {
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
- }
-
- return 0;
-}
-
-void
-save_register_args(enum tof type, Process *proc) {
-}
diff --git a/sysdeps/linux-gnu/ia64/Makefile b/sysdeps/linux-gnu/ia64/Makefile
deleted file mode 100644
index 4f0ef63..0000000
--- a/sysdeps/linux-gnu/ia64/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o breakpoint.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(LD) -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/ia64/Makefile.am b/sysdeps/linux-gnu/ia64/Makefile.am
new file mode 100644
index 0000000..c5fd360
--- /dev/null
+++ b/sysdeps/linux-gnu/ia64/Makefile.am
@@ -0,0 +1,36 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ breakpoint.c \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/ia64/Makefile.in b/sysdeps/linux-gnu/ia64/Makefile.in
new file mode 100644
index 0000000..a4eb305
--- /dev/null
+++ b/sysdeps/linux-gnu/ia64/Makefile.in
@@ -0,0 +1,533 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/ia64
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = breakpoint.lo plt.lo regs.lo trace.lo \
+ fetch.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ breakpoint.c \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/ia64/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/ia64/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/breakpoint.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/ia64/arch.h b/sysdeps/linux-gnu/ia64/arch.h
index 673047c..82780d4 100644
--- a/sysdeps/linux-gnu/ia64/arch.h
+++ b/sysdeps/linux-gnu/ia64/arch.h
@@ -1,9 +1,34 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006,2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#define ARCH_HAVE_DISABLE_BREAKPOINT 1
#define ARCH_HAVE_ENABLE_BREAKPOINT 1
+#define ARCH_HAVE_FETCH_ARG
+#define ARCH_HAVE_FETCH_PACK
#define BREAKPOINT_LENGTH 16
#define BREAKPOINT_VALUE {0}
#define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_LITTLE
+#define ARCH_HAVE_TRANSLATE_ADDRESS
#define LT_ELFCLASS ELFCLASS64
#define LT_ELF_MACHINE EM_IA_64
diff --git a/sysdeps/linux-gnu/ia64/breakpoint.c b/sysdeps/linux-gnu/ia64/breakpoint.c
index 4f09173..ca34e93 100644
--- a/sysdeps/linux-gnu/ia64/breakpoint.c
+++ b/sysdeps/linux-gnu/ia64/breakpoint.c
@@ -1,14 +1,33 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2005,2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
/* IA64 breakpoint support. Much of this clagged from gdb
* -Ian Wienand <ianw@gelato.unsw.edu.au> 10/3/2005
*/
-#include "config.h"
-
#include <sys/ptrace.h>
#include <string.h>
-#include "arch.h"
-#include "options.h"
-#include "output.h"
+#include <assert.h>
+
+#include "breakpoint.h"
#include "debug.h"
static long long
@@ -153,7 +172,8 @@ union bundle_t {
};
void
-arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) {
+arch_enable_breakpoint(pid_t pid, struct breakpoint *sbp)
+{
unsigned long addr = (unsigned long)sbp->addr;
union bundle_t bundle;
@@ -163,9 +183,7 @@ arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) {
debug(1, "Enable Breakpoint at %p)", sbp->addr);
- if (slotnum > 2)
- printf
- ("Can't insert breakpoint for slot numbers greater than 2.");
+ assert(slotnum <= 2);
addr &= ~0x0f;
bundle.ubundle[0] = ptrace(PTRACE_PEEKTEXT, pid, addr, 0);
@@ -190,7 +208,8 @@ arch_enable_breakpoint(pid_t pid, Breakpoint *sbp) {
}
void
-arch_disable_breakpoint(pid_t pid, const Breakpoint *sbp) {
+arch_disable_breakpoint(pid_t pid, const struct breakpoint *sbp)
+{
unsigned long addr = (unsigned long)sbp->addr;
int slotnum = (int)(addr & 0x0f) & 0x3;
diff --git a/sysdeps/linux-gnu/ia64/fetch.c b/sysdeps/linux-gnu/ia64/fetch.c
new file mode 100644
index 0000000..54dc5b8
--- /dev/null
+++ b/sysdeps/linux-gnu/ia64/fetch.c
@@ -0,0 +1,502 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Steve Fink
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <stdlib.h>
+#include <assert.h>
+#include <sys/rse.h>
+#include <ptrace.h>
+#include <string.h>
+#include <errno.h>
+
+#include "backend.h"
+#include "fetch.h"
+#include "type.h"
+#include "proc.h"
+#include "value.h"
+
+struct fetch_context {
+ arch_addr_t stack_pointer;
+ struct pt_all_user_regs regs;
+ enum param_pack_flavor ppflavor;
+
+ /* Return values larger than 256 bits (except HFAs of up to 8
+ * elements) are returned in a buffer allocated by the
+ * caller. A pointer to the buffer is passed to the called
+ * procedure in r8. This register is not guaranteed to be
+ * preserved by the called procedure. */
+ unsigned long r8;
+
+ int slot_n;
+ int flt;
+};
+
+union cfm_t {
+ struct {
+ unsigned long sof:7;
+ unsigned long sol:7;
+ unsigned long sor:4;
+ unsigned long rrb_gr:7;
+ unsigned long rrb_fr:7;
+ unsigned long rrb_pr:6;
+ } cfm;
+ unsigned long value;
+};
+
+static int
+fetch_context_init(struct Process *proc, struct fetch_context *context)
+{
+ context->slot_n = 0;
+ context->flt = 8;
+ if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->regs) < 0)
+ return -1;
+ context->stack_pointer = (void *)(context->regs.gr[12] + 16);
+ context->ppflavor = PARAM_PACK_ARGS;
+
+ return 0;
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *context = malloc(sizeof(*context));
+ if (context == NULL
+ || fetch_context_init(proc, context) < 0) {
+ free(context);
+ return NULL;
+ }
+ context->r8 = context->regs.gr[8];
+
+ return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc,
+ struct fetch_context *context)
+{
+ struct fetch_context *clone = malloc(sizeof(*context));
+ if (clone == NULL)
+ return NULL;
+ *clone = *context;
+ return clone;
+}
+
+int
+allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ size_t al = type_alignof(proc, info);
+ size_t sz = type_sizeof(proc, info);
+ if (al == (size_t)-1 || sz == (size_t)-1)
+ return -1;
+
+ errno = 0;
+ long value = ptrace(PTRACE_PEEKDATA, proc->pid, ctx->stack_pointer, 0);
+ if (value == -1 && errno != 0)
+ return -1;
+ ctx->stack_pointer += 8;
+ value_set_word(valuep, value);
+
+ return 0;
+}
+
+static int
+allocate_reg(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ if (ctx->slot_n >= 8)
+ return allocate_stack_slot(ctx, proc, info, valuep);
+
+ int reg_num = ctx->slot_n++;
+ if (ctx->slot_n == 8)
+ ctx->flt = 16;
+ if (valuep == NULL)
+ return 0;
+
+ /* This would normally be brought over from asm/ptrace.h, but
+ * when we do, we get namespace conflicts between asm/fpu.h
+ * and libunwind. */
+ enum { PT_AUR_BSP = 17 };
+
+ union cfm_t cfm = { .value = ctx->regs.cfm };
+ unsigned long *bsp = (unsigned long *)ctx->regs.ar[PT_AUR_BSP];
+ unsigned long idx = -cfm.cfm.sof + reg_num;
+ unsigned long *ptr = ia64_rse_skip_regs(bsp, idx);
+ errno = 0;
+ long ret = ptrace(PTRACE_PEEKDATA, proc->pid, ptr, 0);
+ if (ret == -1 && errno != 0)
+ return -1;
+
+ value_set_word(valuep, ret);
+ return 0;
+}
+
+static int
+copy_aggregate_part(struct fetch_context *ctx, struct Process *proc,
+ unsigned char *buf, size_t size)
+{
+ size_t slots = (size + 7) / 8;
+ struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
+ while (slots-- > 0) {
+ size_t chunk_sz = size > 8 ? 8 : size;
+ size -= 8;
+
+ struct value tmp;
+ value_init(&tmp, proc, NULL, long_info, 0);
+ int rc = allocate_reg(ctx, proc, long_info, &tmp);
+ if (rc >= 0) {
+ memcpy(buf, value_get_data(&tmp, NULL), chunk_sz);
+ buf += 8;
+ }
+ value_destroy(&tmp);
+ if (rc < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int
+allocate_arg(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ size_t align = type_alignof(proc, info);
+ if (sz == (size_t)-1 || align == (size_t)-1)
+ return -1;
+
+ unsigned char *buf = value_reserve(valuep, sz);
+ if (buf == NULL)
+ return -1;
+
+ assert(align == 0 || align == 1 || align == 2 || align == 4
+ || align == 8 || align == 16);
+
+ /* For aggregates with an external alignment of 16 bytes, the
+ * Next Even policy is used. 128-bit integers use the Next
+ * Even policy as well. */
+ if (align == 16 && ctx->slot_n % 2 != 0)
+ allocate_reg(ctx, proc, info, NULL);
+
+ int rc= copy_aggregate_part(ctx, proc, buf, sz);
+
+ return rc;
+}
+
+/* Stolen from David Mosberger's utrace tool, which he released under
+ the GPL
+ (http://www.gelato.unsw.edu.au/archives/linux-ia64/0104/1405.html) */
+static inline double
+fpreg_to_double (struct ia64_fpreg *fp) {
+ double result;
+ asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp));
+ return result;
+}
+
+static int
+allocate_float(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ int take_slot)
+{
+ /* The actual parameter is passed in the next available
+ * floating-point parameter register, if one is
+ * available. Floating-point parameter registers are allocated
+ * as needed from the range f8-f15, starting with f8. */
+ /* Any register parameters corresponding to a
+ * variable-argument specification are passed in GRs. */
+ if (ctx->flt > 15 || ctx->ppflavor == PARAM_PACK_VARARGS)
+ /* If all available floating-point parameter registers
+ * have been used, the actual parameter is passed in
+ * the appropriate general register(s). */
+ return allocate_reg(ctx, proc, info, valuep);
+
+ union {
+ double d;
+ float f;
+ char buf[0];
+ } u = { .d = fpreg_to_double(&ctx->regs.fr[ctx->flt++]) };
+ if (take_slot)
+ allocate_reg(ctx, proc, info, NULL);
+
+ if (info->type == ARGTYPE_FLOAT)
+ u.f = u.d;
+ else
+ assert(info->type == ARGTYPE_DOUBLE);
+
+ if (value_reserve(valuep, sizeof(u)) == NULL)
+ return -1;
+ memmove(value_get_raw_data(valuep), u.buf, sizeof(u));
+
+ return 0;
+}
+
+static enum arg_type
+get_hfa_type(struct arg_type_info *info, size_t *countp)
+{
+ size_t n = type_aggregate_size(info);
+ if (n == (size_t)-1)
+ return ARGTYPE_VOID;
+
+ enum arg_type type = ARGTYPE_VOID;
+ *countp = 0;
+
+ while (n-- > 0) {
+ struct arg_type_info *emt = type_element(info, n);
+
+ enum arg_type emt_type = emt->type;
+ size_t emt_count = 1;
+ if (emt_type == ARGTYPE_STRUCT || emt_type == ARGTYPE_ARRAY)
+ emt_type = get_hfa_type(emt, &emt_count);
+
+ if (type == ARGTYPE_VOID) {
+ if (emt_type != ARGTYPE_FLOAT
+ && emt_type != ARGTYPE_DOUBLE)
+ return ARGTYPE_VOID;
+ type = emt_type;
+ }
+ if (emt_type != type)
+ return ARGTYPE_VOID;
+ *countp += emt_count;
+ }
+ return type;
+}
+
+static int
+allocate_hfa(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ enum arg_type hfa_type, size_t hfa_count)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ /* If an actual parameter is known to correspond to an HFA
+ * formal parameter, each element is passed in the next
+ * available floating-point argument register, until the eight
+ * argument registers are exhausted. The remaining elements of
+ * the aggregate are passed in output GRs, according to the
+ * normal conventions.
+ *
+ * Because HFAs are mapped to parameter slots as aggregates,
+ * single-precision HFAs will be allocated with two
+ * floating-point values in each parameter slot, but only one
+ * value per register.
+ *
+ * It is possible for the first of two values in a parameter
+ * slot to occupy the last available floating- point parameter
+ * register. In this case, the second value is passed in its
+ * designated GR, but the half of the GR that would have
+ * contained the first value is undefined. */
+
+ size_t slot_off = 0;
+
+ unsigned char *buf = value_reserve(valuep, sz);
+ if (buf == NULL)
+ return -1;
+
+ struct arg_type_info *hfa_info = type_get_simple(hfa_type);
+ size_t hfa_sz = type_sizeof(proc, hfa_info);
+
+ /* Pass in register the part that we can. */
+ while (ctx->flt <= 15 && hfa_count > 0) {
+ struct value tmp;
+ value_init(&tmp, proc, NULL, hfa_info, 0);
+ int rc = allocate_float(ctx, proc, hfa_info, &tmp, 0);
+ if (rc >= 0) {
+ memcpy(buf, value_get_data(&tmp, NULL), hfa_sz);
+ slot_off += hfa_sz;
+ buf += hfa_sz;
+ hfa_count--;
+
+ /* Scratch each fully used slot. */
+ while (slot_off >= 8) {
+ if (allocate_reg(ctx, proc, info, NULL) < 0)
+ rc = -1;
+ slot_off -= 8;
+ }
+ }
+ value_destroy(&tmp);
+ if (rc < 0)
+ return -1;
+ }
+
+ /* If we have half-slot opened (the case where odd
+ * ARGTYPE_FLOAT member fits into the last floating point
+ * register, and the following even member does not), finish
+ * it first. */
+ struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
+ if (slot_off != 0 && hfa_count > 0) {
+ struct value tmp;
+ value_init(&tmp, proc, NULL, long_info, 0);
+ int rc = allocate_reg(ctx, proc, long_info, &tmp);
+ if (rc >= 0) {
+ unsigned char *data = value_get_data(&tmp, NULL);
+ memcpy(buf, data, 8 - slot_off);
+ buf += 8 - slot_off;
+ hfa_count--;
+ }
+ value_destroy(&tmp);
+ if (rc < 0) {
+ return -1;
+ }
+ }
+
+ /* The rest is passed in registers and on stack. */
+ size_t rest = hfa_count * hfa_sz;
+ return copy_aggregate_part(ctx, proc, buf, rest);
+}
+
+static int
+allocate_ret(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ /* Homogeneous floating-point aggregates [...] are returned in
+ * floating-point registers, provided the array or structure
+ * contains no more than eight individual values. The
+ * elements of the aggregate are placed in successive
+ * floating-point registers, beginning with f8. */
+ if (info->type == ARGTYPE_STRUCT || info->type == ARGTYPE_ARRAY) {
+ size_t hfa_size;
+ enum arg_type hfa_type = get_hfa_type(info, &hfa_size);
+ if (hfa_type != ARGTYPE_VOID && hfa_size <= 8)
+ return allocate_hfa(ctx, proc, info, valuep,
+ hfa_type, hfa_size);
+ }
+
+ /* Integers and pointers are passed in r8. 128-bit integers
+ * are passed in r8 and r9. Aggregates of up to 256 bits [32
+ * bytes] are passed in registers r8...r11. */
+ if (sz <= 32) {
+ unsigned char *buf = value_reserve(valuep, sz);
+ if (buf == NULL)
+ return -1;
+ memcpy(buf, ctx->regs.gr + 8, sz);
+ return 0;
+ }
+
+ if (value_pass_by_reference(valuep) < 0)
+ return -1;
+ value_set_word(valuep, ctx->r8);
+ return 0;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
+ struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ switch (info->type) {
+ enum arg_type hfa_type;
+ size_t hfa_size;
+
+ case ARGTYPE_VOID:
+ value_set_word(valuep, 0);
+ return 0;
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ return allocate_float(ctx, proc, info, valuep, 1);
+
+ case ARGTYPE_STRUCT:
+ hfa_type = get_hfa_type(info, &hfa_size);
+ if (hfa_type != ARGTYPE_VOID)
+ return allocate_hfa(ctx, proc, info, valuep,
+ hfa_type, hfa_size);
+ /* Fall through. */
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return allocate_arg(ctx, proc, info, valuep);
+
+ case ARGTYPE_ARRAY:
+ /* Arrays decay into pointers. XXX Fortran? */
+ default:
+ assert(info->type != info->type);
+ abort();
+ }
+}
+
+int
+arch_fetch_retval(struct fetch_context *ctx, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (fetch_context_init(proc, ctx) < 0)
+ return -1;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ /* The rules for returning those types are the same as
+ * for passing them in arguments. */
+ return arch_fetch_arg_next(ctx, type, proc, info, valuep);
+
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ case ARGTYPE_STRUCT:
+ return allocate_ret(ctx, proc, info, valuep);
+
+ case ARGTYPE_ARRAY:
+ /* Arrays decay into pointers. XXX Fortran? */
+ assert(info->type != ARGTYPE_ARRAY);
+ abort();
+ }
+ assert("unhandled type");
+ abort();
+ return arch_fetch_arg_next(ctx, type, proc, info, valuep);
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+ free(context);
+}
+
+int
+arch_fetch_param_pack_start(struct fetch_context *context,
+ enum param_pack_flavor ppflavor)
+{
+ context->ppflavor = ppflavor;
+ return 0;
+}
+
+void
+arch_fetch_param_pack_end(struct fetch_context *context)
+{
+ context->ppflavor = PARAM_PACK_ARGS;
+}
diff --git a/sysdeps/linux-gnu/ia64/plt.c b/sysdeps/linux-gnu/ia64/plt.c
index 7fd451b..a29488f 100644
--- a/sysdeps/linux-gnu/ia64/plt.c
+++ b/sysdeps/linux-gnu/ia64/plt.c
@@ -1,29 +1,56 @@
-#include <gelf.h>
-#include "common.h"
-
-/* A bundle is 128 bits */
-#define BUNDLE_SIZE 16
-
/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
- The PLT has
-
- ] 3 bundles as a header
-
- ] The special reserved entry
+#include <errno.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/ptrace.h>
- ] Following that, each PLT entry has it's initial code that the GOT entry
- points to. Each PLT entry has one bundle allocated.
+#include "proc.h"
+#include "common.h"
+#include "library.h"
- ] Following that, each PLT entry has two bundles of actual PLT code,
- i.e. load up the address from the GOT and jump to it. This is the
- point we want to insert the breakpoint, as this will be captured
- every time we jump to the PLT entry in the code.
+/* A bundle is 128 bits. */
+#define BUNDLE_SIZE 16
-*/
+/* The PLT has
+ *
+ * - 3 bundles as a header
+ *
+ * - The special reserved entry
+ *
+ * - Following that, each PLT entry has it's initial code that the GOT
+ * entry points to. Each PLT entry has one bundle allocated.
+ *
+ * - Following that, each PLT entry has two bundles of actual PLT
+ * code, i.e. load up the address from the GOT and jump to it. This
+ * is the point we want to insert the breakpoint, as this will be
+ * captured every time we jump to the PLT entry in the code.
+ */
GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
+arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela)
+{
/* Find number of entires by removing header and special
* entry, dividing total size by three, since each PLT entry
* will have 3 bundles (1 for inital entry and two for the PLT
@@ -35,7 +62,7 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
unsigned long addr =
lte->plt_addr + (4 * BUNDLE_SIZE) + (BUNDLE_SIZE * entries) +
(2 * ndx * BUNDLE_SIZE);
- debug(3, "Found PLT %d entry at %lx\n", ndx, addr);
+ debug(3, "Found PLT %zd entry at %lx", ndx, addr);
return addr;
}
@@ -44,3 +71,29 @@ void *
sym2addr(Process *proc, struct library_symbol *sym) {
return sym->enter_addr;
}
+
+int
+arch_translate_address_dyn(struct Process *proc,
+ arch_addr_t addr, arch_addr_t *ret)
+{
+ errno = 0;
+ unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ if (l == -1UL && errno) {
+ fprintf(stderr, "dynamic .opd translation of %p: %s\n",
+ addr, strerror(errno));
+ return -1;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ *ret = (arch_addr_t)(uintptr_t)l;
+ return 0;
+}
+
+int
+arch_translate_address(struct ltelf *lte,
+ arch_addr_t addr, arch_addr_t *ret)
+{
+ *ret = addr;
+ return 0;
+}
diff --git a/sysdeps/linux-gnu/ia64/ptrace.h b/sysdeps/linux-gnu/ia64/ptrace.h
index c3cbcb6..ef63b4f 100644
--- a/sysdeps/linux-gnu/ia64/ptrace.h
+++ b/sysdeps/linux-gnu/ia64/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/ia64/regs.c b/sysdeps/linux-gnu/ia64/regs.c
index d161d34..cbc2744 100644
--- a/sysdeps/linux-gnu/ia64/regs.c
+++ b/sysdeps/linux-gnu/ia64/regs.c
@@ -1,13 +1,36 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include <sys/ptrace.h>
+#include <errno.h>
#include <asm/ptrace_offsets.h>
#include <asm/rse.h>
#include <stddef.h>
-#include "debug.h"
+#include "proc.h"
#include "common.h"
void *
@@ -37,12 +60,18 @@ set_instruction_pointer(Process *proc, void *addr) {
void *
get_stack_pointer(Process *proc) {
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0);
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0);
+ if (l == -1 && errno)
+ return NULL;
+ return (void *)l;
}
void *
get_return_addr(Process *proc, void *stack_pointer) {
- return (void *)ptrace(PTRACE_PEEKUSER, proc->pid, PT_B0, 0);
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_B0, 0);
+ if (l == -1 && errno)
+ return NULL;
+ return (void *)l;
}
void
diff --git a/sysdeps/linux-gnu/ia64/signalent.h b/sysdeps/linux-gnu/ia64/signalent.h
index 5395f82..31699db 100644
--- a/sysdeps/linux-gnu/ia64/signalent.h
+++ b/sysdeps/linux-gnu/ia64/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/ia64/syscallent.h b/sysdeps/linux-gnu/ia64/syscallent.h
index 9bb4fb8..094cea2 100644
--- a/sysdeps/linux-gnu/ia64/syscallent.h
+++ b/sysdeps/linux-gnu/ia64/syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"0", /* 0 */
"1", /* 1 */
"2", /* 2 */
diff --git a/sysdeps/linux-gnu/ia64/trace.c b/sysdeps/linux-gnu/ia64/trace.c
index 799e0ff..e608275 100644
--- a/sysdeps/linux-gnu/ia64/trace.c
+++ b/sysdeps/linux-gnu/ia64/trace.c
@@ -1,3 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Steve Fink
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <stdlib.h>
@@ -9,8 +31,11 @@
#include <string.h>
#include <asm/ptrace_offsets.h>
#include <asm/rse.h>
+#include <errno.h>
+#include "proc.h"
#include "common.h"
+#include "type.h"
/* What we think of as a bundle, ptrace thinks of it as two unsigned
* longs */
@@ -48,9 +73,10 @@ int
syscall_p(Process *proc, int status, int *sysnum) {
if (WIFSTOPPED(status)
&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
- unsigned long slot =
- (ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0) >> 41) &
- 0x3;
+ long l = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IPSR, 0);
+ if (l == -1 && errno)
+ return -1;
+ unsigned long slot = ((unsigned long)l >> 41) & 0x3;
unsigned long ip =
ptrace(PTRACE_PEEKUSER, proc->pid, PT_CR_IIP, 0);
@@ -114,155 +140,6 @@ syscall_p(Process *proc, int status, int *sysnum) {
return 0;
}
-/* Stolen from David Mosberger's utrace tool, which he released under
- the GPL
- (http://www.gelato.unsw.edu.au/archives/linux-ia64/0104/1405.html) */
-static inline double
-fpreg_to_double (struct ia64_fpreg *fp) {
- double result;
-
- asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp));
- return result;
-}
-
-static long
-gimme_long_arg(enum tof type, Process *proc, int arg_num) {
- union cfm_t cfm;
- unsigned long bsp;
-
- bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0);
- cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0);
-
- if (arg_num == -1) /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, PT_R8, 0);
-
- /* First 8 arguments are passed in registers on the register
- * stack, the following arguments are passed on the stack
- * after a 16 byte scratch area
- *
- * If the function has returned, the ia64 register window has
- * been reverted to the caller's configuration. So although in
- * the callee, the first parameter is in R32, in the caller
- * the first parameter comes in the registers after the local
- * registers (really, input parameters plus locals, but the
- * hardware doesn't track the distinction.) So we have to add
- * in the size of the local area (sol) to find the first
- * parameter passed to the callee. */
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- if (arg_num < 8) {
- if (type == LT_TOF_FUNCTIONR)
- arg_num += cfm.cfm.sol;
-
- return ptrace(PTRACE_PEEKDATA, proc->pid,
- (long)ia64_rse_skip_regs((unsigned long *)bsp,
- -cfm.cfm.sof + arg_num),
- 0);
- } else {
- unsigned long sp =
- ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16;
- return ptrace(PTRACE_PEEKDATA, proc->pid,
- sp + (8 * (arg_num - 8)));
- }
- }
-
- if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR)
- return ptrace(PTRACE_PEEKDATA, proc->pid,
- (long)ia64_rse_skip_regs((unsigned long *)bsp, arg_num),
- 0);
-
- /* error if we get here */
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
-}
-
-static long float_regs[8] = { PT_F8, PT_F9, PT_F10, PT_F11,
- PT_F12, PT_F13, PT_F14, PT_F15 };
-static double
-gimme_float_arg(enum tof type, Process *proc, int arg_num) {
- union cfm_t cfm;
- unsigned long bsp;
- struct ia64_fpreg reg;
-
- if (arg_num == -1) { /* return value */
- reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid,
- PT_F8, 0);
- reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid,
- PT_F8 + 0x8, 0);
- return fpreg_to_double(&reg);
- }
-
- bsp = ptrace(PTRACE_PEEKUSER, proc->pid, PT_AR_BSP, 0);
- cfm.value = ptrace(PTRACE_PEEKUSER, proc->pid, PT_CFM, 0);
-
- /* The first 8 arguments are passed in regular registers
- * (counting from R32), unless they are floating point values
- * (the case in question here). In that case, up to the first
- * 8 regular registers are still "allocated" for each of the
- * first 8 parameters, but if a parameter is floating point,
- * then the register is left unset and the parameter is passed
- * in the first available floating-point register, counting
- * from F8.
- *
- * Take func(int a, float f, int b, double d), for example.
- * a - passed in R32
- * f - R33 left unset, value passed in F8
- * b - passed in R34
- * d - R35 left unset, value passed in F9
- *
- * ltrace handles this by counting floating point arguments
- * while parsing declarations. The "arg_num" in this routine
- * (which is only called for floating point values) really
- * means which floating point parameter we're looking for,
- * ignoring everything else.
- *
- * Following the first 8 arguments, the remaining arguments
- * are passed on the stack after a 16 byte scratch area
- */
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- if (arg_num < 8) {
- reg.u.bits[0] = ptrace(PTRACE_PEEKUSER, proc->pid,
- float_regs[arg_num], 0);
- reg.u.bits[1] = ptrace(PTRACE_PEEKUSER, proc->pid,
- float_regs[arg_num] + 0x8, 0);
- return fpreg_to_double(&reg);
- } else {
- unsigned long sp =
- ptrace(PTRACE_PEEKUSER, proc->pid, PT_R12, 0) + 16;
- reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid,
- sp + (8 * (arg_num - 8)));
- reg.u.bits[0] = ptrace(PTRACE_PEEKDATA, proc->pid,
- sp + (8 * (arg_num - 8)) + 0x8);
- return fpreg_to_double(&reg);
- }
- }
-
- /* error if we get here */
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
-}
-
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- union {
- long l;
- float f;
- double d;
- } cvt;
-
- if (info->type == ARGTYPE_FLOAT)
- cvt.f = gimme_float_arg(type, proc, info->u.float_info.float_index);
- else if (info->type == ARGTYPE_DOUBLE)
- cvt.d = gimme_float_arg(type, proc, info->u.double_info.float_index);
- else
- cvt.l = gimme_long_arg(type, proc, arg_num);
-
- return cvt.l;
-}
-
-void
-save_register_args(enum tof type, Process *proc) {
-}
-
void
get_arch_dep(Process *proc) {
}
diff --git a/sysdeps/linux-gnu/m68k/Makefile b/sysdeps/linux-gnu/m68k/Makefile
deleted file mode 100644
index 60d7531..0000000
--- a/sysdeps/linux-gnu/m68k/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/m68k/Makefile.am b/sysdeps/linux-gnu/m68k/Makefile.am
new file mode 100644
index 0000000..aa63e15
--- /dev/null
+++ b/sysdeps/linux-gnu/m68k/Makefile.am
@@ -0,0 +1,35 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/m68k/Makefile.in b/sysdeps/linux-gnu/m68k/Makefile.in
new file mode 100644
index 0000000..45eebd3
--- /dev/null
+++ b/sysdeps/linux-gnu/m68k/Makefile.in
@@ -0,0 +1,530 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/m68k
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo fetch.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/m68k/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/m68k/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/m68k/arch.h b/sysdeps/linux-gnu/m68k/arch.h
index 1790d09..3829901 100644
--- a/sysdeps/linux-gnu/m68k/arch.h
+++ b/sysdeps/linux-gnu/m68k/arch.h
@@ -1,6 +1,29 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 1998,2002,2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define ARCH_HAVE_FETCH_ARG
+
#define BREAKPOINT_VALUE { 0x4e, 0x4f }
#define BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 2
+#define ARCH_ENDIAN_BIG
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_68K
diff --git a/sysdeps/linux-gnu/m68k/fetch.c b/sysdeps/linux-gnu/m68k/fetch.c
new file mode 100644
index 0000000..f6d8a0b
--- /dev/null
+++ b/sysdeps/linux-gnu/m68k/fetch.c
@@ -0,0 +1,239 @@
+/*
+ * This file is part of ltrace.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/procfs.h>
+#include <sys/reg.h>
+
+#include "backend.h"
+#include "expr.h"
+#include "fetch.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
+#include "value.h"
+
+struct fetch_context
+{
+ elf_gregset_t regs;
+ elf_fpregset_t fpregs;
+
+ int arg_num;
+ arch_addr_t stack_pointer;
+ struct value retval;
+};
+
+static int
+fetch_register_banks(struct Process *proc, struct fetch_context *context,
+ int floating)
+{
+ if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->regs) < 0)
+ return -1;
+
+ if (floating
+ && ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0)
+ return -1;
+
+ return 0;
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *context = malloc(sizeof(*context));
+ if (context == NULL)
+ return NULL;
+
+ assert(type != LT_TOF_FUNCTIONR && type != LT_TOF_SYSCALLR);
+ if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTION) < 0) {
+ fail:
+ free(context);
+ return NULL;
+ }
+
+ context->arg_num = 0;
+ context->stack_pointer = (arch_addr_t)context->regs[PT_USP] + 4;
+
+ size_t sz = type_sizeof(proc, ret_info);
+ if (sz == (size_t)-1)
+ goto fail;
+
+ if (ret_info->type == ARGTYPE_STRUCT && !(sz <= 4 || sz == 8)) {
+ value_init(&context->retval, proc, NULL, ret_info, 0);
+
+ if (value_pass_by_reference(&context->retval) < 0)
+ goto fail;
+ value_set_word(&context->retval, context->regs[PT_A1]);
+ } else {
+ value_init_detached(&context->retval, NULL, NULL, 0);
+ }
+
+ return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context)
+{
+ struct fetch_context *ret = malloc(sizeof(*ret));
+ if (ret == NULL)
+ return NULL;
+ *ret = *context;
+ return ret;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ if (type == LT_TOF_SYSCALL) {
+ int reg;
+
+ switch (context->arg_num++) {
+ case 0: reg = PT_D1; break;
+ case 1: reg = PT_D2; break;
+ case 2: reg = PT_D3; break;
+ case 3: reg = PT_D4; break;
+ case 4: reg = PT_D5; break;
+ case 5: reg = PT_A0; break;
+ default:
+ assert(!"More than six syscall arguments???");
+ abort();
+ }
+ value_set_word(valuep, context->regs[reg]);
+ } else {
+ size_t a = type_alignof(valuep->inferior, valuep->type);
+ if (a < 4)
+ a = 4;
+ context->stack_pointer = (arch_addr_t)
+ align((unsigned long)context->stack_pointer, a);
+ if (sz < 4)
+ context->stack_pointer += 4 - sz;
+
+ value_in_inferior(valuep, context->stack_pointer);
+ context->stack_pointer += sz;
+ }
+
+ return 0;
+}
+
+int
+arch_fetch_retval(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0)
+ return -1;
+
+ if (context->retval.type != NULL) {
+ /* Struct return value was extracted when in fetch
+ * init. */
+ *valuep = context->retval;
+ return 0;
+ }
+
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_POINTER:
+ {
+ unsigned char *buf = value_get_raw_data(valuep);
+ int reg = info->type == ARGTYPE_POINTER ? PT_A0 : PT_D0;
+ unsigned char *val
+ = (unsigned char *)&context->regs[reg];
+ if (sz < 4) val += 4 - sz;
+ memcpy(buf, val, sz);
+ }
+ return 0;
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ {
+ union {
+ long double ld;
+ double d;
+ float f;
+ char buf[0];
+ } u;
+
+ unsigned long *reg = &context->fpregs.fpregs[0];
+ memcpy (&u.ld, reg, sizeof (u.ld));
+ if (valuep->type->type == ARGTYPE_FLOAT)
+ u.f = (float)u.ld;
+ else if (valuep->type->type == ARGTYPE_DOUBLE)
+ u.d = (double)u.ld;
+ else {
+ assert(!"Unexpected floating type!");
+ abort();
+ }
+ unsigned char *buf = value_get_raw_data (valuep);
+ memcpy (buf, u.buf, sz);
+ }
+ return 0;
+
+ case ARGTYPE_STRUCT:
+ {
+ unsigned char *buf = value_get_raw_data(valuep);
+ unsigned char *val
+ = (unsigned char *)&context->regs[PT_D0];
+
+ assert(sz <= 4 || sz == 8);
+ if (sz < 4) val += 4 - sz;
+ memcpy(buf, val, sz <= 4 ? sz : 4);
+ if (sz == 8)
+ memcpy(buf + 4, &context->regs[PT_D1], 4);
+ }
+ return 0;
+
+ default:
+ assert(!"Unexpected m68k retval type!");
+ abort();
+ }
+
+ abort();
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+ if (context != NULL)
+ free(context);
+}
diff --git a/sysdeps/linux-gnu/m68k/plt.c b/sysdeps/linux-gnu/m68k/plt.c
index 508d7fc..c1b37dd 100644
--- a/sysdeps/linux-gnu/m68k/plt.c
+++ b/sysdeps/linux-gnu/m68k/plt.c
@@ -1,10 +1,32 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
+#include "proc.h"
#include "common.h"
+#include "library.h"
GElf_Addr
arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
return lte->plt_addr + (ndx + 1)
- * ((lte->ehdr.e_flags & EF_CPU32) ? 24 : 12);
+ * ((lte->ehdr.e_flags & EF_CPU32) ? 24 : 20);
}
void *
diff --git a/sysdeps/linux-gnu/m68k/ptrace.h b/sysdeps/linux-gnu/m68k/ptrace.h
index c3cbcb6..ad7e0d6 100644
--- a/sysdeps/linux-gnu/m68k/ptrace.h
+++ b/sysdeps/linux-gnu/m68k/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/m68k/regs.c b/sysdeps/linux-gnu/m68k/regs.c
index 959a60e..4afdfbb 100644
--- a/sysdeps/linux-gnu/m68k/regs.c
+++ b/sysdeps/linux-gnu/m68k/regs.c
@@ -1,9 +1,30 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
diff --git a/sysdeps/linux-gnu/m68k/signalent.h b/sysdeps/linux-gnu/m68k/signalent.h
index 5395f82..31699db 100644
--- a/sysdeps/linux-gnu/m68k/signalent.h
+++ b/sysdeps/linux-gnu/m68k/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/m68k/syscallent.h b/sysdeps/linux-gnu/m68k/syscallent.h
index 4d65b39..ceafd2e 100644
--- a/sysdeps/linux-gnu/m68k/syscallent.h
+++ b/sysdeps/linux-gnu/m68k/syscallent.h
@@ -1,4 +1,25 @@
- "0", /* 0 */
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Andreas Schwab
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "restart_syscall", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
"read", /* 3 */
@@ -15,7 +36,7 @@
"mknod", /* 14 */
"chmod", /* 15 */
"chown", /* 16 */
- "break", /* 17 */
+ "17", /* 17 */
"oldstat", /* 18 */
"lseek", /* 19 */
"getpid", /* 20 */
@@ -29,11 +50,11 @@
"oldfstat", /* 28 */
"pause", /* 29 */
"utime", /* 30 */
- "stty", /* 31 */
- "gtty", /* 32 */
+ "31", /* 31 */
+ "32", /* 32 */
"access", /* 33 */
"nice", /* 34 */
- "ftime", /* 35 */
+ "35", /* 35 */
"sync", /* 36 */
"kill", /* 37 */
"rename", /* 38 */
@@ -42,7 +63,7 @@
"dup", /* 41 */
"pipe", /* 42 */
"times", /* 43 */
- "prof", /* 44 */
+ "44", /* 44 */
"brk", /* 45 */
"setgid", /* 46 */
"getgid", /* 47 */
@@ -51,13 +72,13 @@
"getegid", /* 50 */
"acct", /* 51 */
"umount2", /* 52 */
- "lock", /* 53 */
+ "53", /* 53 */
"ioctl", /* 54 */
"fcntl", /* 55 */
- "mpx", /* 56 */
+ "56", /* 56 */
"setpgid", /* 57 */
- "ulimit", /* 58 */
- "oldolduname", /* 59 */
+ "58", /* 58 */
+ "59", /* 59 */
"umask", /* 60 */
"chroot", /* 61 */
"ustat", /* 62 */
@@ -96,10 +117,10 @@
"fchown", /* 95 */
"getpriority", /* 96 */
"setpriority", /* 97 */
- "profil", /* 98 */
+ "98", /* 98 */
"statfs", /* 99 */
"fstatfs", /* 100 */
- "ioperm", /* 101 */
+ "101", /* 101 */
"socketcall", /* 102 */
"syslog", /* 103 */
"setitimer", /* 104 */
@@ -107,7 +128,7 @@
"stat", /* 106 */
"lstat", /* 107 */
"fstat", /* 108 */
- "olduname", /* 109 */
+ "109", /* 109 */
"110", /* 110 */
"vhangup", /* 111 */
"112", /* 112 */
@@ -135,7 +156,7 @@
"bdflush", /* 134 */
"sysfs", /* 135 */
"personality", /* 136 */
- "afs_syscall", /* 137 */
+ "137", /* 137 */
"setfsuid", /* 138 */
"setfsgid", /* 139 */
"_llseek", /* 140 */
@@ -276,7 +297,72 @@
"mq_notify", /* 275 */
"mq_getsetattr", /* 276 */
"waitid", /* 277 */
- "vserver", /* 278 */
+ "278", /* 278 */
"add_key", /* 279 */
"request_key", /* 280 */
"keyctl", /* 281 */
+ "ioprio_set", /* 282 */
+ "ioprio_get", /* 283 */
+ "inotify_init", /* 284 */
+ "inotify_add_watch", /* 285 */
+ "inotify_rm_watch", /* 286 */
+ "migrate_pages", /* 287 */
+ "openat", /* 288 */
+ "mkdirat", /* 289 */
+ "mknodat", /* 290 */
+ "fchownat", /* 291 */
+ "futimesat", /* 292 */
+ "fstatat64", /* 293 */
+ "unlinkat", /* 294 */
+ "renameat", /* 295 */
+ "linkat", /* 296 */
+ "symlinkat", /* 297 */
+ "readlinkat", /* 298 */
+ "fchmodat", /* 299 */
+ "faccessat", /* 300 */
+ "pselect6", /* 301 */
+ "ppoll", /* 302 */
+ "unshare", /* 303 */
+ "set_robust_list", /* 304 */
+ "get_robust_list", /* 305 */
+ "splice", /* 306 */
+ "sync_file_range", /* 307 */
+ "tee", /* 308 */
+ "vmsplice", /* 309 */
+ "move_pages", /* 310 */
+ "sched_setaffinity", /* 311 */
+ "sched_getaffinity", /* 312 */
+ "kexec_load", /* 313 */
+ "getcpu", /* 314 */
+ "epoll_pwait", /* 315 */
+ "utimensat", /* 316 */
+ "signalfd", /* 317 */
+ "timerfd_create", /* 318 */
+ "eventfd", /* 319 */
+ "fallocate", /* 320 */
+ "timerfd_settime", /* 321 */
+ "timerfd_gettime", /* 322 */
+ "signalfd4", /* 323 */
+ "eventfd2", /* 324 */
+ "epoll_create1", /* 325 */
+ "dup3", /* 326 */
+ "pipe2", /* 327 */
+ "inotify_init1", /* 328 */
+ "preadv", /* 329 */
+ "pwritev", /* 330 */
+ "rt_tgsigqueueinfo", /* 331 */
+ "perf_event_open", /* 332 */
+ "get_thread_area", /* 333 */
+ "set_thread_area", /* 334 */
+ "atomic_cmpxchg_32", /* 335 */
+ "atomic_barrier", /* 336 */
+ "fanotify_init", /* 337 */
+ "fanotify_mark", /* 338 */
+ "prlimit64", /* 339 */
+ "name_to_handle_at", /* 340 */
+ "open_by_handle_at", /* 341 */
+ "clock_adjtime", /* 342 */
+ "syncfs", /* 343 */
+ "setns", /* 344 */
+ "process_vm_readv", /* 345 */
+ "process_vm_writev", /* 346 */
diff --git a/sysdeps/linux-gnu/m68k/trace.c b/sysdeps/linux-gnu/m68k/trace.c
index 2f89fdf..311ffd5 100644
--- a/sysdeps/linux-gnu/m68k/trace.c
+++ b/sysdeps/linux-gnu/m68k/trace.c
@@ -1,3 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 1998,2001,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
@@ -6,6 +28,7 @@
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
@@ -44,46 +67,3 @@ syscall_p(Process *proc, int status, int *sysnum) {
}
return 0;
}
-
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D0, 0);
- }
-
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- return ptrace(PTRACE_PEEKTEXT, proc->pid,
- proc->stack_pointer + 4 * (arg_num + 1), 0);
- } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
-#if 0
- switch (arg_num) {
- case 0:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D1, 0);
- case 1:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D2, 0);
- case 2:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D3, 0);
- case 3:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D4, 0);
- case 4:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * PT_D5, 0);
- default:
- fprintf(stderr,
- "gimme_arg called with wrong arguments\n");
- exit(2);
- }
-#else
- /* That hack works on m68k, too */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 4 * arg_num, 0);
-#endif
- } else {
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
- }
-
- return 0;
-}
-
-void
-save_register_args(enum tof type, Process *proc) {
-}
diff --git a/sysdeps/linux-gnu/mipsel/Doxyfile b/sysdeps/linux-gnu/mipsel/Doxyfile
index b4f5eb2..165f929 100644
--- a/sysdeps/linux-gnu/mipsel/Doxyfile
+++ b/sysdeps/linux-gnu/mipsel/Doxyfile
@@ -1,3 +1,21 @@
+# This file is part of ltrace.
+# Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
# Doxyfile 1.5.1
#---------------------------------------------------------------------------
diff --git a/sysdeps/linux-gnu/mipsel/Makefile b/sysdeps/linux-gnu/mipsel/Makefile
deleted file mode 100644
index 44f4aae..0000000
--- a/sysdeps/linux-gnu/mipsel/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-.PHONY: all deps clean docs
-
-OBJ = trace.o regs.o plt.o
-SRC=$(OBJ:.o=.c)
-
-all: arch.o
-
-deps:
- $(CC) $(CFLAGS) $(CPPFLAGS) -M $(SRC) > .depends
-
-arch.o: $(OBJ) arch.h
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- -rm -f $(OBJ) arch.o
- -rm -rf html
-
-docs:
- doxygen
-
-
--include .depends
diff --git a/sysdeps/linux-gnu/mipsel/Makefile.am b/sysdeps/linux-gnu/mipsel/Makefile.am
new file mode 100644
index 0000000..9cf8f19
--- /dev/null
+++ b/sysdeps/linux-gnu/mipsel/Makefile.am
@@ -0,0 +1,38 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ mipsel.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+EXTRA_DIST = \
+ Doxyfile
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/mipsel/Makefile.in b/sysdeps/linux-gnu/mipsel/Makefile.in
new file mode 100644
index 0000000..f0a1b06
--- /dev/null
+++ b/sysdeps/linux-gnu/mipsel/Makefile.in
@@ -0,0 +1,532 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/mipsel
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ mipsel.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+EXTRA_DIST = \
+ Doxyfile
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/mipsel/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/mipsel/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/mipsel/arch.h b/sysdeps/linux-gnu/mipsel/arch.h
index dd0ca35..684b546 100644
--- a/sysdeps/linux-gnu/mipsel/arch.h
+++ b/sysdeps/linux-gnu/mipsel/arch.h
@@ -1,9 +1,67 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Eric Vaitl
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef LTRACE_MIPS_ARCH_H
+#define LTRACE_MIPS_ARCH_H
+
+#include <stddef.h>
+#include <gelf.h>
+
#define BREAKPOINT_VALUE { 0x0d, 0x00, 0x00, 0x00 }
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_LITTLE
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_MIPS
-#define PLTs_INIT_BY_HERE "_start"
-#define E_ENTRY_NAME "_start"
+#define ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+ size_t pltgot_addr;
+ size_t mips_local_gotno;
+ size_t mips_gotsym;
+};
+
+#define ARCH_HAVE_FIND_DL_DEBUG
+#define ARCH_HAVE_GET_SYMINFO
+#define ARCH_HAVE_DYNLINK_DONE
+#define ARCH_HAVE_ADD_PLT_ENTRY
+#define ARCH_HAVE_ATOMIC_SINGLESTEP
+#define ARCH_HAVE_SYMBOL_RET
+
+#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
+enum mips_plt_type
+{
+ MIPS_PLT_UNRESOLVED,
+ MIPS_PLT_RESOLVED,
+};
+
+struct arch_library_symbol_data {
+ enum mips_plt_type type;
+ GElf_Addr resolved_addr;
+ GElf_Addr stub_addr;
+
+ /* Set for FUNCs that have GOT entries but not PLT entries. */
+ int gotonly : 1;
+ /* Set for FUNCs that have PLT entries that are always used. */
+ int pltalways : 1;
+};
+
+#endif /* LTRACE_MIPS_ARCH_H */
diff --git a/sysdeps/linux-gnu/mipsel/mipsel.h b/sysdeps/linux-gnu/mipsel/mipsel.h
index a63cafd..a2dbda2 100644
--- a/sysdeps/linux-gnu/mipsel/mipsel.h
+++ b/sysdeps/linux-gnu/mipsel/mipsel.h
@@ -1,11 +1,33 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Arnaud Patard, Mandriva SA
+ * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#ifndef MIPSEL_h
#define MIPSEL_h
-// linux-2.4.30/arch/mips/kernel/ptrace.c for these offsets.
+// asm/ptrace.h for these offsets.
#define off_v0 2
#define off_pc 64
#define off_a0 4
#define off_a3 7
#define off_lr 31
+#define off_fpr0 32
#define off_sp 29
#endif // MIPSEL_h
diff --git a/sysdeps/linux-gnu/mipsel/plt.c b/sysdeps/linux-gnu/mipsel/plt.c
index 003171b..b277fbc 100644
--- a/sysdeps/linux-gnu/mipsel/plt.c
+++ b/sysdeps/linux-gnu/mipsel/plt.c
@@ -1,13 +1,51 @@
-#include <debug.h>
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <string.h>
+#include <error.h>
+#include <errno.h>
#include <gelf.h>
#include <sys/ptrace.h>
+
#include "common.h"
+#include "debug.h"
+#include "proc.h"
+#include "library.h"
+#include "breakpoint.h"
+#include "backend.h"
/**
\addtogroup mipsel
@{
*/
+/* Are we in pure CPIC mode (the non-PIC ABI extension)? */
+static inline int
+mips_elf_is_cpic(unsigned int elf_flags)
+{
+ return (elf_flags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC;
+}
+
/**
\param lte Structure containing link table entry information
\param ndx Index into .dynsym
@@ -32,10 +70,19 @@
*/
GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- debug(1,"plt_addr %x ndx %#x",lte->pltgot_addr, ndx);
- return lte->pltgot_addr +
- sizeof(void *) * (lte->mips_local_gotno + (ndx - lte->mips_gotsym));
+arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
+{
+ debug(1,"plt_addr %zx ndx %#zx",lte->arch.pltgot_addr, ndx);
+
+ if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+ /* Return a pointer into the PLT. */
+ return lte->plt_addr + 16 * 2 + (ndx * 16);
+ }
+
+ /* Return a pointer to a GOT entry. */
+ return lte->arch.pltgot_addr +
+ sizeof(void *) * (lte->arch.mips_local_gotno
+ + (ndx - lte->arch.mips_gotsym));
}
/**
\param proc The process to work on.
@@ -59,6 +106,12 @@ arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
void *
sym2addr(Process *proc, struct library_symbol *sym) {
long ret;
+
+ if (sym->arch.pltalways
+ || (!sym->arch.gotonly && sym->plt_type == LS_TOPLT_NONE)) {
+ return sym->enter_addr;
+ }
+
if(!proc->pid){
return 0;
}
@@ -69,4 +122,304 @@ sym2addr(Process *proc, struct library_symbol *sym) {
return (void *)ret;;
}
+/* Address of run time loader map, used for debugging. */
+#define DT_MIPS_RLD_MAP 0x70000016
+int
+arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
+ arch_addr_t *ret)
+{
+ arch_addr_t rld_addr;
+ int r;
+
+ /* MIPS puts the address of the r_debug structure into the
+ * DT_MIPS_RLD_MAP entry instead of into the DT_DEBUG entry. */
+ r = proc_find_dynamic_entry_addr(proc, dyn_addr,
+ DT_MIPS_RLD_MAP, &rld_addr);
+ if (r == 0) {
+ if (umovebytes(proc, rld_addr,
+ ret, sizeof *ret) != sizeof *ret) {
+ r = -1;
+ }
+ }
+ return r;
+}
+
+
+/*
+ * MIPS doesn't have traditional got.plt entries with corresponding
+ * relocations.
+ *
+ * sym_index is an offset into the external GOT entries. Filter out
+ * stuff that are not functions.
+ */
+int
+arch_get_sym_info(struct ltelf *lte, const char *filename,
+ size_t sym_index, GElf_Rela *rela, GElf_Sym *sym)
+{
+ const char *name;
+
+ if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+ return elf_get_sym_info(lte, filename, sym_index, rela, sym);
+ }
+
+ /* Fixup the offset. */
+ sym_index += lte->arch.mips_gotsym;
+
+ if (gelf_getsym(lte->dynsym, sym_index, sym) == NULL){
+ error(EXIT_FAILURE, 0,
+ "Couldn't get relocation from \"%s\"", filename);
+ }
+
+ name = lte->dynstr + sym->st_name;
+ if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC) {
+ debug(2, "sym %s not a function", name);
+ return -1;
+ }
+
+ return 0;
+}
+
+/**
+ MIPS ABI Supplement:
+
+ DT_PLTGOT This member holds the address of the .got section.
+
+ DT_MIPS_SYMTABNO This member holds the number of entries in the
+ .dynsym section.
+
+ DT_MIPS_LOCAL_GOTNO This member holds the number of local global
+ offset table entries.
+
+ DT_MIPS_GOTSYM This member holds the index of the first dyamic
+ symbol table entry that corresponds to an entry in the gobal offset
+ table.
+
+ */
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+
+ /* FIXME: for CPIC we should really scan both GOT tables
+ * to pick up relocations to external functions. Right now
+ * function pointers from the main binary to external functions
+ * can't be traced in CPIC mode. */
+ if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+ return 0; /* We are already done. */
+ }
+
+ if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
+ || scn == NULL) {
+ fail:
+ error(0, 0, "Couldn't get SHT_DYNAMIC: %s",
+ elf_errmsg(-1));
+ return -1;
+ }
+
+ Elf_Data *data = elf_loaddata(scn, &shdr);
+ if (data == NULL)
+ goto fail;
+
+ size_t j;
+ for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
+ GElf_Dyn dyn;
+ if (gelf_getdyn(data, j, &dyn) == NULL)
+ goto fail;
+
+ if(dyn.d_tag == DT_PLTGOT) {
+ lte->arch.pltgot_addr = dyn.d_un.d_ptr;
+ }
+ if(dyn.d_tag == DT_MIPS_LOCAL_GOTNO){
+ lte->arch.mips_local_gotno = dyn.d_un.d_val;
+ }
+ if(dyn.d_tag == DT_MIPS_GOTSYM){
+ lte->arch.mips_gotsym = dyn.d_un.d_val;
+ }
+ }
+
+ /* Tell the generic code how many dynamic trace:able symbols
+ * we've got. */
+ lte->relplt_count = lte->dynsym_count - lte->arch.mips_gotsym;
+ return 0;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+}
+
+/* When functions return we check if the symbol needs an updated
+ breakpoint with the resolved address. */
+void arch_symbol_ret(struct Process *proc, struct library_symbol *libsym)
+{
+ struct breakpoint *bp;
+ arch_addr_t resolved_addr;
+ struct Process *leader = proc->leader;
+
+ /* Only deal with unresolved symbols. */
+ if (libsym->arch.type != MIPS_PLT_UNRESOLVED)
+ return;
+
+ /* Get out if we are always using the PLT. */
+ if (libsym->arch.pltalways)
+ return;
+
+ resolved_addr = sym2addr(proc, libsym);
+ libsym->arch.resolved_addr = (uintptr_t) resolved_addr;
+ libsym->arch.type = MIPS_PLT_RESOLVED;
+
+ if (libsym->arch.stub_addr == libsym->arch.resolved_addr) {
+ /* Prelinked symbol. No need to add new breakpoint. */
+ return;
+ }
+
+ bp = malloc(sizeof (*bp));
+ if (bp == NULL) {
+ fprintf(stderr, "Failed to allocate bp for %s\n",
+ libsym->name);
+ return;
+ }
+
+ if (breakpoint_init(bp, leader, resolved_addr, libsym) < 0)
+ goto err;
+
+ if (proc_add_breakpoint(leader, bp) < 0) {
+ breakpoint_destroy(bp);
+ goto err;
+ }
+
+ if (breakpoint_turn_on(bp, leader) < 0) {
+ proc_remove_breakpoint(leader, bp);
+ breakpoint_destroy(bp);
+ goto err;
+ }
+ return;
+err:
+ free(bp);
+}
+
+static enum callback_status
+cb_enable_breakpoint_sym(struct library_symbol *libsym, void *data)
+{
+ struct Process *proc = data;
+ arch_addr_t bp_addr;
+
+ if (!libsym->arch.gotonly)
+ return CBS_CONT;
+
+ /* Update state. */
+ bp_addr = sym2addr(proc, libsym);
+ /* XXX The cast to uintptr_t should be removed when
+ * arch_addr_t becomes integral type. keywords: double cast. */
+ libsym->arch.resolved_addr = (uintptr_t) bp_addr;
+
+ if (libsym->arch.resolved_addr == 0)
+ /* FIXME: What does this mean? */
+ return CBS_CONT;
+
+ libsym->arch.type = MIPS_PLT_RESOLVED;
+
+ /* Now, activate the symbol causing a breakpoint to be added. */
+ if (proc_activate_delayed_symbol(proc, libsym) < 0) {
+ fprintf(stderr, "Failed to activate delayed sym %s\n",
+ libsym->name);
+ }
+ return CBS_CONT;
+}
+
+static enum callback_status
+cb_enable_breakpoint_lib(struct Process *proc, struct library *lib, void *data)
+{
+ library_each_symbol(lib, NULL, cb_enable_breakpoint_sym, proc);
+ return CBS_CONT;
+}
+
+void arch_dynlink_done(struct Process *proc)
+{
+ proc_each_library(proc->leader, NULL, cb_enable_breakpoint_lib, NULL);
+}
+
+enum plt_status
+arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+ const char *a_name, GElf_Rela *rela, size_t ndx,
+ struct library_symbol **ret)
+{
+ char *name = NULL;
+ int sym_index = ndx + lte->arch.mips_gotsym;
+
+ struct library_symbol *libsym = malloc(sizeof(*libsym));
+ if (libsym == NULL)
+ return plt_fail;
+
+ GElf_Addr addr = arch_plt_sym_val(lte, sym_index, 0);
+
+ name = strdup(a_name);
+ if (name == NULL) {
+ fprintf(stderr, "%s: failed %s(%#llx): %s\n", __func__,
+ name, addr, strerror(errno));
+ goto fail;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ if (library_symbol_init(libsym,
+ (arch_addr_t) (uintptr_t) addr,
+ name, 1, LS_TOPLT_EXEC) < 0) {
+ fprintf(stderr, "%s: failed %s : %llx\n", __func__, name, addr);
+ goto fail;
+ }
+
+ arch_addr_t bp_addr = sym2addr(proc, libsym);
+ /* XXX This cast should be removed when
+ * arch_addr_t becomes integral type. keywords: double cast. */
+ libsym->arch.stub_addr = (uintptr_t) bp_addr;
+
+ if (bp_addr == 0) {
+ /* Function pointers without PLT entries. */
+ libsym->plt_type = LS_TOPLT_NONE;
+ libsym->arch.gotonly = 1;
+ libsym->arch.type = MIPS_PLT_UNRESOLVED;
+
+ /* Delay breakpoint activation until the symbol gets
+ * resolved. */
+ libsym->delayed = 1;
+ } else if (mips_elf_is_cpic(lte->ehdr.e_flags)) {
+ libsym->arch.pltalways = 1;
+ }
+
+ *ret = libsym;
+ return plt_ok;
+
+fail:
+ free(name);
+ free(libsym);
+ return plt_fail;
+}
+
+int
+arch_library_symbol_init(struct library_symbol *libsym)
+{
+ libsym->arch.pltalways = 0;
+ libsym->arch.gotonly = 0;
+ libsym->arch.type = MIPS_PLT_UNRESOLVED;
+ if (libsym->plt_type == LS_TOPLT_NONE) {
+ libsym->arch.type = MIPS_PLT_RESOLVED;
+ }
+ return 0;
+}
+
+void
+arch_library_symbol_destroy(struct library_symbol *libsym)
+{
+}
+
+int
+arch_library_symbol_clone(struct library_symbol *retp,
+ struct library_symbol *libsym)
+{
+ retp->arch = libsym->arch;
+ return 0;
+}
+
/**@}*/
diff --git a/sysdeps/linux-gnu/mipsel/ptrace.h b/sysdeps/linux-gnu/mipsel/ptrace.h
index c3cbcb6..00c8673 100644
--- a/sysdeps/linux-gnu/mipsel/ptrace.h
+++ b/sysdeps/linux-gnu/mipsel/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/mipsel/regs.c b/sysdeps/linux-gnu/mipsel/regs.c
index a7a6de1..8731ac5 100644
--- a/sysdeps/linux-gnu/mipsel/regs.c
+++ b/sysdeps/linux-gnu/mipsel/regs.c
@@ -1,11 +1,32 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <stddef.h>
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
-#include <linux/user.h>
+#include "proc.h"
#include "common.h"
#include "mipsel.h"
diff --git a/sysdeps/linux-gnu/mipsel/signalent.h b/sysdeps/linux-gnu/mipsel/signalent.h
index 6bb1ff6..d779af5 100644
--- a/sysdeps/linux-gnu/mipsel/signalent.h
+++ b/sysdeps/linux-gnu/mipsel/signalent.h
@@ -1,32 +1,52 @@
-"SIG_0", /* 0 */
- "SIGHUP", // 1 /* Hangup (POSIX). */
- "SIGINT", // 2 /* Interrupt (ANSI). */
- "SIGQUIT", // 3 /* Quit (POSIX). */
- "SIGILL", // 4 /* Illegal instruction (ANSI). */
- "SIGTRAP", // 5 /* Trace trap (POSIX). */
- "SIGIOT", // 6 /* IOT trap (4.2 BSD). */
- "SIGEMT", // 7
- "SIGFPE", // 8 /* Floating-point exception (ANSI). */
- "SIGKILL", // 9 /* Kill, unblockable (POSIX). */
- "SIGBUS", // 10 /* BUS error (4.2 BSD). */
- "SIGSEGV", // 11 /* Segmentation violation (ANSI). */
- "SIGSYS", // 12
- "SIGPIPE", // 13 /* Broken pipe (POSIX). */
- "SIGALRM", // 14 /* Alarm clock (POSIX). */
- "SIGTERM", // 15 /* Termination (ANSI). */
- "SIGUSR1", // 16 /* User-defined signal 1 (POSIX). */
- "SIGUSR2", // 17 /* User-defined signal 2 (POSIX). */
- "SIGCHLD", // 18 /* Child status has changed (POSIX). */
- "SIGPWR", // 19 /* Power failure restart (System V). */
- "SIGWINCH", // 20 /* Window size change (4.3 BSD, Sun). */
- "SIGURG", // 21 /* Urgent condition on socket (4.2 BSD). */
- "SIGIO", // 22 /* I/O now possible (4.2 BSD). */
- "SIGSTOP", // 23 /* Stop, unblockable (POSIX). */
- "SIGTSTP", // 24 /* Keyboard stop (POSIX). */
- "SIGCONT", // 25 /* Continue (POSIX). */
- "SIGTTIN", // 26 /* Background read from tty (POSIX). */
- "SIGTTOU", // 27 /* Background write to tty (POSIX). */
- "SIGVTALRM", // 28 /* Virtual alarm clock (4.2 BSD). */
- "SIGPROF", // 29 /* Profiling alarm clock (4.2 BSD). */
- "SIGXCPU", // 30 /* CPU limit exceeded (4.2 BSD). */
- "SIGXFSZ", // 31 /* File size limit exceeded (4.2 BSD). */
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Arnaud Patard, Mandriva SA
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "SIG_0", /* 0 */
+ "SIGHUP", /* 1 */
+ "SIGINT", /* 2 */
+ "SIGQUIT", /* 3 */
+ "SIGILL", /* 4 */
+ "SIGTRAP", /* 5 */
+ "SIGIOT", /* 6 */
+ "SIGEMT", /* 7 */
+ "SIGFPE", /* 8 */
+ "SIGKILL", /* 9 */
+ "SIGBUS", /* 10 */
+ "SIGSEGV", /* 11 */
+ "SIGSYS", /* 12 */
+ "SIGPIPE", /* 13 */
+ "SIGALRM", /* 14 */
+ "SIGTERM", /* 15 */
+ "SIGUSR1", /* 16 */
+ "SIGUSR2", /* 17 */
+ "SIGCHLD", /* 18 */
+ "SIGPWR", /* 19 */
+ "SIGWINCH", /* 20 */
+ "SIGURG", /* 21 */
+ "SIGIO", /* 22 */
+ "SIGSTOP", /* 23 */
+ "SIGTSTP", /* 24 */
+ "SIGCONT", /* 25 */
+ "SIGTTIN", /* 26 */
+ "SIGTTOU", /* 27 */
+ "SIGVTALRM", /* 28 */
+ "SIGPROF", /* 29 */
+ "SIGXCPU", /* 30 */
+ "SIGXFSZ", /* 31 */
diff --git a/sysdeps/linux-gnu/mipsel/syscallent.h b/sysdeps/linux-gnu/mipsel/syscallent.h
index bed43fe..c0e5dd6 100644
--- a/sysdeps/linux-gnu/mipsel/syscallent.h
+++ b/sysdeps/linux-gnu/mipsel/syscallent.h
@@ -1,241 +1,368 @@
- "0", /*Linux + 0*/
- "exit", /*Linux + 1*/
- "fork", /*Linux + 2*/
- "read", /*Linux + 3*/
- "write", /*Linux + 4*/
- "open", /*Linux + 5*/
- "close", /*Linux + 6*/
- "waitpid", /*Linux + 7*/
- "creat", /*Linux + 8*/
- "link", /*Linux + 9*/
- "unlink", /*Linux + 10*/
- "execve", /*Linux + 11*/
- "chdir", /*Linux + 12*/
- "time", /*Linux + 13*/
- "mknod", /*Linux + 14*/
- "chmod", /*Linux + 15*/
- "lchown", /*Linux + 16*/
- "break", /*Linux + 17*/
- "unused18", /*Linux + 18*/
- "lseek", /*Linux + 19*/
- "getpid", /*Linux + 20*/
- "mount", /*Linux + 21*/
- "umount", /*Linux + 22*/
- "setuid", /*Linux + 23*/
- "getuid", /*Linux + 24*/
- "stime", /*Linux + 25*/
- "ptrace", /*Linux + 26*/
- "alarm", /*Linux + 27*/
- "unused28", /*Linux + 28*/
- "pause", /*Linux + 29*/
- "utime", /*Linux + 30*/
- "stty", /*Linux + 31*/
- "gtty", /*Linux + 32*/
- "access", /*Linux + 33*/
- "nice", /*Linux + 34*/
- "ftime", /*Linux + 35*/
- "sync", /*Linux + 36*/
- "kill", /*Linux + 37*/
- "rename", /*Linux + 38*/
- "mkdir", /*Linux + 39*/
- "rmdir", /*Linux + 40*/
- "dup", /*Linux + 41*/
- "pipe", /*Linux + 42*/
- "times", /*Linux + 43*/
- "prof", /*Linux + 44*/
- "brk", /*Linux + 45*/
- "setgid", /*Linux + 46*/
- "getgid", /*Linux + 47*/
- "signal", /*Linux + 48*/
- "geteuid", /*Linux + 49*/
- "getegid", /*Linux + 50*/
- "acct", /*Linux + 51*/
- "umount2", /*Linux + 52*/
- "lock", /*Linux + 53*/
- "ioctl", /*Linux + 54*/
- "fcntl", /*Linux + 55*/
- "mpx", /*Linux + 56*/
- "setpgid", /*Linux + 57*/
- "ulimit", /*Linux + 58*/
- "unused59", /*Linux + 59*/
- "umask", /*Linux + 60*/
- "chroot", /*Linux + 61*/
- "ustat", /*Linux + 62*/
- "dup2", /*Linux + 63*/
- "getppid", /*Linux + 64*/
- "getpgrp", /*Linux + 65*/
- "setsid", /*Linux + 66*/
- "sigaction", /*Linux + 67*/
- "sgetmask", /*Linux + 68*/
- "ssetmask", /*Linux + 69*/
- "setreuid", /*Linux + 70*/
- "setregid", /*Linux + 71*/
- "sigsuspend", /*Linux + 72*/
- "sigpending", /*Linux + 73*/
- "sethostname", /*Linux + 74*/
- "setrlimit", /*Linux + 75*/
- "getrlimit", /*Linux + 76*/
- "getrusage", /*Linux + 77*/
- "gettimeofday", /*Linux + 78*/
- "settimeofday", /*Linux + 79*/
- "getgroups", /*Linux + 80*/
- "setgroups", /*Linux + 81*/
- "reserved82", /*Linux + 82*/
- "symlink", /*Linux + 83*/
- "unused84", /*Linux + 84*/
- "readlink", /*Linux + 85*/
- "uselib", /*Linux + 86*/
- "swapon", /*Linux + 87*/
- "reboot", /*Linux + 88*/
- "readdir", /*Linux + 89*/
- "mmap", /*Linux + 90*/
- "munmap", /*Linux + 91*/
- "truncate", /*Linux + 92*/
- "ftruncate", /*Linux + 93*/
- "fchmod", /*Linux + 94*/
- "fchown", /*Linux + 95*/
- "getpriority", /*Linux + 96*/
- "setpriority", /*Linux + 97*/
- "profil", /*Linux + 98*/
- "statfs", /*Linux + 99*/
- "fstatfs", /*Linux + 100*/
- "ioperm", /*Linux + 101*/
- "socketcall", /*Linux + 102*/
- "syslog", /*Linux + 103*/
- "setitimer", /*Linux + 104*/
- "getitimer", /*Linux + 105*/
- "stat", /*Linux + 106*/
- "lstat", /*Linux + 107*/
- "fstat", /*Linux + 108*/
- "unused109", /*Linux + 109*/
- "iopl", /*Linux + 110*/
- "vhangup", /*Linux + 111*/
- "idle", /*Linux + 112*/
- "vm86", /*Linux + 113*/
- "wait4", /*Linux + 114*/
- "swapoff", /*Linux + 115*/
- "sysinfo", /*Linux + 116*/
- "ipc", /*Linux + 117*/
- "fsync", /*Linux + 118*/
- "sigreturn", /*Linux + 119*/
- "clone", /*Linux + 120*/
- "setdomainname", /*Linux + 121*/
- "uname", /*Linux + 122*/
- "modify_ldt", /*Linux + 123*/
- "adjtimex", /*Linux + 124*/
- "mprotect", /*Linux + 125*/
- "sigprocmask", /*Linux + 126*/
- "create_module", /*Linux + 127*/
- "init_module", /*Linux + 128*/
- "delete_module", /*Linux + 129*/
- "get_kernel_syms", /*Linux + 130*/
- "quotactl", /*Linux + 131*/
- "getpgid", /*Linux + 132*/
- "fchdir", /*Linux + 133*/
- "bdflush", /*Linux + 134*/
- "sysfs", /*Linux + 135*/
- "personality", /*Linux + 136*/
- "afs_syscall", /*Linux + 137*/ /* Syscall for Andrew File System */
- "setfsuid", /*Linux + 138*/
- "setfsgid", /*Linux + 139*/
- "_llseek", /*Linux + 140*/
- "getdents", /*Linux + 141*/
- "_newselect", /*Linux + 142*/
- "flock", /*Linux + 143*/
- "msync", /*Linux + 144*/
- "readv", /*Linux + 145*/
- "writev", /*Linux + 146*/
- "cacheflush", /*Linux + 147*/
- "cachectl", /*Linux + 148*/
- "sysmips", /*Linux + 149*/
- "unused150", /*Linux + 150*/
- "getsid", /*Linux + 151*/
- "fdatasync", /*Linux + 152*/
- "_sysctl", /*Linux + 153*/
- "mlock", /*Linux + 154*/
- "munlock", /*Linux + 155*/
- "mlockall", /*Linux + 156*/
- "munlockall", /*Linux + 157*/
- "sched_setparam", /*Linux + 158*/
- "sched_getparam", /*Linux + 159*/
- "sched_setscheduler", /*Linux + 160*/
- "sched_getscheduler", /*Linux + 161*/
- "sched_yield", /*Linux + 162*/
- "sched_get_priority_max", /*Linux + 163*/
- "sched_get_priority_min", /*Linux + 164*/
- "sched_rr_get_interval", /*Linux + 165*/
- "nanosleep", /*Linux + 166*/
- "mremap", /*Linux + 167*/
- "accept", /*Linux + 168*/
- "bind", /*Linux + 169*/
- "connect", /*Linux + 170*/
- "getpeername", /*Linux + 171*/
- "getsockname", /*Linux + 172*/
- "getsockopt", /*Linux + 173*/
- "listen", /*Linux + 174*/
- "recv", /*Linux + 175*/
- "recvfrom", /*Linux + 176*/
- "recvmsg", /*Linux + 177*/
- "send", /*Linux + 178*/
- "sendmsg", /*Linux + 179*/
- "sendto", /*Linux + 180*/
- "setsockopt", /*Linux + 181*/
- "shutdown", /*Linux + 182*/
- "socket", /*Linux + 183*/
- "socketpair", /*Linux + 184*/
- "setresuid", /*Linux + 185*/
- "getresuid", /*Linux + 186*/
- "query_module", /*Linux + 187*/
- "poll", /*Linux + 188*/
- "nfsservctl", /*Linux + 189*/
- "setresgid", /*Linux + 190*/
- "getresgid", /*Linux + 191*/
- "prctl", /*Linux + 192*/
- "rt_sigreturn", /*Linux + 193*/
- "rt_sigaction", /*Linux + 194*/
- "rt_sigprocmask", /*Linux + 195*/
- "rt_sigpending", /*Linux + 196*/
- "rt_sigtimedwait", /*Linux + 197*/
- "rt_sigqueueinfo", /*Linux + 198*/
- "rt_sigsuspend", /*Linux + 199*/
- "pread", /*Linux + 200*/
- "pwrite", /*Linux + 201*/
- "chown", /*Linux + 202*/
- "getcwd", /*Linux + 203*/
- "capget", /*Linux + 204*/
- "capset", /*Linux + 205*/
- "sigaltstack", /*Linux + 206*/
- "sendfile", /*Linux + 207*/
- "getpmsg", /*Linux + 208*/
- "putpmsg", /*Linux + 209*/
- "mmap2", /*Linux + 210*/
- "truncate64", /*Linux + 211*/
- "ftruncate64", /*Linux + 212*/
- "stat64", /*Linux + 213*/
- "lstat64", /*Linux + 214*/
- "fstat64", /*Linux + 215*/
- "pivot_root", /*Linux + 216*/
- "mincore", /*Linux + 217*/
- "madvise", /*Linux + 218*/
- "getdents64", /*Linux + 219*/
- "fcntl64", /*Linux + 220*/
- "security", /*Linux + 221*/
- "gettid", /*Linux + 222*/
- "readahead", /*Linux + 223*/
- "setxattr", /*Linux + 224*/
- "lsetxattr", /*Linux + 225*/
- "fsetxattr", /*Linux + 226*/
- "getxattr", /*Linux + 227*/
- "lgetxattr", /*Linux + 228*/
- "fgetxattr", /*Linux + 229*/
- "listxattr", /*Linux + 230*/
- "llistxattr", /*Linux + 231*/
- "flistxattr", /*Linux + 232*/
- "removexattr", /*Linux + 233*/
- "lremovexattr", /*Linux + 234*/
- "fremovexattr", /*Linux + 235*/
- "tkill", /*Linux + 236*/
- "sendfile64", /*Linux + 237*/
- "futex", /*Linux + 238*/
- "sched_setaffinity", /*Linux + 239*/
- "sched_getaffinity", /*Linux + 240*/
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2010 Arnaud Patard, Mandriva SA
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "syscall", /* 0 */
+ "exit", /* 1 */
+ "fork", /* 2 */
+ "read", /* 3 */
+ "write", /* 4 */
+ "open", /* 5 */
+ "close", /* 6 */
+ "waitpid", /* 7 */
+ "creat", /* 8 */
+ "link", /* 9 */
+ "unlink", /* 10 */
+ "execve", /* 11 */
+ "chdir", /* 12 */
+ "time", /* 13 */
+ "mknod", /* 14 */
+ "chmod", /* 15 */
+ "lchown", /* 16 */
+ "break", /* 17 */
+ "unused18", /* 18 */
+ "lseek", /* 19 */
+ "getpid", /* 20 */
+ "mount", /* 21 */
+ "umount", /* 22 */
+ "setuid", /* 23 */
+ "getuid", /* 24 */
+ "stime", /* 25 */
+ "ptrace", /* 26 */
+ "alarm", /* 27 */
+ "unused28", /* 28 */
+ "pause", /* 29 */
+ "utime", /* 30 */
+ "stty", /* 31 */
+ "gtty", /* 32 */
+ "access", /* 33 */
+ "nice", /* 34 */
+ "ftime", /* 35 */
+ "sync", /* 36 */
+ "kill", /* 37 */
+ "rename", /* 38 */
+ "mkdir", /* 39 */
+ "rmdir", /* 40 */
+ "dup", /* 41 */
+ "pipe", /* 42 */
+ "times", /* 43 */
+ "prof", /* 44 */
+ "brk", /* 45 */
+ "setgid", /* 46 */
+ "getgid", /* 47 */
+ "signal", /* 48 */
+ "geteuid", /* 49 */
+ "getegid", /* 50 */
+ "acct", /* 51 */
+ "umount2", /* 52 */
+ "lock", /* 53 */
+ "ioctl", /* 54 */
+ "fcntl", /* 55 */
+ "mpx", /* 56 */
+ "setpgid", /* 57 */
+ "ulimit", /* 58 */
+ "unused59", /* 59 */
+ "umask", /* 60 */
+ "chroot", /* 61 */
+ "ustat", /* 62 */
+ "dup2", /* 63 */
+ "getppid", /* 64 */
+ "getpgrp", /* 65 */
+ "setsid", /* 66 */
+ "sigaction", /* 67 */
+ "sgetmask", /* 68 */
+ "ssetmask", /* 69 */
+ "setreuid", /* 70 */
+ "setregid", /* 71 */
+ "sigsuspend", /* 72 */
+ "sigpending", /* 73 */
+ "sethostname", /* 74 */
+ "setrlimit", /* 75 */
+ "getrlimit", /* 76 */
+ "getrusage", /* 77 */
+ "gettimeofday", /* 78 */
+ "settimeofday", /* 79 */
+ "getgroups", /* 80 */
+ "setgroups", /* 81 */
+ "reserved82", /* 82 */
+ "symlink", /* 83 */
+ "unused84", /* 84 */
+ "readlink", /* 85 */
+ "uselib", /* 86 */
+ "swapon", /* 87 */
+ "reboot", /* 88 */
+ "readdir", /* 89 */
+ "mmap", /* 90 */
+ "munmap", /* 91 */
+ "truncate", /* 92 */
+ "ftruncate", /* 93 */
+ "fchmod", /* 94 */
+ "fchown", /* 95 */
+ "getpriority", /* 96 */
+ "setpriority", /* 97 */
+ "profil", /* 98 */
+ "statfs", /* 99 */
+ "fstatfs", /* 100 */
+ "ioperm", /* 101 */
+ "socketcall", /* 102 */
+ "syslog", /* 103 */
+ "setitimer", /* 104 */
+ "getitimer", /* 105 */
+ "stat", /* 106 */
+ "lstat", /* 107 */
+ "fstat", /* 108 */
+ "unused109", /* 109 */
+ "iopl", /* 110 */
+ "vhangup", /* 111 */
+ "idle", /* 112 */
+ "vm86", /* 113 */
+ "wait4", /* 114 */
+ "swapoff", /* 115 */
+ "sysinfo", /* 116 */
+ "ipc", /* 117 */
+ "fsync", /* 118 */
+ "sigreturn", /* 119 */
+ "clone", /* 120 */
+ "setdomainname", /* 121 */
+ "uname", /* 122 */
+ "modify_ldt", /* 123 */
+ "adjtimex", /* 124 */
+ "mprotect", /* 125 */
+ "sigprocmask", /* 126 */
+ "create_module", /* 127 */
+ "init_module", /* 128 */
+ "delete_module", /* 129 */
+ "get_kernel_syms", /* 130 */
+ "quotactl", /* 131 */
+ "getpgid", /* 132 */
+ "fchdir", /* 133 */
+ "bdflush", /* 134 */
+ "sysfs", /* 135 */
+ "personality", /* 136 */
+ "afs_syscall", /* 137 */
+ "setfsuid", /* 138 */
+ "setfsgid", /* 139 */
+ "_llseek", /* 140 */
+ "getdents", /* 141 */
+ "_newselect", /* 142 */
+ "flock", /* 143 */
+ "msync", /* 144 */
+ "readv", /* 145 */
+ "writev", /* 146 */
+ "cacheflush", /* 147 */
+ "cachectl", /* 148 */
+ "sysmips", /* 149 */
+ "unused150", /* 150 */
+ "getsid", /* 151 */
+ "fdatasync", /* 152 */
+ "_sysctl", /* 153 */
+ "mlock", /* 154 */
+ "munlock", /* 155 */
+ "mlockall", /* 156 */
+ "munlockall", /* 157 */
+ "sched_setparam", /* 158 */
+ "sched_getparam", /* 159 */
+ "sched_setscheduler", /* 160 */
+ "sched_getscheduler", /* 161 */
+ "sched_yield", /* 162 */
+ "sched_get_priority_max", /* 163 */
+ "sched_get_priority_min", /* 164 */
+ "sched_rr_get_interval", /* 165 */
+ "nanosleep", /* 166 */
+ "mremap", /* 167 */
+ "accept", /* 168 */
+ "bind", /* 169 */
+ "connect", /* 170 */
+ "getpeername", /* 171 */
+ "getsockname", /* 172 */
+ "getsockopt", /* 173 */
+ "listen", /* 174 */
+ "recv", /* 175 */
+ "recvfrom", /* 176 */
+ "recvmsg", /* 177 */
+ "send", /* 178 */
+ "sendmsg", /* 179 */
+ "sendto", /* 180 */
+ "setsockopt", /* 181 */
+ "shutdown", /* 182 */
+ "socket", /* 183 */
+ "socketpair", /* 184 */
+ "setresuid", /* 185 */
+ "getresuid", /* 186 */
+ "query_module", /* 187 */
+ "poll", /* 188 */
+ "nfsservctl", /* 189 */
+ "setresgid", /* 190 */
+ "getresgid", /* 191 */
+ "prctl", /* 192 */
+ "rt_sigreturn", /* 193 */
+ "rt_sigaction", /* 194 */
+ "rt_sigprocmask", /* 195 */
+ "rt_sigpending", /* 196 */
+ "rt_sigtimedwait", /* 197 */
+ "rt_sigqueueinfo", /* 198 */
+ "rt_sigsuspend", /* 199 */
+ "pread64", /* 200 */
+ "pwrite64", /* 201 */
+ "chown", /* 202 */
+ "getcwd", /* 203 */
+ "capget", /* 204 */
+ "capset", /* 205 */
+ "sigaltstack", /* 206 */
+ "sendfile", /* 207 */
+ "getpmsg", /* 208 */
+ "putpmsg", /* 209 */
+ "mmap2", /* 210 */
+ "truncate64", /* 211 */
+ "ftruncate64", /* 212 */
+ "stat64", /* 213 */
+ "lstat64", /* 214 */
+ "fstat64", /* 215 */
+ "pivot_root", /* 216 */
+ "mincore", /* 217 */
+ "madvise", /* 218 */
+ "getdents64", /* 219 */
+ "fcntl64", /* 220 */
+ "reserved221", /* 221 */
+ "gettid", /* 222 */
+ "readahead", /* 223 */
+ "setxattr", /* 224 */
+ "lsetxattr", /* 225 */
+ "fsetxattr", /* 226 */
+ "getxattr", /* 227 */
+ "lgetxattr", /* 228 */
+ "fgetxattr", /* 229 */
+ "listxattr", /* 230 */
+ "llistxattr", /* 231 */
+ "flistxattr", /* 232 */
+ "removexattr", /* 233 */
+ "lremovexattr", /* 234 */
+ "fremovexattr", /* 235 */
+ "tkill", /* 236 */
+ "sendfile64", /* 237 */
+ "futex", /* 238 */
+ "sched_setaffinity", /* 239 */
+ "sched_getaffinity", /* 240 */
+ "io_setup", /* 241 */
+ "io_destroy", /* 242 */
+ "io_getevents", /* 243 */
+ "io_submit", /* 244 */
+ "io_cancel", /* 245 */
+ "exit_group", /* 246 */
+ "lookup_dcookie", /* 247 */
+ "epoll_create", /* 248 */
+ "epoll_ctl", /* 249 */
+ "epoll_wait", /* 250 */
+ "remap_file_pages", /* 251 */
+ "set_tid_address", /* 252 */
+ "restart_syscall", /* 253 */
+ "fadvise64", /* 254 */
+ "statfs64", /* 255 */
+ "fstatfs64", /* 256 */
+ "timer_create", /* 257 */
+ "timer_settime", /* 258 */
+ "timer_gettime", /* 259 */
+ "timer_getoverrun", /* 260 */
+ "timer_delete", /* 261 */
+ "clock_settime", /* 262 */
+ "clock_gettime", /* 263 */
+ "clock_getres", /* 264 */
+ "clock_nanosleep", /* 265 */
+ "tgkill", /* 266 */
+ "utimes", /* 267 */
+ "mbind", /* 268 */
+ "get_mempolicy", /* 269 */
+ "set_mempolicy", /* 270 */
+ "mq_open", /* 271 */
+ "mq_unlink", /* 272 */
+ "mq_timedsend", /* 273 */
+ "mq_timedreceive", /* 274 */
+ "mq_notify", /* 275 */
+ "mq_getsetattr", /* 276 */
+ "vserver", /* 277 */
+ "waitid", /* 278 */
+ "279", /* 279 */
+ "add_key", /* 280 */
+ "request_key", /* 281 */
+ "keyctl", /* 282 */
+ "set_thread_area", /* 283 */
+ "inotify_init", /* 284 */
+ "inotify_add_watch", /* 285 */
+ "inotify_rm_watch", /* 286 */
+ "migrate_pages", /* 287 */
+ "openat", /* 288 */
+ "mkdirat", /* 289 */
+ "mknodat", /* 290 */
+ "fchownat", /* 291 */
+ "futimesat", /* 292 */
+ "fstatat64", /* 293 */
+ "unlinkat", /* 294 */
+ "renameat", /* 295 */
+ "linkat", /* 296 */
+ "symlinkat", /* 297 */
+ "readlinkat", /* 298 */
+ "fchmodat", /* 299 */
+ "faccessat", /* 300 */
+ "pselect6", /* 301 */
+ "ppoll", /* 302 */
+ "unshare", /* 303 */
+ "splice", /* 304 */
+ "sync_file_range", /* 305 */
+ "tee", /* 306 */
+ "vmsplice", /* 307 */
+ "move_pages", /* 308 */
+ "set_robust_list", /* 309 */
+ "get_robust_list", /* 310 */
+ "kexec_load", /* 311 */
+ "getcpu", /* 312 */
+ "epoll_pwait", /* 313 */
+ "ioprio_set", /* 314 */
+ "ioprio_get", /* 315 */
+ "utimensat", /* 316 */
+ "signalfd", /* 317 */
+ "timerfd", /* 318 */
+ "eventfd", /* 319 */
+ "fallocate", /* 320 */
+ "timerfd_create", /* 321 */
+ "timerfd_gettime", /* 322 */
+ "timerfd_settime", /* 323 */
+ "signalfd4", /* 324 */
+ "eventfd2", /* 325 */
+ "epoll_create1", /* 326 */
+ "dup3", /* 327 */
+ "pipe2", /* 328 */
+ "inotify_init1", /* 329 */
+ "preadv", /* 330 */
+ "pwritev", /* 331 */
+ "rt_tgsigqueueinfo", /* 332 */
+ "perf_event_open", /* 333 */
+ "accept4", /* 334 */
+ "recvmmsg", /* 335 */
+ "fanotify_init", /* 336 */
+ "fanotify_mark", /* 337 */
+ "prlimit64", /* 338 */
+ "name_to_handle_at", /* 339 */
+ "open_by_handle_at", /* 340 */
+ "clock_adjtime", /* 341 */
+ "syncfs", /* 342 */
+ "sendmmsg", /* 343 */
+ "setns", /* 344 */
+ "process_vm_readv", /* 345 */
+ "process_vm_writev", /* 346 */
diff --git a/sysdeps/linux-gnu/mipsel/trace.c b/sysdeps/linux-gnu/mipsel/trace.c
index ff94930..db9ec21 100644
--- a/sysdeps/linux-gnu/mipsel/trace.c
+++ b/sysdeps/linux-gnu/mipsel/trace.c
@@ -1,3 +1,26 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
+ * Copyright (C) 2010 Arnaud Patard, Mandriva SA
+ * Copyright (C) 2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Eric Vaitl, Cisco Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
@@ -5,9 +28,15 @@
#include <signal.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
-#include "debug.h"
+#include <assert.h>
+
+#include "backend.h"
#include "common.h"
+#include "debug.h"
#include "mipsel.h"
+#include "proc.h"
+#include "type.h"
+
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
#endif
@@ -88,6 +117,177 @@ syscall_p(Process *proc, int status, int *sysnum) {
}
return 0;
}
+
+/* Based on GDB code. */
+#define mips32_op(x) (x >> 26)
+#define itype_op(x) (x >> 26)
+#define itype_rs(x) ((x >> 21) & 0x1f)
+#define itype_rt(x) ((x >> 16) & 0x1f)
+#define itype_immediate(x) (x & 0xffff)
+
+#define jtype_op(x) (x >> 26)
+#define jtype_target(x) (x & 0x03ffffff)
+
+#define rtype_op(x) (x >> 26)
+#define rtype_rs(x) ((x >> 21) & 0x1f)
+#define rtype_rt(x) ((x >> 16) & 0x1f)
+#define rtype_rd(x) ((x >> 11) & 0x1f)
+#define rtype_shamt(x) ((x >> 6) & 0x1f)
+#define rtype_funct(x) (x & 0x3f)
+
+static int32_t
+mips32_relative_offset (uint32_t inst)
+{
+ return ((itype_immediate(inst) ^ 0x8000) - 0x8000) << 2;
+}
+
+int mips_next_pcs(struct Process *proc, uint32_t pc, uint32_t *newpc)
+{
+ uint32_t inst, rx;
+ int op;
+ int rn;
+ int nr = 0;
+
+ inst = ptrace(PTRACE_PEEKTEXT, proc->pid, pc, 0);
+
+ if ((inst & 0xe0000000) != 0) {
+ /* Check for branches. */
+ if (itype_op(inst) >> 2 == 5) {
+ /* BEQL, BNEL, BLEZL, BGTZL: bits 0101xx */
+ op = (itype_op(inst) & 0x03);
+ switch (op)
+ {
+ case 0: /* BEQL */
+ case 1: /* BNEL */
+ case 2: /* BLEZL */
+ case 3: /* BGTZL */
+ newpc[nr++] = pc + 8;
+ newpc[nr++] = pc + 4 +
+ mips32_relative_offset(inst);
+ break;
+ default:
+ newpc[nr++] = pc + 4;
+ break;
+ }
+ } else if (itype_op(inst) == 17 && itype_rs(inst) == 8) {
+ /* Step over the branch. */
+ newpc[nr++] = pc + 8;
+ newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
+ } else {
+ newpc[nr++] = pc + 4;
+ }
+ } else {
+ /* Further subdivide into SPECIAL, REGIMM and other. */
+ switch (op = itype_op(inst) & 0x07)
+ {
+ case 0:
+ op = rtype_funct(inst);
+ switch (op)
+ {
+ case 8: /* JR */
+ case 9: /* JALR */
+ rn = rtype_rs(inst);
+
+ rx = ptrace(PTRACE_PEEKUSER,proc->pid, rn, 0);
+ newpc[nr++] = rx;
+ break;
+ default:
+ case 12: /* SYSCALL */
+ newpc[nr++] = pc + 4;
+ break;
+ }
+ break;
+ case 1:
+ op = itype_rt(inst);
+ switch (op)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 16:
+ case 17:
+ case 18:
+ case 19:
+ newpc[nr++] = pc + 8;
+ newpc[nr++] = pc + 4 +
+ mips32_relative_offset(inst);
+ break;
+ default:
+ newpc[nr++] = pc + 4;
+ break;
+ }
+ break;
+ case 2: /* J */
+ case 3: /* JAL */
+ rx = jtype_target(inst) << 2;
+ /* Upper four bits get never changed... */
+ newpc[nr++] = rx + ((pc + 4) & ~0x0fffffff);
+ break;
+ case 4: /* BEQ */
+ if (itype_rs(inst) == itype_rt(inst)) {
+ /* Compare the same reg for equality, always
+ * follow the branch. */
+ newpc[nr++] = pc + 4 +
+ mips32_relative_offset(inst);
+ break;
+ }
+ /* Fall through. */
+ default:
+ case 5:
+ case 6:
+ case 7:
+ /* Step over the branch. */
+ newpc[nr++] = pc + 8;
+ newpc[nr++] = pc + mips32_relative_offset(inst) + 4;
+ break;
+ }
+ }
+ if (nr <= 0 || nr > 2)
+ goto fail;
+ if (nr == 2) {
+ if (newpc[1] == 0)
+ goto fail;
+ }
+ if (newpc[0] == 0)
+ goto fail;
+
+ assert(nr == 1 || nr == 2);
+ return nr;
+
+fail:
+ printf("nr=%d pc=%x\n", nr, pc);
+ printf("pc=%x %x\n", newpc[0], newpc[1]);
+ return 0;
+}
+
+int
+arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
+ int (*add_cb)(void *addr, void *data),
+ void *add_cb_data)
+{
+ uint32_t pc = (uint32_t) get_instruction_pointer(proc);
+ uint32_t newpcs[2];
+ int nr;
+
+ nr = mips_next_pcs(proc, pc, newpcs);
+
+ while (nr-- > 0) {
+ arch_addr_t baddr = (arch_addr_t) newpcs[nr];
+ /* Not sure what to do here. We've already got a bp? */
+ if (dict_find_entry(proc->leader->breakpoints, baddr) != NULL) {
+ fprintf(stderr, "skip %p %p\n", baddr, add_cb_data);
+ continue;
+ }
+
+ if (add_cb(baddr, add_cb_data) < 0)
+ return -1;
+ }
+
+ ptrace(PTRACE_SYSCALL, proc->pid, 0, 0);
+ return 0;
+}
+
/**
\param type Function/syscall call or return.
\param proc The process that had an event.
@@ -117,51 +317,61 @@ I'm not doing any floating point support here.
*/
long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
+gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info)
+{
long ret;
+ long addr;
debug(2,"type %d arg %d",type,arg_num);
- if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL){
+ if (arg_num == -1) {
+ if(type == LT_TOF_FUNCTIONR) {
+ return ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
+ }
+ if (type == LT_TOF_SYSCALLR) {
+ unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
+ unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
+ if(!a3){
+ return v0;
+ }
+ return -1;
+ }
+ }
+ if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL) {
+ /* o32: float args are in f12 and f14 */
+ if ((info->type == ARGTYPE_FLOAT) && (arg_num < 2)) {
+ ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_fpr0+12+arg_num*2,0);
+ debug(2,"ret = %#lx",ret);
+ return ret;
+ }
if(arg_num <4){
ret=ptrace(PTRACE_PEEKUSER,proc->pid,off_a0+arg_num,0);
debug(2,"ret = %#lx",ret);
return ret;
} else {
- // If we need this, I think we can look at [sp+16] for arg_num==4.
- CP;
- return 0;
+ /* not sure it's going to work for something else than syscall */
+ addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
+ if (addr == -1) {
+ debug(2,"ret = %#lx",addr);
+ return addr;
+ }
+ ret = addr + 4*arg_num;
+ ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
+ debug(2,"ret = %#lx",ret);
+ return ret;
}
}
- if(arg_num>=0){
- fprintf(stderr,"args on return?");
- }
- if(type == LT_TOF_FUNCTIONR) {
- return ptrace(PTRACE_PEEKUSER,proc->pid,off_v0,0);
- }
- if (type == LT_TOF_SYSCALLR) {
- unsigned a3=ptrace(PTRACE_PEEKUSER, proc->pid,off_a3,0);
- unsigned v0=ptrace(PTRACE_PEEKUSER, proc->pid,off_v0,0);
- if(!a3){
- return v0;
+ if (type == LT_TOF_FUNCTIONR || type == LT_TOF_SYSCALLR){
+ addr=ptrace(PTRACE_PEEKUSER,proc->pid,off_sp,0);
+ if (addr == -1) {
+ debug(2,"ret = %#lx",addr);
+ return addr;
}
- return -1;
+ ret = addr + 4*arg_num;
+ ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
+ debug(2,"ret = %#lx",ret);
+ return ret;
}
fprintf(stderr, "gimme_arg called with wrong arguments\n");
return 0;
}
-/**
- \param type Type of call/return
- \param proc Process to work with.
-
- Called by \c output_left(), which is called on a syscall or
- function.
-
- The other architectures stub this out, but seems to be the place to
- stash off the arguments on a call so we have them on the return.
-
-*/
-void
-save_register_args(enum tof type, Process *proc) {
-}
-
/**@}*/
diff --git a/sysdeps/linux-gnu/mksignalent b/sysdeps/linux-gnu/mksignalent
index 316d81f..b78b692 100755
--- a/sysdeps/linux-gnu/mksignalent
+++ b/sysdeps/linux-gnu/mksignalent
@@ -1,4 +1,21 @@
#!/usr/bin/awk -f
+# This file is part of ltrace.
+# Copyright (C) 1999 Juan Cespedes
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
# hack expression to generate arch/signalent.h from <asm/signal.h>
# It reads from stdin and writes to stdout
diff --git a/sysdeps/linux-gnu/mksyscallent b/sysdeps/linux-gnu/mksyscallent
index e0c3ec7..615ff06 100755
--- a/sysdeps/linux-gnu/mksyscallent
+++ b/sysdeps/linux-gnu/mksyscallent
@@ -1,4 +1,22 @@
#!/usr/bin/awk -f
+# This file is part of ltrace.
+# Copyright (C) 2006 Ian Wienand
+# Copyright (C) 1999 Juan Cespedes
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
# hack expression to generate arch/syscallent.h from <asm/unistd.h>
# It reads from stdin and writes to stdout
diff --git a/sysdeps/linux-gnu/mksyscallent_s390 b/sysdeps/linux-gnu/mksyscallent_s390
index 73416d9..1964d14 100644
--- a/sysdeps/linux-gnu/mksyscallent_s390
+++ b/sysdeps/linux-gnu/mksyscallent_s390
@@ -1,4 +1,22 @@
#!/usr/bin/perl
+# This file is part of ltrace.
+# Copyright (C) 2006 Heiko Carstens, IBM Corporation
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
#
# Generate syscall table for s390/s390x
#
diff --git a/sysdeps/linux-gnu/os.h b/sysdeps/linux-gnu/os.h
new file mode 100644
index 0000000..62bf38b
--- /dev/null
+++ b/sysdeps/linux-gnu/os.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define OS_HAVE_PROCESS_DATA
+struct os_process_data {
+ arch_addr_t debug_addr;
+ int debug_state;
+};
diff --git a/sysdeps/linux-gnu/ppc/Makefile b/sysdeps/linux-gnu/ppc/Makefile
deleted file mode 100644
index 60d7531..0000000
--- a/sysdeps/linux-gnu/ppc/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
-
diff --git a/sysdeps/linux-gnu/ppc/Makefile.am b/sysdeps/linux-gnu/ppc/Makefile.am
new file mode 100644
index 0000000..2239ae3
--- /dev/null
+++ b/sysdeps/linux-gnu/ppc/Makefile.am
@@ -0,0 +1,36 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ insn.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/ppc/Makefile.in b/sysdeps/linux-gnu/ppc/Makefile.in
new file mode 100644
index 0000000..bcc9d84
--- /dev/null
+++ b/sysdeps/linux-gnu/ppc/Makefile.in
@@ -0,0 +1,531 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/ppc
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo fetch.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ insn.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/ppc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/ppc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/ppc/arch.h b/sysdeps/linux-gnu/ppc/arch.h
index 711b4a3..fb8768a 100644
--- a/sysdeps/linux-gnu/ppc/arch.h
+++ b/sysdeps/linux-gnu/ppc/arch.h
@@ -1,3 +1,29 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata
+ * Copyright (C) 2006 Paul Gilliam
+ * Copyright (C) 2002,2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef LTRACE_PPC_ARCH_H
+#define LTRACE_PPC_ARCH_H
+
+#include <gelf.h>
+
#define BREAKPOINT_VALUE { 0x7f, 0xe0, 0x00, 0x08 }
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 0
@@ -11,14 +37,72 @@
#define ARCH_SUPPORTS_OPD
#endif
-#define PLT_REINITALISATION_BP "_start"
+#define ARCH_HAVE_ATOMIC_SINGLESTEP
+#define ARCH_HAVE_ADD_PLT_ENTRY
+#define ARCH_HAVE_TRANSLATE_ADDRESS
+#define ARCH_HAVE_DYNLINK_DONE
+#define ARCH_HAVE_FETCH_ARG
+#define ARCH_ENDIAN_BIG
+#define ARCH_HAVE_SIZEOF
+#define ARCH_HAVE_ALIGNOF
-/* Start of arch-specific functions. */
-#define ARCH_HAVE_UMOVELONG
+struct library_symbol;
-#define PPC_NOP { 0x60, 0x00, 0x00, 0x00 }
-#define PPC_NOP_LENGTH 4
+#define ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+ GElf_Addr plt_stub_vma;
+ struct library_symbol *stubs;
+ Elf_Data *opd_data;
+ GElf_Addr opd_base;
+ GElf_Xword opd_size;
+ int secure_plt;
+};
-#if (PPC_NOP_LENGTH != BREAKPOINT_LENGTH)
-#error "Length of the breakpoint value not equal to the length of a nop instruction"
-#endif
+#define ARCH_HAVE_LIBRARY_DATA
+struct arch_library_data {
+ GElf_Addr pltgot_addr;
+ int bss_plt_prelinked;
+};
+
+enum ppc64_plt_type {
+ /* Either a non-PLT symbol, or PPC32 symbol. */
+ PPC_DEFAULT = 0,
+
+ /* PPC64 STUB, never resolved. */
+ PPC64_PLT_STUB,
+
+ /* Unresolved PLT symbol (.plt contains PLT address). */
+ PPC_PLT_UNRESOLVED,
+
+ /* Resolved PLT symbol. The corresponding .plt slot contained
+ * target address, which was changed to the address of
+ * corresponding PLT entry. The original is now saved in
+ * RESOLVED_VALUE. */
+ PPC_PLT_RESOLVED,
+};
+
+#define ARCH_HAVE_LIBRARY_SYMBOL_DATA
+struct arch_library_symbol_data {
+ enum ppc64_plt_type type;
+ GElf_Addr resolved_value;
+
+ /* Address of corresponding slot in .plt. */
+ GElf_Addr plt_slot_addr;
+};
+
+#define ARCH_HAVE_BREAKPOINT_DATA
+struct arch_breakpoint_data {
+ /* We need this just for arch_breakpoint_init. */
+};
+
+#define ARCH_HAVE_PROCESS_DATA
+struct arch_process_data {
+ /* Breakpoint that hits when the dynamic linker is about to
+ * update a .plt slot. NULL before that address is known. */
+ struct breakpoint *dl_plt_update_bp;
+
+ /* PLT update breakpoint looks here for the handler. */
+ struct process_stopping_handler *handler;
+};
+
+#endif /* LTRACE_PPC_ARCH_H */
diff --git a/sysdeps/linux-gnu/ppc/fetch.c b/sysdeps/linux-gnu/ppc/fetch.c
new file mode 100644
index 0000000..9963a1e
--- /dev/null
+++ b/sysdeps/linux-gnu/ppc/fetch.c
@@ -0,0 +1,436 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ucontext.h>
+
+#include "backend.h"
+#include "fetch.h"
+#include "type.h"
+#include "ptrace.h"
+#include "proc.h"
+#include "value.h"
+
+static int allocate_gpr(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep);
+
+/* Floating point registers have the same width on 32-bit as well as
+ * 64-bit PPC, but <ucontext.h> presents a different API depending on
+ * whether ltrace is PPC32 or PPC64.
+ *
+ * This is PPC64 definition. The PPC32 is simply an array of 33
+ * doubles, and doesn't contain the terminating pad. Both seem
+ * compatible enough. */
+struct fpregs_t
+{
+ double fpregs[32];
+ double fpscr;
+ unsigned int _pad[2];
+};
+
+typedef uint32_t gregs32_t[48];
+typedef uint64_t gregs64_t[48];
+
+struct fetch_context {
+ arch_addr_t stack_pointer;
+ int greg;
+ int freg;
+ int ret_struct;
+
+ union {
+ gregs32_t r32;
+ gregs64_t r64;
+ } regs;
+ struct fpregs_t fpregs;
+
+};
+
+static int
+fetch_context_init(struct Process *proc, struct fetch_context *context)
+{
+ context->greg = 3;
+ context->freg = 1;
+
+ if (proc->e_machine == EM_PPC)
+ context->stack_pointer = proc->stack_pointer + 8;
+ else
+ context->stack_pointer = proc->stack_pointer + 112;
+
+ /* When ltrace is 64-bit, we might use PTRACE_GETREGS to
+ * obtain 64-bit as well as 32-bit registers. But if we do it
+ * this way, 32-bit ltrace can obtain 64-bit registers.
+ *
+ * XXX this direction is not supported as of this writing, but
+ * should be eventually. */
+ if (proc->e_machine == EM_PPC64) {
+ if (ptrace(PTRACE_GETREGS64, proc->pid, 0,
+ &context->regs.r64) < 0)
+ return -1;
+ } else {
+#ifdef __powerpc64__
+ if (ptrace(PTRACE_GETREGS, proc->pid, 0,
+ &context->regs.r64) < 0)
+ return -1;
+ unsigned i;
+ for (i = 0; i < sizeof(context->regs.r64)/8; ++i)
+ context->regs.r32[i] = context->regs.r64[i];
+#else
+ if (ptrace(PTRACE_GETREGS, proc->pid, 0,
+ &context->regs.r32) < 0)
+ return -1;
+#endif
+ }
+
+ if (ptrace(PTRACE_GETFPREGS, proc->pid, 0, &context->fpregs) < 0)
+ return -1;
+
+ return 0;
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *context = malloc(sizeof(*context));
+ if (context == NULL
+ || fetch_context_init(proc, context) < 0) {
+ free(context);
+ return NULL;
+ }
+
+ /* Aggregates or unions of any length, and character strings
+ * of length longer than 8 bytes, will be returned in a
+ * storage buffer allocated by the caller. The caller will
+ * pass the address of this buffer as a hidden first argument
+ * in r3, causing the first explicit argument to be passed in
+ * r4. */
+ context->ret_struct = ret_info->type == ARGTYPE_STRUCT;
+ if (context->ret_struct)
+ context->greg++;
+
+ return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc,
+ struct fetch_context *context)
+{
+ struct fetch_context *clone = malloc(sizeof(*context));
+ if (clone == NULL)
+ return NULL;
+ *clone = *context;
+ return clone;
+}
+
+static int
+allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ size_t a = type_alignof(proc, info);
+ size_t off = 0;
+ if (proc->e_machine == EM_PPC && a < 4)
+ a = 4;
+ else if (proc->e_machine == EM_PPC64 && a < 8)
+ a = 8;
+
+ /* XXX Remove the two double casts when arch_addr_t
+ * becomes integral type. */
+ uintptr_t tmp = align((uint64_t)(uintptr_t)ctx->stack_pointer, a);
+ ctx->stack_pointer = (arch_addr_t)tmp;
+
+ if (valuep != NULL)
+ value_in_inferior(valuep, ctx->stack_pointer + off);
+ ctx->stack_pointer += sz;
+
+ return 0;
+}
+
+static uint64_t
+read_gpr(struct fetch_context *ctx, struct Process *proc, int reg_num)
+{
+ if (proc->e_machine == EM_PPC)
+ return ctx->regs.r32[reg_num];
+ else
+ return ctx->regs.r64[reg_num];
+}
+
+/* The support for little endian PowerPC is in upstream Linux and BFD,
+ * and Unix-like Solaris, which we might well support at some point,
+ * runs PowerPC in little endian as well. This code moves SZ-sized
+ * value to the beginning of W-sized BUF regardless of
+ * endian. */
+static void
+align_small_int(unsigned char *buf, size_t w, size_t sz)
+{
+ assert(w == 4 || w == 8);
+ union {
+ uint64_t i64;
+ uint32_t i32;
+ uint16_t i16;
+ uint8_t i8;
+ char buf[0];
+ } u;
+ memcpy(u.buf, buf, w);
+ if (w == 4)
+ u.i64 = u.i32;
+
+ switch (sz) {
+ case 1:
+ u.i8 = u.i64;
+ break;
+ case 2:
+ u.i16 = u.i64;
+ break;
+ case 4:
+ u.i32 = u.i64;
+ case 8:
+ break;
+ }
+
+ memcpy(buf, u.buf, sz);
+}
+
+static int
+allocate_gpr(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ if (ctx->greg > 10)
+ return allocate_stack_slot(ctx, proc, info, valuep);
+
+ int reg_num = ctx->greg++;
+ if (valuep == NULL)
+ return 0;
+
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+ assert(sz == 1 || sz == 2 || sz == 4 || sz == 8);
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ union {
+ uint64_t i64;
+ unsigned char buf[0];
+ } u;
+
+ u.i64 = read_gpr(ctx, proc, reg_num);
+ if (proc->e_machine == EM_PPC)
+ align_small_int(u.buf, 8, sz);
+ memcpy(value_get_raw_data(valuep), u.buf, sz);
+ return 0;
+}
+
+static int
+allocate_float(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ int pool = proc->e_machine == EM_PPC64 ? 13 : 8;
+ if (ctx->freg <= pool) {
+ union {
+ double d;
+ float f;
+ char buf[0];
+ } u = { .d = ctx->fpregs.fpregs[ctx->freg] };
+
+ ctx->freg++;
+ if (proc->e_machine == EM_PPC64)
+ allocate_gpr(ctx, proc, info, NULL);
+
+ size_t sz = sizeof(double);
+ if (info->type == ARGTYPE_FLOAT) {
+ sz = sizeof(float);
+ u.f = (float)u.d;
+ }
+
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ memcpy(value_get_raw_data(valuep), u.buf, sz);
+ return 0;
+ }
+ return allocate_stack_slot(ctx, proc, info, valuep);
+}
+
+static int
+allocate_argument(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ /* Floating point types and void are handled specially. */
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ value_set_word(valuep, 0);
+ return 0;
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ return allocate_float(ctx, proc, info, valuep);
+
+ case ARGTYPE_STRUCT:
+ if (proc->e_machine == EM_PPC) {
+ if (value_pass_by_reference(valuep) < 0)
+ return -1;
+ } else {
+ /* PPC64: Fixed size aggregates and unions passed by
+ * value are mapped to as many doublewords of the
+ * parameter save area as the value uses in memory.
+ * [...] The first eight doublewords mapped to the
+ * parameter save area correspond to the registers r3
+ * through r10. */
+ }
+ /* fall through */
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ break;
+
+ case ARGTYPE_ARRAY:
+ /* Arrays decay into pointers. XXX Fortran? */
+ default:
+ assert(info->type != info->type);
+ abort();
+ }
+
+ unsigned width = proc->e_machine == EM_PPC64 ? 8 : 4;
+
+ /* For other cases (integral types and aggregates), read the
+ * eightbytes comprising the data. */
+ size_t sz = type_sizeof(proc, valuep->type);
+ if (sz == (size_t)-1)
+ return -1;
+ size_t slots = (sz + width - 1) / width; /* Round up. */
+ unsigned char *buf = value_reserve(valuep, slots * width);
+ if (buf == NULL)
+ return -1;
+ struct arg_type_info *long_info = type_get_simple(ARGTYPE_LONG);
+
+ unsigned char *ptr = buf;
+ while (slots-- > 0) {
+ struct value val;
+ value_init(&val, proc, NULL, long_info, 0);
+
+ /* Floating point registers [...] are used [...] to
+ pass [...] one member aggregates passed by value
+ containing a floating point value[.] Note that for
+ one member aggregates, "containing" extends to
+ aggregates within aggregates ad infinitum. */
+ int rc;
+ struct arg_type_info *fp_info
+ = type_get_fp_equivalent(valuep->type);
+ if (fp_info != NULL)
+ rc = allocate_float(ctx, proc, fp_info, &val);
+ else
+ rc = allocate_gpr(ctx, proc, long_info, &val);
+
+ if (rc >= 0) {
+ memcpy(ptr, value_get_data(&val, NULL), width);
+ ptr += width;
+ }
+ value_destroy(&val);
+
+ /* Bail out if we failed or if we are dealing with
+ * FP-equivalent. Those don't need the adjustments
+ * made below. */
+ if (rc < 0 || fp_info != NULL)
+ return rc;
+ }
+
+ /* Small values need post-processing. */
+ if (sz < width) {
+ switch (info->type) {
+ default:
+ abort();
+
+ /* Simple integer types (char, short, int, long, enum)
+ * are mapped to a single doubleword. Values shorter
+ * than a doubleword are sign or zero extended as
+ * necessary. */
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_UINT:
+ align_small_int(buf, width, sz);
+ break;
+
+ /* Single precision floating point values are mapped
+ * to the second word in a single doubleword.
+ *
+ * An aggregate or union smaller than one doubleword
+ * in size is padded so that it appears in the least
+ * significant bits of the doubleword. */
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ memmove(buf, buf + width - sz, sz);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
+ struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ return allocate_argument(ctx, proc, info, valuep);
+}
+
+int
+arch_fetch_retval(struct fetch_context *ctx, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (ctx->ret_struct) {
+ assert(info->type == ARGTYPE_STRUCT);
+
+ uint64_t addr = read_gpr(ctx, proc, 3);
+ value_init(valuep, proc, NULL, info, 0);
+
+ valuep->where = VAL_LOC_INFERIOR;
+ /* XXX Remove the double cast when arch_addr_t
+ * becomes integral type. */
+ valuep->u.address = (arch_addr_t)(uintptr_t)addr;
+ return 0;
+ }
+
+ if (fetch_context_init(proc, ctx) < 0)
+ return -1;
+ return allocate_argument(ctx, proc, info, valuep);
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+ free(context);
+}
diff --git a/sysdeps/linux-gnu/ppc/insn.h b/sysdeps/linux-gnu/ppc/insn.h
new file mode 100644
index 0000000..cd94b5e
--- /dev/null
+++ b/sysdeps/linux-gnu/ppc/insn.h
@@ -0,0 +1,45 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/* Instruction masks used during single-stepping of atomic
+ * sequences. This was lifted from GDB. */
+#define LWARX_MASK 0xfc0007fe
+#define LWARX_INSTRUCTION 0x7c000028
+#define LDARX_INSTRUCTION 0x7c0000A8
+#define STWCX_MASK 0xfc0007ff
+#define STWCX_INSTRUCTION 0x7c00012d
+#define STDCX_INSTRUCTION 0x7c0001ad
+#define BRANCH_MASK 0xfc000000
+#define BC_MASK 0xfc000000
+#define BC_INSN 0x40000000
+#define B_INSN 0x48000000
+
+static inline arch_addr_t
+ppc_branch_dest(arch_addr_t addr, uint32_t insn)
+{
+ int immediate = ((insn & 0xfffc) ^ 0x8000) - 0x8000;
+ int absolute = insn & 2;
+
+ /* XXX drop the following double casts. */
+ if (absolute)
+ return (arch_addr_t)(uintptr_t)immediate;
+ else
+ return addr + (uintptr_t)immediate;
+}
diff --git a/sysdeps/linux-gnu/ppc/plt.c b/sysdeps/linux-gnu/ppc/plt.c
index 31830fb..f83f087 100644
--- a/sysdeps/linux-gnu/ppc/plt.c
+++ b/sysdeps/linux-gnu/ppc/plt.c
@@ -1,54 +1,1038 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Paul Gilliam
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
+#include <sys/ptrace.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <assert.h>
+#include <string.h>
+
+#include "proc.h"
#include "common.h"
+#include "insn.h"
+#include "library.h"
+#include "breakpoint.h"
+#include "linux-gnu/trace.h"
+#include "backend.h"
+
+/* There are two PLT types on 32-bit PPC: old-style, BSS PLT, and
+ * new-style "secure" PLT. We can tell one from the other by the
+ * flags on the .plt section. If it's +X (executable), it's BSS PLT,
+ * otherwise it's secure.
+ *
+ * BSS PLT works the same way as most architectures: the .plt section
+ * contains trampolines and we put breakpoints to those. If not
+ * prelinked, .plt contains zeroes, and dynamic linker fills in the
+ * initial set of trampolines, which means that we need to delay
+ * enabling breakpoints until after binary entry point is hit.
+ * Additionally, after first call, dynamic linker updates .plt with
+ * branch to resolved address. That means that on first hit, we must
+ * do something similar to the PPC64 gambit described below.
+ *
+ * With secure PLT, the .plt section doesn't contain instructions but
+ * addresses. The real PLT table is stored in .text. Addresses of
+ * those PLT entries can be computed, and apart from the fact that
+ * they are in .text, they are ordinary PLT entries.
+ *
+ * 64-bit PPC is more involved. Program linker creates for each
+ * library call a _stub_ symbol named xxxxxxxx.plt_call.<callee>
+ * (where xxxxxxxx is a hexadecimal number). That stub does the call
+ * dispatch: it loads an address of a function to call from the
+ * section .plt, and branches. PLT entries themselves are essentially
+ * a curried call to the resolver. When the symbol is resolved, the
+ * resolver updates the value stored in .plt, and the next time
+ * around, the stub calls the library function directly. So we make
+ * at most one trip (none if the binary is prelinked) through each PLT
+ * entry, and correspondingly that is useless as a breakpoint site.
+ *
+ * Note the three confusing terms: stubs (that play the role of PLT
+ * entries), PLT entries, .plt section.
+ *
+ * We first check symbol tables and see if we happen to have stub
+ * symbols available. If yes we just put breakpoints to those, and
+ * treat them as usual breakpoints. The only tricky part is realizing
+ * that there can be more than one breakpoint per symbol.
+ *
+ * The case that we don't have the stub symbols available is harder.
+ * The following scheme uses two kinds of PLT breakpoints: unresolved
+ * and resolved (to some address). When the process starts (or when
+ * we attach), we distribute unresolved PLT breakpoints to the PLT
+ * entries (not stubs). Then we look in .plt, and for each entry
+ * whose value is different than the corresponding PLT entry address,
+ * we assume it was already resolved, and convert the breakpoint to
+ * resolved. We also rewrite the resolved value in .plt back to the
+ * PLT address.
+ *
+ * When a PLT entry hits a resolved breakpoint (which happens because
+ * we rewrite .plt with the original unresolved addresses), we move
+ * the instruction pointer to the corresponding address and continue
+ * the process as if nothing happened.
+ *
+ * When unresolved PLT entry is called for the first time, we need to
+ * catch the new value that the resolver will write to a .plt slot.
+ * We also need to prevent another thread from racing through and
+ * taking the branch without ltrace noticing. So when unresolved PLT
+ * entry hits, we have to stop all threads. We then single-step
+ * through the resolver, until the .plt slot changes. When it does,
+ * we treat it the same way as above: convert the PLT breakpoint to
+ * resolved, and rewrite the .plt value back to PLT address. We then
+ * start all threads again.
+ *
+ * As an optimization, we remember the address where the address was
+ * resolved, and put a breakpoint there. The next time around (when
+ * the next PLT entry is to be resolved), instead of single-stepping
+ * through half the dynamic linker, we just let the thread run and hit
+ * this breakpoint. When it hits, we know the PLT entry was resolved.
+ *
+ * XXX TODO If we have hardware watch point, we might put a read watch
+ * on .plt slot, and discover the offenders this way. I don't know
+ * the details, but I assume at most a handful (like, one or two, if
+ * available at all) addresses may be watched at a time, and thus this
+ * would be used as an amendment of the above rather than full-on
+ * solution to PLT tracing on PPC.
+ */
+
+#define PPC_PLT_STUB_SIZE 16
+#define PPC64_PLT_STUB_SIZE 8 //xxx
+
+static inline int
+host_powerpc64()
+{
+#ifdef __powerpc64__
+ return 1;
+#else
+ return 0;
+#endif
+}
+
+int
+read_target_4(struct Process *proc, arch_addr_t addr, uint32_t *lp)
+{
+ unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ if (l == -1UL && errno)
+ return -1;
+#ifdef __powerpc64__
+ l >>= 32;
+#endif
+ *lp = l;
+ return 0;
+}
+
+static int
+read_target_8(struct Process *proc, arch_addr_t addr, uint64_t *lp)
+{
+ unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ if (l == -1UL && errno)
+ return -1;
+ if (host_powerpc64()) {
+ *lp = l;
+ } else {
+ unsigned long l2 = ptrace(PTRACE_PEEKTEXT, proc->pid,
+ addr + 4, 0);
+ if (l2 == -1UL && errno)
+ return -1;
+ *lp = ((uint64_t)l << 32) | l2;
+ }
+ return 0;
+}
+
+int
+read_target_long(struct Process *proc, arch_addr_t addr, uint64_t *lp)
+{
+ if (proc->e_machine == EM_PPC) {
+ uint32_t w;
+ int ret = read_target_4(proc, addr, &w);
+ if (ret >= 0)
+ *lp = (uint64_t)w;
+ return ret;
+ } else {
+ return read_target_8(proc, addr, lp);
+ }
+}
+
+static void
+mark_as_resolved(struct library_symbol *libsym, GElf_Addr value)
+{
+ libsym->arch.type = PPC_PLT_RESOLVED;
+ libsym->arch.resolved_value = value;
+}
+
+void
+arch_dynlink_done(struct Process *proc)
+{
+ /* On PPC32 with BSS PLT, we need to enable delayed symbols. */
+ struct library_symbol *libsym = NULL;
+ while ((libsym = proc_each_symbol(proc, libsym,
+ library_symbol_delayed_cb, NULL))) {
+ if (read_target_8(proc, libsym->enter_addr,
+ &libsym->arch.resolved_value) < 0) {
+ fprintf(stderr,
+ "couldn't read PLT value for %s(%p): %s\n",
+ libsym->name, libsym->enter_addr,
+ strerror(errno));
+ return;
+ }
+
+ /* arch_dynlink_done is called on attach as well. In
+ * that case some slots will have been resolved
+ * already. Unresolved PLT looks like this:
+ *
+ * <sleep@plt>: li r11,0
+ * <sleep@plt+4>: b "resolve"
+ *
+ * "resolve" is another address in PLTGOT (the same
+ * block that all the PLT slots are it). When
+ * resolved, it looks either this way:
+ *
+ * <sleep@plt>: b 0xfea88d0 <sleep>
+ *
+ * Which is easy to detect. It can also look this
+ * way:
+ *
+ * <sleep@plt>: li r11,0
+ * <sleep@plt+4>: b "dispatch"
+ *
+ * The "dispatch" address lies in PLTGOT as well. In
+ * current GNU toolchain, "dispatch" address is the
+ * same as PLTGOT address. We rely on this to figure
+ * out whether the address is resolved or not. */
+ uint32_t insn1 = libsym->arch.resolved_value >> 32;
+ uint32_t insn2 = (uint32_t)libsym->arch.resolved_value;
+ if ((insn1 & BRANCH_MASK) == B_INSN
+ || ((insn2 & BRANCH_MASK) == B_INSN
+ /* XXX double cast */
+ && (ppc_branch_dest(libsym->enter_addr + 4, insn2)
+ == (void*)(long)libsym->lib->arch.pltgot_addr)))
+ mark_as_resolved(libsym, libsym->arch.resolved_value);
+
+ if (proc_activate_delayed_symbol(proc, libsym) < 0)
+ return;
+
+ /* XXX double cast */
+ libsym->arch.plt_slot_addr
+ = (GElf_Addr)(uintptr_t)libsym->enter_addr;
+ }
+}
GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- return rela->r_offset;
+arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela *rela)
+{
+ if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
+ assert(lte->arch.plt_stub_vma != 0);
+ return lte->arch.plt_stub_vma + PPC_PLT_STUB_SIZE * ndx;
+
+ } else if (lte->ehdr.e_machine == EM_PPC) {
+ return rela->r_offset;
+
+ } else {
+ /* If we get here, we don't have stub symbols. In
+ * that case we put brakpoints to PLT entries the same
+ * as the PPC32 secure PLT case does. */
+ assert(lte->arch.plt_stub_vma != 0);
+ return lte->arch.plt_stub_vma + PPC64_PLT_STUB_SIZE * ndx;
+ }
+}
+
+/* This entry point is called when ltelf is not available
+ * anymore--during runtime. At that point we don't have to concern
+ * ourselves with bias, as the values in OPD have been resolved
+ * already. */
+int
+arch_translate_address_dyn(struct Process *proc,
+ arch_addr_t addr, arch_addr_t *ret)
+{
+ if (proc->e_machine == EM_PPC64) {
+ uint64_t value;
+ if (read_target_8(proc, addr, &value) < 0) {
+ fprintf(stderr,
+ "dynamic .opd translation of %p: %s\n",
+ addr, strerror(errno));
+ return -1;
+ }
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ *ret = (arch_addr_t)(uintptr_t)value;
+ return 0;
+ }
+
+ *ret = addr;
+ return 0;
+}
+
+int
+arch_translate_address(struct ltelf *lte,
+ arch_addr_t addr, arch_addr_t *ret)
+{
+ if (lte->ehdr.e_machine == EM_PPC64) {
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ GElf_Xword offset
+ = (GElf_Addr)(uintptr_t)addr - lte->arch.opd_base;
+ uint64_t value;
+ if (elf_read_u64(lte->arch.opd_data, offset, &value) < 0) {
+ fprintf(stderr, "static .opd translation of %p: %s\n",
+ addr, elf_errmsg(-1));
+ return -1;
+ }
+ *ret = (arch_addr_t)(uintptr_t)(value + lte->bias);
+ return 0;
+ }
+
+ *ret = addr;
+ return 0;
+}
+
+static int
+load_opd_data(struct ltelf *lte, struct library *lib)
+{
+ Elf_Scn *sec;
+ GElf_Shdr shdr;
+ if (elf_get_section_named(lte, ".opd", &sec, &shdr) < 0) {
+ fail:
+ fprintf(stderr, "couldn't find .opd data\n");
+ return -1;
+ }
+
+ lte->arch.opd_data = elf_rawdata(sec, NULL);
+ if (lte->arch.opd_data == NULL)
+ goto fail;
+
+ lte->arch.opd_base = shdr.sh_addr + lte->bias;
+ lte->arch.opd_size = shdr.sh_size;
+
+ return 0;
}
void *
-sym2addr(Process *proc, struct library_symbol *sym) {
- void *addr = sym->enter_addr;
- long pt_ret;
+sym2addr(struct Process *proc, struct library_symbol *sym)
+{
+ return sym->enter_addr;
+}
- debug(3, 0);
+static GElf_Addr
+get_glink_vma(struct ltelf *lte, GElf_Addr ppcgot, Elf_Data *plt_data)
+{
+ Elf_Scn *ppcgot_sec = NULL;
+ GElf_Shdr ppcgot_shdr;
+ if (ppcgot != 0
+ && elf_get_section_covering(lte, ppcgot,
+ &ppcgot_sec, &ppcgot_shdr) < 0)
+ fprintf(stderr,
+ "DT_PPC_GOT=%#"PRIx64", but no such section found\n",
+ ppcgot);
- if (sym->plt_type != LS_TOPLT_POINT) {
- return addr;
+ if (ppcgot_sec != NULL) {
+ Elf_Data *data = elf_loaddata(ppcgot_sec, &ppcgot_shdr);
+ if (data == NULL || data->d_size < 8 ) {
+ fprintf(stderr, "couldn't read GOT data\n");
+ } else {
+ // where PPCGOT begins in .got
+ size_t offset = ppcgot - ppcgot_shdr.sh_addr;
+ assert(offset % 4 == 0);
+ uint32_t glink_vma;
+ if (elf_read_u32(data, offset + 4, &glink_vma) < 0) {
+ fprintf(stderr, "couldn't read glink VMA"
+ " address at %zd@GOT\n", offset);
+ return 0;
+ }
+ if (glink_vma != 0) {
+ debug(1, "PPC GOT glink_vma address: %#" PRIx32,
+ glink_vma);
+ return (GElf_Addr)glink_vma;
+ }
+ }
}
- if (proc->pid == 0) {
+ if (plt_data != NULL) {
+ uint32_t glink_vma;
+ if (elf_read_u32(plt_data, 0, &glink_vma) < 0) {
+ fprintf(stderr, "couldn't read glink VMA address\n");
+ return 0;
+ }
+ debug(1, ".plt glink_vma address: %#" PRIx32, glink_vma);
+ return (GElf_Addr)glink_vma;
+ }
+
+ return 0;
+}
+
+static int
+load_dynamic_entry(struct ltelf *lte, int tag, GElf_Addr *valuep)
+{
+ Elf_Scn *scn;
+ GElf_Shdr shdr;
+ if (elf_get_section_type(lte, SHT_DYNAMIC, &scn, &shdr) < 0
+ || scn == NULL) {
+ fail:
+ fprintf(stderr, "Couldn't get SHT_DYNAMIC: %s\n",
+ elf_errmsg(-1));
+ return -1;
+ }
+
+ Elf_Data *data = elf_loaddata(scn, &shdr);
+ if (data == NULL)
+ goto fail;
+
+ size_t j;
+ for (j = 0; j < shdr.sh_size / shdr.sh_entsize; ++j) {
+ GElf_Dyn dyn;
+ if (gelf_getdyn(data, j, &dyn) == NULL)
+ goto fail;
+
+ if(dyn.d_tag == tag) {
+ *valuep = dyn.d_un.d_ptr;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int
+nonzero_data(Elf_Data *data)
+{
+ /* We are not supposed to get here if there's no PLT. */
+ assert(data != NULL);
+
+ unsigned char *buf = data->d_buf;
+ if (buf == NULL)
return 0;
+
+ size_t i;
+ for (i = 0; i < data->d_size; ++i)
+ if (buf[i] != 0)
+ return 1;
+ return 0;
+}
+
+int
+arch_elf_init(struct ltelf *lte, struct library *lib)
+{
+ if (lte->ehdr.e_machine == EM_PPC64
+ && load_opd_data(lte, lib) < 0)
+ return -1;
+
+ lte->arch.secure_plt = !(lte->plt_flags & SHF_EXECINSTR);
+
+ /* For PPC32 BSS, it is important whether the binary was
+ * prelinked. If .plt section is NODATA, or if it contains
+ * zeroes, then this library is not prelinked, and we need to
+ * delay breakpoints. */
+ if (lte->ehdr.e_machine == EM_PPC && !lte->arch.secure_plt)
+ lib->arch.bss_plt_prelinked = nonzero_data(lte->plt_data);
+ else
+ /* For cases where it's irrelevant, initialize the
+ * value to something conspicuous. */
+ lib->arch.bss_plt_prelinked = -1;
+
+ if (lte->ehdr.e_machine == EM_PPC && lte->arch.secure_plt) {
+ GElf_Addr ppcgot;
+ if (load_dynamic_entry(lte, DT_PPC_GOT, &ppcgot) < 0) {
+ fprintf(stderr, "couldn't find DT_PPC_GOT\n");
+ return -1;
+ }
+ GElf_Addr glink_vma = get_glink_vma(lte, ppcgot, lte->plt_data);
+
+ assert(lte->relplt_size % 12 == 0);
+ size_t count = lte->relplt_size / 12; // size of RELA entry
+ lte->arch.plt_stub_vma = glink_vma
+ - (GElf_Addr)count * PPC_PLT_STUB_SIZE;
+ debug(1, "stub_vma is %#" PRIx64, lte->arch.plt_stub_vma);
+
+ } else if (lte->ehdr.e_machine == EM_PPC64) {
+ GElf_Addr glink_vma;
+ if (load_dynamic_entry(lte, DT_PPC64_GLINK, &glink_vma) < 0) {
+ fprintf(stderr, "couldn't find DT_PPC64_GLINK\n");
+ return -1;
+ }
+
+ /* The first glink stub starts at offset 32. */
+ lte->arch.plt_stub_vma = glink_vma + 32;
+
+ } else {
+ /* By exhaustion--PPC32 BSS. */
+ if (load_dynamic_entry(lte, DT_PLTGOT,
+ &lib->arch.pltgot_addr) < 0) {
+ fprintf(stderr, "couldn't find DT_PLTGOT\n");
+ return -1;
+ }
+ }
+
+ /* On PPC64, look for stub symbols in symbol table. These are
+ * called: xxxxxxxx.plt_call.callee_name@version+addend. */
+ if (lte->ehdr.e_machine == EM_PPC64
+ && lte->symtab != NULL && lte->strtab != NULL) {
+
+ /* N.B. We can't simply skip the symbols that we fail
+ * to read or malloc. There may be more than one stub
+ * per symbol name, and if we failed in one but
+ * succeeded in another, the PLT enabling code would
+ * have no way to tell that something is missing. We
+ * could work around that, of course, but it doesn't
+ * seem worth the trouble. So if anything fails, we
+ * just pretend that we don't have stub symbols at
+ * all, as if the binary is stripped. */
+
+ size_t i;
+ for (i = 0; i < lte->symtab_count; ++i) {
+ GElf_Sym sym;
+ if (gelf_getsym(lte->symtab, i, &sym) == NULL) {
+ struct library_symbol *sym, *next;
+ fail:
+ for (sym = lte->arch.stubs; sym != NULL; ) {
+ next = sym->next;
+ library_symbol_destroy(sym);
+ free(sym);
+ sym = next;
+ }
+ lte->arch.stubs = NULL;
+ break;
+ }
+
+ const char *name = lte->strtab + sym.st_name;
+
+#define STUBN ".plt_call."
+ if ((name = strstr(name, STUBN)) == NULL)
+ continue;
+ name += sizeof(STUBN) - 1;
+#undef STUBN
+
+ size_t len;
+ const char *ver = strchr(name, '@');
+ if (ver != NULL) {
+ len = ver - name;
+
+ } else {
+ /* If there is "+" at all, check that
+ * the symbol name ends in "+0". */
+ const char *add = strrchr(name, '+');
+ if (add != NULL) {
+ assert(strcmp(add, "+0") == 0);
+ len = add - name;
+ } else {
+ len = strlen(name);
+ }
+ }
+
+ char *sym_name = strndup(name, len);
+ struct library_symbol *libsym = malloc(sizeof(*libsym));
+ if (sym_name == NULL || libsym == NULL) {
+ fail2:
+ free(sym_name);
+ free(libsym);
+ goto fail;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ arch_addr_t addr = (arch_addr_t)
+ (uintptr_t)sym.st_value + lte->bias;
+ if (library_symbol_init(libsym, addr, sym_name, 1,
+ LS_TOPLT_EXEC) < 0)
+ goto fail2;
+ libsym->arch.type = PPC64_PLT_STUB;
+ libsym->next = lte->arch.stubs;
+ lte->arch.stubs = libsym;
+ }
+ }
+
+ return 0;
+}
+
+static int
+read_plt_slot_value(struct Process *proc, GElf_Addr addr, GElf_Addr *valp)
+{
+ /* On PPC64, we read from .plt, which contains 8 byte
+ * addresses. On PPC32 we read from .plt, which contains 4
+ * byte instructions, but the PLT is two instructions, and
+ * either can change. */
+ uint64_t l;
+ /* XXX double cast. */
+ if (read_target_8(proc, (arch_addr_t)(uintptr_t)addr, &l) < 0) {
+ fprintf(stderr, "ptrace .plt slot value @%#" PRIx64": %s\n",
+ addr, strerror(errno));
+ return -1;
+ }
+
+ *valp = (GElf_Addr)l;
+ return 0;
+}
+
+static int
+unresolve_plt_slot(struct Process *proc, GElf_Addr addr, GElf_Addr value)
+{
+ /* We only modify plt_entry[0], which holds the resolved
+ * address of the routine. We keep the TOC and environment
+ * pointers intact. Hence the only adjustment that we need to
+ * do is to IP. */
+ if (ptrace(PTRACE_POKETEXT, proc->pid, addr, value) < 0) {
+ fprintf(stderr, "failed to unresolve .plt slot: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+enum plt_status
+arch_elf_add_plt_entry(struct Process *proc, struct ltelf *lte,
+ const char *a_name, GElf_Rela *rela, size_t ndx,
+ struct library_symbol **ret)
+{
+ if (lte->ehdr.e_machine == EM_PPC) {
+ if (lte->arch.secure_plt)
+ return plt_default;
+
+ struct library_symbol *libsym = NULL;
+ if (default_elf_add_plt_entry(proc, lte, a_name, rela, ndx,
+ &libsym) < 0)
+ return plt_fail;
+
+ /* On PPC32 with BSS PLT, delay the symbol until
+ * dynamic linker is done. */
+ assert(!libsym->delayed);
+ libsym->delayed = 1;
+
+ *ret = libsym;
+ return plt_ok;
+ }
+
+ /* PPC64. If we have stubs, we return a chain of breakpoint
+ * sites, one for each stub that corresponds to this PLT
+ * entry. */
+ struct library_symbol *chain = NULL;
+ struct library_symbol **symp;
+ for (symp = &lte->arch.stubs; *symp != NULL; ) {
+ struct library_symbol *sym = *symp;
+ if (strcmp(sym->name, a_name) != 0) {
+ symp = &(*symp)->next;
+ continue;
+ }
+
+ /* Re-chain the symbol from stubs to CHAIN. */
+ *symp = sym->next;
+ sym->next = chain;
+ chain = sym;
}
- if (options.debug >= 3) {
- xinfdump(proc->pid, (void *)(((long)addr-32)&0xfffffff0),
- sizeof(void*)*8);
+ if (chain != NULL) {
+ *ret = chain;
+ return plt_ok;
}
- // On a PowerPC-64 system, a plt is three 64-bit words: the first is the
- // 64-bit address of the routine. Before the PLT has been initialized,
- // this will be 0x0. In fact, the symbol table won't have the plt's
- // address even. Ater the PLT has been initialized, but before it has
- // been resolved, the first word will be the address of the function in
- // the dynamic linker that will reslove the PLT. After the PLT is
- // resolved, this will will be the address of the routine whose symbol
- // is in the symbol table.
+ /* We don't have stub symbols. Find corresponding .plt slot,
+ * and check whether it contains the corresponding PLT address
+ * (or 0 if the dynamic linker hasn't run yet). N.B. we don't
+ * want read this from ELF file, but from process image. That
+ * makes a difference if we are attaching to a running
+ * process. */
- // On a PowerPC-32 system, there are two types of PLTs: secure (new) and
- // non-secure (old). For the secure case, the PLT is simply a pointer
- // and we can treat it much as we do for the PowerPC-64 case. For the
- // non-secure case, the PLT is executable code and we can put the
- // break-point right in the PLT.
+ GElf_Addr plt_entry_addr = arch_plt_sym_val(lte, ndx, rela);
+ GElf_Addr plt_slot_addr = rela->r_offset;
+ assert(plt_slot_addr >= lte->plt_addr
+ || plt_slot_addr < lte->plt_addr + lte->plt_size);
- pt_ret = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ GElf_Addr plt_slot_value;
+ if (read_plt_slot_value(proc, plt_slot_addr, &plt_slot_value) < 0)
+ return plt_fail;
+
+ char *name = strdup(a_name);
+ struct library_symbol *libsym = malloc(sizeof(*libsym));
+ if (name == NULL || libsym == NULL) {
+ fprintf(stderr, "allocation for .plt slot: %s\n",
+ strerror(errno));
+ fail:
+ free(name);
+ free(libsym);
+ return plt_fail;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ if (library_symbol_init(libsym,
+ (arch_addr_t)(uintptr_t)plt_entry_addr,
+ name, 1, LS_TOPLT_EXEC) < 0)
+ goto fail;
+ libsym->arch.plt_slot_addr = plt_slot_addr;
+
+ if (plt_slot_value == plt_entry_addr || plt_slot_value == 0) {
+ libsym->arch.type = PPC_PLT_UNRESOLVED;
+ libsym->arch.resolved_value = plt_entry_addr;
- if (proc->mask_32bit) {
- // Assume big-endian.
- addr = (void *)((pt_ret >> 32) & 0xffffffff);
} else {
- addr = (void *)pt_ret;
+ /* Unresolve the .plt slot. If the binary was
+ * prelinked, this makes the code invalid, because in
+ * case of prelinked binary, the dynamic linker
+ * doesn't update .plt[0] and .plt[1] with addresses
+ * of the resover. But we don't care, we will never
+ * need to enter the resolver. That just means that
+ * we have to un-un-resolve this back before we
+ * detach. */
+
+ if (unresolve_plt_slot(proc, plt_slot_addr, plt_entry_addr) < 0) {
+ library_symbol_destroy(libsym);
+ goto fail;
+ }
+ mark_as_resolved(libsym, plt_slot_value);
+ }
+
+ *ret = libsym;
+ return plt_ok;
+}
+
+void
+arch_elf_destroy(struct ltelf *lte)
+{
+ struct library_symbol *sym;
+ for (sym = lte->arch.stubs; sym != NULL; ) {
+ struct library_symbol *next = sym->next;
+ library_symbol_destroy(sym);
+ free(sym);
+ sym = next;
+ }
+}
+
+static void
+dl_plt_update_bp_on_hit(struct breakpoint *bp, struct Process *proc)
+{
+ debug(DEBUG_PROCESS, "pid=%d dl_plt_update_bp_on_hit %s(%p)",
+ proc->pid, breakpoint_name(bp), bp->addr);
+ struct process_stopping_handler *self = proc->arch.handler;
+ assert(self != NULL);
+
+ struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
+ GElf_Addr value;
+ if (read_plt_slot_value(proc, libsym->arch.plt_slot_addr, &value) < 0)
+ return;
+
+ /* On PPC64, we rewrite the slot value. */
+ if (proc->e_machine == EM_PPC64)
+ unresolve_plt_slot(proc, libsym->arch.plt_slot_addr,
+ libsym->arch.resolved_value);
+ /* We mark the breakpoint as resolved on both arches. */
+ mark_as_resolved(libsym, value);
+
+ /* cb_on_all_stopped looks if HANDLER is set to NULL as a way
+ * to check that this was run. It's an error if it
+ * wasn't. */
+ proc->arch.handler = NULL;
+
+ breakpoint_turn_off(bp, proc);
+}
+
+static void
+cb_on_all_stopped(struct process_stopping_handler *self)
+{
+ /* Put that in for dl_plt_update_bp_on_hit to see. */
+ assert(self->task_enabling_breakpoint->arch.handler == NULL);
+ self->task_enabling_breakpoint->arch.handler = self;
+
+ linux_ptrace_disable_and_continue(self);
+}
+
+static enum callback_status
+cb_keep_stepping_p(struct process_stopping_handler *self)
+{
+ struct Process *proc = self->task_enabling_breakpoint;
+ struct library_symbol *libsym = self->breakpoint_being_enabled->libsym;
+
+ GElf_Addr value;
+ if (read_plt_slot_value(proc, libsym->arch.plt_slot_addr, &value) < 0)
+ return CBS_FAIL;
+
+ /* In UNRESOLVED state, the RESOLVED_VALUE in fact contains
+ * the PLT entry value. */
+ if (value == libsym->arch.resolved_value)
+ return CBS_CONT;
+
+ debug(DEBUG_PROCESS, "pid=%d PLT got resolved to value %#"PRIx64,
+ proc->pid, value);
+
+ /* The .plt slot got resolved! We can migrate the breakpoint
+ * to RESOLVED and stop single-stepping. */
+ if (proc->e_machine == EM_PPC64
+ && unresolve_plt_slot(proc, libsym->arch.plt_slot_addr,
+ libsym->arch.resolved_value) < 0)
+ return CBS_FAIL;
+
+ /* Resolving on PPC64 consists of overwriting a doubleword in
+ * .plt. That doubleword is than read back by a stub, and
+ * jumped on. Hopefully we can assume that double word update
+ * is done on a single place only, as it contains a final
+ * address. We still need to look around for any sync
+ * instruction, but essentially it is safe to optimize away
+ * the single stepping next time and install a post-update
+ * breakpoint.
+ *
+ * The situation on PPC32 BSS is more complicated. The
+ * dynamic linker here updates potentially several
+ * instructions (XXX currently we assume two) and the rules
+ * are more complicated. Sometimes it's enough to adjust just
+ * one of the addresses--the logic for generating optimal
+ * dispatch depends on relative addresses of the .plt entry
+ * and the jump destination. We can't assume that the some
+ * instruction block does the update every time. So on PPC32,
+ * we turn the optimization off and just step through it each
+ * time. */
+ if (proc->e_machine == EM_PPC)
+ goto done;
+
+ /* Install breakpoint to the address where the change takes
+ * place. If we fail, then that just means that we'll have to
+ * singlestep the next time around as well. */
+ struct Process *leader = proc->leader;
+ if (leader == NULL || leader->arch.dl_plt_update_bp != NULL)
+ goto done;
+
+ /* We need to install to the next instruction. ADDR points to
+ * a store instruction, so moving the breakpoint one
+ * instruction forward is safe. */
+ arch_addr_t addr = get_instruction_pointer(proc) + 4;
+ leader->arch.dl_plt_update_bp = insert_breakpoint(proc, addr, NULL);
+ if (leader->arch.dl_plt_update_bp == NULL)
+ goto done;
+
+ static struct bp_callbacks dl_plt_update_cbs = {
+ .on_hit = dl_plt_update_bp_on_hit,
+ };
+ leader->arch.dl_plt_update_bp->cbs = &dl_plt_update_cbs;
+
+ /* Turn it off for now. We will turn it on again when we hit
+ * the PLT entry that needs this. */
+ breakpoint_turn_off(leader->arch.dl_plt_update_bp, proc);
+
+done:
+ mark_as_resolved(libsym, value);
+
+ return CBS_STOP;
+}
+
+static void
+jump_to_entry_point(struct Process *proc, struct breakpoint *bp)
+{
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ arch_addr_t rv = (arch_addr_t)
+ (uintptr_t)bp->libsym->arch.resolved_value;
+ set_instruction_pointer(proc, rv);
+}
+
+static void
+ppc_plt_bp_continue(struct breakpoint *bp, struct Process *proc)
+{
+ switch (bp->libsym->arch.type) {
+ struct Process *leader;
+ void (*on_all_stopped)(struct process_stopping_handler *);
+ enum callback_status (*keep_stepping_p)
+ (struct process_stopping_handler *);
+
+ case PPC_DEFAULT:
+ assert(proc->e_machine == EM_PPC);
+ assert(bp->libsym != NULL);
+ assert(bp->libsym->lib->arch.bss_plt_prelinked == 0);
+ /* Fall through. */
+
+ case PPC_PLT_UNRESOLVED:
+ on_all_stopped = NULL;
+ keep_stepping_p = NULL;
+ leader = proc->leader;
+
+ if (leader != NULL && leader->arch.dl_plt_update_bp != NULL
+ && breakpoint_turn_on(leader->arch.dl_plt_update_bp,
+ proc) >= 0)
+ on_all_stopped = cb_on_all_stopped;
+ else
+ keep_stepping_p = cb_keep_stepping_p;
+
+ if (process_install_stopping_handler
+ (proc, bp, on_all_stopped, keep_stepping_p, NULL) < 0) {
+ fprintf(stderr, "ppc_plt_bp_continue: "
+ "couldn't install event handler\n");
+ continue_after_breakpoint(proc, bp);
+ }
+ return;
+
+ case PPC_PLT_RESOLVED:
+ if (proc->e_machine == EM_PPC) {
+ continue_after_breakpoint(proc, bp);
+ return;
+ }
+
+ jump_to_entry_point(proc, bp);
+ continue_process(proc->pid);
+ return;
+
+ case PPC64_PLT_STUB:
+ /* These should never hit here. */
+ break;
+ }
+
+ assert(bp->libsym->arch.type != bp->libsym->arch.type);
+ abort();
+}
+
+/* When a process is in a PLT stub, it may have already read the data
+ * in .plt that we changed. If we detach now, it will jump to PLT
+ * entry and continue to the dynamic linker, where it will SIGSEGV,
+ * because zeroth .plt slot is not filled in prelinked binaries, and
+ * the dynamic linker needs that data. Moreover, the process may
+ * actually have hit the breakpoint already. This functions tries to
+ * detect both cases and do any fix-ups necessary to mend this
+ * situation. */
+static enum callback_status
+detach_task_cb(struct Process *task, void *data)
+{
+ struct breakpoint *bp = data;
+
+ if (get_instruction_pointer(task) == bp->addr) {
+ debug(DEBUG_PROCESS, "%d at %p, which is PLT slot",
+ task->pid, bp->addr);
+ jump_to_entry_point(task, bp);
+ return CBS_CONT;
}
- return addr;
+ /* XXX There's still a window of several instructions where we
+ * might catch the task inside a stub such that it has already
+ * read destination address from .plt, but hasn't jumped yet,
+ * thus avoiding the breakpoint. */
+
+ return CBS_CONT;
+}
+
+static void
+ppc_plt_bp_retract(struct breakpoint *bp, struct Process *proc)
+{
+ /* On PPC64, we rewrite .plt with PLT entry addresses. This
+ * needs to be undone. Unfortunately, the program may have
+ * made decisions based on that value */
+ if (proc->e_machine == EM_PPC64
+ && bp->libsym != NULL
+ && bp->libsym->arch.type == PPC_PLT_RESOLVED) {
+ each_task(proc->leader, NULL, detach_task_cb, bp);
+ unresolve_plt_slot(proc, bp->libsym->arch.plt_slot_addr,
+ bp->libsym->arch.resolved_value);
+ }
+}
+
+void
+arch_library_init(struct library *lib)
+{
+}
+
+void
+arch_library_destroy(struct library *lib)
+{
+}
+
+void
+arch_library_clone(struct library *retp, struct library *lib)
+{
+}
+
+int
+arch_library_symbol_init(struct library_symbol *libsym)
+{
+ /* We set type explicitly in the code above, where we have the
+ * necessary context. This is for calls from ltrace-elf.c and
+ * such. */
+ libsym->arch.type = PPC_DEFAULT;
+ return 0;
+}
+
+void
+arch_library_symbol_destroy(struct library_symbol *libsym)
+{
+}
+
+int
+arch_library_symbol_clone(struct library_symbol *retp,
+ struct library_symbol *libsym)
+{
+ retp->arch = libsym->arch;
+ return 0;
+}
+
+/* For some symbol types, we need to set up custom callbacks. XXX we
+ * don't need PROC here, we can store the data in BP if it is of
+ * interest to us. */
+int
+arch_breakpoint_init(struct Process *proc, struct breakpoint *bp)
+{
+ /* Artificial and entry-point breakpoints are plain. */
+ if (bp->libsym == NULL || bp->libsym->plt_type != LS_TOPLT_EXEC)
+ return 0;
+
+ /* On PPC, secure PLT and prelinked BSS PLT are plain. */
+ if (proc->e_machine == EM_PPC
+ && bp->libsym->lib->arch.bss_plt_prelinked != 0)
+ return 0;
+
+ /* On PPC64, stub PLT breakpoints are plain. */
+ if (proc->e_machine == EM_PPC64
+ && bp->libsym->arch.type == PPC64_PLT_STUB)
+ return 0;
+
+ static struct bp_callbacks cbs = {
+ .on_continue = ppc_plt_bp_continue,
+ .on_retract = ppc_plt_bp_retract,
+ };
+ breakpoint_set_callbacks(bp, &cbs);
+ return 0;
+}
+
+void
+arch_breakpoint_destroy(struct breakpoint *bp)
+{
+}
+
+int
+arch_breakpoint_clone(struct breakpoint *retp, struct breakpoint *sbp)
+{
+ retp->arch = sbp->arch;
+ return 0;
+}
+
+int
+arch_process_init(struct Process *proc)
+{
+ proc->arch.dl_plt_update_bp = NULL;
+ proc->arch.handler = NULL;
+ return 0;
+}
+
+void
+arch_process_destroy(struct Process *proc)
+{
+}
+
+int
+arch_process_clone(struct Process *retp, struct Process *proc)
+{
+ retp->arch = proc->arch;
+ return 0;
+}
+
+int
+arch_process_exec(struct Process *proc)
+{
+ return arch_process_init(proc);
}
diff --git a/sysdeps/linux-gnu/ppc/ptrace.h b/sysdeps/linux-gnu/ppc/ptrace.h
index c3cbcb6..57c230c 100644
--- a/sysdeps/linux-gnu/ppc/ptrace.h
+++ b/sysdeps/linux-gnu/ppc/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/ppc/regs.c b/sysdeps/linux-gnu/ppc/regs.c
index eca58ff..37f89a4 100644
--- a/sysdeps/linux-gnu/ppc/regs.c
+++ b/sysdeps/linux-gnu/ppc/regs.c
@@ -1,9 +1,34 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2002,2008,2009 Juan Cespedes
+ * Copyright (C) 2009 Juan Cespedes
+ * Copyright (C) 2008 Luis Machado, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include <errno.h>
+#include <error.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
@@ -20,8 +45,10 @@ get_instruction_pointer(Process *proc) {
}
void
-set_instruction_pointer(Process *proc, void *addr) {
- ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr);
+set_instruction_pointer(Process *proc, void *addr)
+{
+ if (ptrace(PTRACE_POKEUSER, proc->pid, sizeof(long)*PT_NIP, addr) != 0)
+ error(0, errno, "set_instruction_pointer");
}
void *
diff --git a/sysdeps/linux-gnu/ppc/signalent.h b/sysdeps/linux-gnu/ppc/signalent.h
index d58a36c..9b8baa0 100644
--- a/sysdeps/linux-gnu/ppc/signalent.h
+++ b/sysdeps/linux-gnu/ppc/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/ppc/syscallent.h b/sysdeps/linux-gnu/ppc/syscallent.h
index 5ce5739..6989e81 100644
--- a/sysdeps/linux-gnu/ppc/syscallent.h
+++ b/sysdeps/linux-gnu/ppc/syscallent.h
@@ -1,4 +1,25 @@
-"0", /* 0 */
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+ "restart_syscall", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
"read", /* 3 */
@@ -177,8 +198,8 @@
"rt_sigtimedwait", /* 176 */
"rt_sigqueueinfo", /* 177 */
"rt_sigsuspend", /* 178 */
- "pread", /* 179 */
- "pwrite", /* 180 */
+ "pread64", /* 179 */
+ "pwrite64", /* 180 */
"chown", /* 181 */
"getcwd", /* 182 */
"capget", /* 183 */
@@ -254,6 +275,12 @@
"fstatfs64", /* 253 */
"fadvise64_64", /* 254 */
"rtas", /* 255 */
+ "sys_debug_setcontext", /* 256 */
+ "server", /* 257 */
+ "migrate_pages", /* 258 */
+ "mbind", /* 259 */
+ "get_mempolicy", /* 260 */
+ "set_mempolicy", /* 261 */
"mq_open", /* 262 */
"mq_unlink", /* 263 */
"mq_timedsend", /* 264 */
@@ -270,3 +297,78 @@
"inotify_init", /* 275 */
"inotify_add_watch", /* 276 */
"inotify_rm_watch", /* 277 */
+ "spu_run", /* 278 */
+ "spu_create", /* 279 */
+ "pselect6", /* 280 */
+ "ppoll", /* 281 */
+ "unshare", /* 282 */
+ "splice", /* 283 */
+ "tee", /* 284 */
+ "vmsplice", /* 285 */
+ "openat", /* 286 */
+ "mkdirat", /* 287 */
+ "mknodat", /* 288 */
+ "fchownat", /* 289 */
+ "futimesat", /* 290 */
+ "fstatat64", /* 291 */
+ "unlinkat", /* 292 */
+ "renameat", /* 293 */
+ "linkat", /* 294 */
+ "symlinkat", /* 295 */
+ "readlinkat", /* 296 */
+ "fchmodat", /* 297 */
+ "faccessat", /* 298 */
+ "get_robust_list", /* 299 */
+ "set_robust_list", /* 300 */
+ "move_pages", /* 301 */
+ "getcpu", /* 302 */
+ "epoll_pwait", /* 303 */
+ "utimensat", /* 304 */
+ "signalfd", /* 305 */
+ "timerfd_create", /* 306 */
+ "eventfd", /* 307 */
+ "sync_file_range2", /* 308 */
+ "fallocate", /* 309 */
+ "subpage_prot", /* 310 */
+ "timerfd_settime", /* 311 */
+ "timerfd_gettime", /* 312 */
+ "signalfd4", /* 313 */
+ "eventfd2", /* 314 */
+ "epoll_create1", /* 315 */
+ "dup3", /* 316 */
+ "pipe2", /* 317 */
+ "inotify_init1", /* 318 */
+ "perf_event_open", /* 319 */
+ "preadv", /* 320 */
+ "pwritev", /* 321 */
+ "rt_tgsigqueueinfo", /* 322 */
+ "fanotify_init", /* 323 */
+ "fanotify_mark", /* 324 */
+ "prlimit64", /* 325 */
+ "socket", /* 326 */
+ "bind", /* 327 */
+ "connect", /* 328 */
+ "listen", /* 329 */
+ "accept", /* 330 */
+ "getsockname", /* 331 */
+ "getpeername", /* 332 */
+ "socketpair", /* 333 */
+ "send", /* 334 */
+ "sendto", /* 335 */
+ "recv", /* 336 */
+ "recvfrom", /* 337 */
+ "shutdown", /* 338 */
+ "setsockopt", /* 339 */
+ "getsockopt", /* 340 */
+ "sendmsg", /* 341 */
+ "recvmsg", /* 342 */
+ "recvmmsg", /* 343 */
+ "accept4", /* 344 */
+ "name_to_handle_at", /* 345 */
+ "open_by_handle_at", /* 346 */
+ "clock_adjtime", /* 347 */
+ "syncfs", /* 348 */
+ "sendmmsg", /* 349 */
+ "setns", /* 350 */
+ "process_vm_readv", /* 351 */
+ "process_writev", /* 352 */
diff --git a/sysdeps/linux-gnu/ppc/trace.c b/sysdeps/linux-gnu/ppc/trace.c
index 81fb71d..4357a1e 100644
--- a/sysdeps/linux-gnu/ppc/trace.c
+++ b/sysdeps/linux-gnu/ppc/trace.c
@@ -1,14 +1,44 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2011 Andreas Schwab
+ * Copyright (C) 2002,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2008 Luis Machado, IBM Corporation
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include <assert.h>
#include <elf.h>
#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include "backend.h"
+#include "breakpoint.h"
#include "common.h"
+#include "insn.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
@@ -21,20 +51,13 @@
void
get_arch_dep(Process *proc) {
#ifdef __powerpc64__
- if (proc->arch_ptr)
- return;
proc->mask_32bit = (proc->e_machine == EM_PPC);
- proc->arch_ptr = (void *)1;
#endif
}
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */
#define SYSCALL_INSN 0x44000002
-unsigned int greg = 3;
-unsigned int freg = 1;
-unsigned int vreg = 2;
-
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise. */
int
syscall_p(Process *proc, int status, int *sysnum) {
if (WIFSTOPPED(status)
@@ -59,97 +82,167 @@ syscall_p(Process *proc, int status, int *sysnum) {
return 0;
}
-/* Grab functions arguments based on the PPC64 ABI. */
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- long data;
-
- if (type == LT_TOF_FUNCTIONR) {
- if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE)
- return ptrace (PTRACE_PEEKUSER, proc->pid,
- sizeof (long) * (PT_FPR0 + 1), 0);
- else
- return ptrace (PTRACE_PEEKUSER, proc->pid,
- sizeof (long) * PT_R3, 0);
- }
+/* The atomic skip code is mostly taken from GDB. */
- /* Check if we're entering a new function call to list parameters. If
- so, initialize the register control variables to keep track of where
- the parameters were stored. */
- if (type == LT_TOF_FUNCTION && arg_num == 0) {
- /* Initialize the set of registrers for parameter passing. */
- greg = 3;
- freg = 1;
- vreg = 2;
+/* In plt.h. XXX make this official interface. */
+int read_target_4(struct Process *proc, arch_addr_t addr, uint32_t *lp);
+
+int
+arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
+ int (*add_cb)(void *addr, void *data),
+ void *add_cb_data)
+{
+ arch_addr_t ip = get_instruction_pointer(proc);
+ struct breakpoint *other = address2bpstruct(proc->leader, ip);
+
+ debug(1, "arch_atomic_singlestep pid=%d addr=%p %s(%p)",
+ proc->pid, ip, breakpoint_name(sbp), sbp->addr);
+
+ /* If the original instruction was lwarx/ldarx, we can't
+ * single-step over it, instead we have to execute the whole
+ * atomic block at once. */
+ union {
+ uint32_t insn;
+ char buf[BREAKPOINT_LENGTH];
+ } u;
+ if (other != NULL) {
+ memcpy(u.buf, sbp->orig_value, BREAKPOINT_LENGTH);
+ } else if (read_target_4(proc, ip, &u.insn) < 0) {
+ fprintf(stderr, "couldn't read instruction at IP %p\n", ip);
+ /* Do the normal singlestep. */
+ return 1;
}
- if (info->type == ARGTYPE_FLOAT || info->type == ARGTYPE_DOUBLE) {
- if (freg <= 13 || (proc->mask_32bit && freg <= 8)) {
- data = ptrace (PTRACE_PEEKUSER, proc->pid,
- sizeof (long) * (PT_FPR0 + freg), 0);
-
- if (info->type == ARGTYPE_FLOAT) {
- /* float values passed in FP registers are automatically
- promoted to double. We need to convert it back to float
- before printing. */
- union { long val; float fval; double dval; } cvt;
- cvt.val = data;
- cvt.fval = (float) cvt.dval;
- data = cvt.val;
- }
+ if ((u.insn & LWARX_MASK) != LWARX_INSTRUCTION
+ && (u.insn & LWARX_MASK) != LDARX_INSTRUCTION)
+ return 1;
+
+ debug(1, "singlestep over atomic block at %p", ip);
+
+ int insn_count;
+ arch_addr_t addr = ip;
+ for (insn_count = 0; ; ++insn_count) {
+ addr += 4;
+ unsigned long l = ptrace(PTRACE_PEEKTEXT, proc->pid, addr, 0);
+ if (l == (unsigned long)-1 && errno)
+ return -1;
+ uint32_t insn;
+#ifdef __powerpc64__
+ insn = l >> 32;
+#else
+ insn = l;
+#endif
- freg++;
- greg++;
+ /* If a conditional branch is found, put a breakpoint
+ * in its destination address. */
+ if ((insn & BRANCH_MASK) == BC_INSN) {
+ arch_addr_t branch_addr = ppc_branch_dest(addr, insn);
+ debug(1, "pid=%d, branch in atomic block from %p to %p",
+ proc->pid, addr, branch_addr);
+ if (add_cb(branch_addr, add_cb_data) < 0)
+ return -1;
+ }
- return data;
+ /* Assume that the atomic sequence ends with a
+ * stwcx/stdcx instruction. */
+ if ((insn & STWCX_MASK) == STWCX_INSTRUCTION
+ || (insn & STWCX_MASK) == STDCX_INSTRUCTION) {
+ debug(1, "pid=%d, found end of atomic block %p at %p",
+ proc->pid, ip, addr);
+ break;
}
- }
- else if (greg <= 10) {
- data = ptrace (PTRACE_PEEKUSER, proc->pid,
- sizeof (long) * greg, 0);
- greg++;
- return data;
+ /* Arbitrary cut-off. If we didn't find the
+ * terminating instruction by now, just give up. */
+ if (insn_count > 16) {
+ fprintf(stderr, "[%d] couldn't find end of atomic block"
+ " at %p\n", proc->pid, ip);
+ return -1;
+ }
}
- else
- return ptrace (PTRACE_PEEKDATA, proc->pid,
- proc->stack_pointer + sizeof (long) *
- (arg_num - 8), 0);
+ /* Put the breakpoint to the next instruction. */
+ addr += 4;
+ if (add_cb(addr, add_cb_data) < 0)
+ return -1;
+
+ debug(1, "PTRACE_CONT");
+ ptrace(PTRACE_CONT, proc->pid, 0, 0);
return 0;
}
-void
-save_register_args(enum tof type, Process *proc) {
+size_t
+arch_type_sizeof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_CHAR:
+ return 1;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 2;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ return 4;
+
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return proc->e_machine == EM_PPC64 ? 8 : 4;
+
+ case ARGTYPE_FLOAT:
+ return 4;
+ case ARGTYPE_DOUBLE:
+ return 8;
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
+
+ default:
+ assert(info->type != info->type);
+ abort();
+ break;
+ }
}
-/* Read a single long from the process's memory address 'addr'. */
-int
-arch_umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
- long pointed_to;
-
- errno = 0;
-
- pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
-
- if (pointed_to == -1 && errno)
- return -errno;
-
- /* Since int's are 4-bytes (long is 8-bytes) in length for ppc64, we
- need to shift the long values returned by ptrace to end up with
- the correct value. */
-
- if (info) {
- if (info->type == ARGTYPE_INT || (proc->mask_32bit && (info->type == ARGTYPE_POINTER
- || info->type == ARGTYPE_STRING))) {
- pointed_to = pointed_to >> 32;
-
- /* Make sure we have nothing in the upper word so we can
- do a explicit cast from long to int later in the code. */
- pointed_to &= 0x00000000ffffffff;
- }
+size_t
+arch_type_alignof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ default:
+ assert(info->type != info->type);
+ abort();
+ break;
+
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ /* On both PPC and PPC64, fundamental types have the
+ * same alignment as size. */
+ return arch_type_sizeof(proc, info);
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
}
-
- *result = pointed_to;
- return 0;
}
diff --git a/sysdeps/linux-gnu/proc.c b/sysdeps/linux-gnu/proc.c
index 4251c1d..5adfb16 100644
--- a/sysdeps/linux-gnu/proc.c
+++ b/sysdeps/linux-gnu/proc.c
@@ -1,11 +1,53 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2010 Zachary T Welch, CodeSourcery
+ * Copyright (C) 2010 Joe Damato
+ * Copyright (C) 1998,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define _GNU_SOURCE /* For getline. */
#include "config.h"
+#include <sys/stat.h>
+#include <sys/syscall.h>
#include <sys/types.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <link.h>
+#include <signal.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
-#include <signal.h>
#include <unistd.h>
+#include "backend.h"
+#include "breakpoint.h"
+#include "config.h"
+#include "debug.h"
+#include "events.h"
+#include "library.h"
+#include "ltrace-elf.h"
+#include "proc.h"
+
/* /proc/pid doesn't exist just after the fork, and sometimes `ltrace'
* couldn't open it to find the executable. So it may be necessary to
* have a bit delay
@@ -13,17 +55,19 @@
#define MAX_DELAY 100000 /* 100000 microseconds = 0.1 seconds */
+#define PROC_PID_FILE(VAR, FORMAT, PID) \
+ char VAR[strlen(FORMAT) + 6]; \
+ sprintf(VAR, FORMAT, PID)
+
/*
* Returns a (malloc'd) file name corresponding to a running pid
*/
char *
pid2name(pid_t pid) {
- char proc_exe[1024];
-
if (!kill(pid, 0)) {
int delay = 0;
- sprintf(proc_exe, "/proc/%d/exe", pid);
+ PROC_PID_FILE(proc_exe, "/proc/%d/exe", pid);
while (delay < MAX_DELAY) {
if (!access(proc_exe, F_OK)) {
@@ -34,3 +78,655 @@ pid2name(pid_t pid) {
}
return NULL;
}
+
+static FILE *
+open_status_file(pid_t pid)
+{
+ PROC_PID_FILE(fn, "/proc/%d/status", pid);
+ /* Don't complain if we fail. This would typically happen
+ when the process is about to terminate, and these files are
+ not available anymore. This function is called from the
+ event loop, and we don't want to clutter the output just
+ because the process terminates. */
+ return fopen(fn, "r");
+}
+
+static char *
+find_line_starting(FILE * file, const char * prefix, size_t len)
+{
+ char * line = NULL;
+ size_t line_len = 0;
+ while (!feof(file)) {
+ if (getline(&line, &line_len, file) < 0)
+ return NULL;
+ if (strncmp(line, prefix, len) == 0)
+ return line;
+ }
+ return NULL;
+}
+
+static void
+each_line_starting(FILE *file, const char *prefix,
+ enum callback_status (*cb)(const char *line,
+ const char *prefix,
+ void *data),
+ void *data)
+{
+ size_t len = strlen(prefix);
+ char * line;
+ while ((line = find_line_starting(file, prefix, len)) != NULL) {
+ enum callback_status st = (*cb)(line, prefix, data);
+ free(line);
+ if (st == CBS_STOP)
+ return;
+ }
+}
+
+static enum callback_status
+process_leader_cb(const char *line, const char *prefix, void *data)
+{
+ pid_t * pidp = data;
+ *pidp = atoi(line + strlen(prefix));
+ return CBS_STOP;
+}
+
+pid_t
+process_leader(pid_t pid)
+{
+ pid_t tgid = 0;
+ FILE * file = open_status_file(pid);
+ if (file != NULL) {
+ each_line_starting(file, "Tgid:\t", &process_leader_cb, &tgid);
+ fclose(file);
+ }
+
+ return tgid;
+}
+
+static enum callback_status
+process_stopped_cb(const char *line, const char *prefix, void *data)
+{
+ char c = line[strlen(prefix)];
+ // t:tracing stop, T:job control stop
+ *(int *)data = (c == 't' || c == 'T');
+ return CBS_STOP;
+}
+
+int
+process_stopped(pid_t pid)
+{
+ int is_stopped = -1;
+ FILE * file = open_status_file(pid);
+ if (file != NULL) {
+ each_line_starting(file, "State:\t", &process_stopped_cb,
+ &is_stopped);
+ fclose(file);
+ }
+ return is_stopped;
+}
+
+static enum callback_status
+process_status_cb(const char *line, const char *prefix, void *data)
+{
+ const char * status = line + strlen(prefix);
+ const char c = *status;
+
+#define RETURN(C) do { \
+ *(enum process_status *)data = C; \
+ return CBS_STOP; \
+ } while (0)
+
+ switch (c) {
+ case 'Z': RETURN(ps_zombie);
+ case 't': RETURN(ps_tracing_stop);
+ case 'T':
+ /* This can be either "T (stopped)" or, for older
+ * kernels, "T (tracing stop)". */
+ if (!strcmp(status, "T (stopped)\n"))
+ RETURN(ps_stop);
+ else if (!strcmp(status, "T (tracing stop)\n"))
+ RETURN(ps_tracing_stop);
+ else {
+ fprintf(stderr, "Unknown process status: %s",
+ status);
+ RETURN(ps_stop); /* Some sort of stop
+ * anyway. */
+ }
+ case 'D':
+ case 'S': RETURN(ps_sleeping);
+ }
+
+ RETURN(ps_other);
+#undef RETURN
+}
+
+enum process_status
+process_status(pid_t pid)
+{
+ enum process_status ret = ps_invalid;
+ FILE * file = open_status_file(pid);
+ if (file != NULL) {
+ each_line_starting(file, "State:\t", &process_status_cb, &ret);
+ fclose(file);
+ if (ret == ps_invalid)
+ fprintf(stderr, "process_status %d: %s", pid,
+ strerror(errno));
+ } else
+ /* If the file is not present, the process presumably
+ * exited already. */
+ ret = ps_zombie;
+
+ return ret;
+}
+
+static int
+all_digits(const char *str)
+{
+ while (isdigit(*str))
+ str++;
+ return !*str;
+}
+
+int
+process_tasks(pid_t pid, pid_t **ret_tasks, size_t *ret_n)
+{
+ PROC_PID_FILE(fn, "/proc/%d/task", pid);
+ DIR * d = opendir(fn);
+ if (d == NULL)
+ return -1;
+
+ pid_t *tasks = NULL;
+ size_t n = 0;
+ size_t alloc = 0;
+
+ while (1) {
+ struct dirent entry;
+ struct dirent *result;
+ if (readdir_r(d, &entry, &result) != 0) {
+ free(tasks);
+ return -1;
+ }
+ if (result == NULL)
+ break;
+ if (result->d_type == DT_DIR && all_digits(result->d_name)) {
+ pid_t npid = atoi(result->d_name);
+ if (n >= alloc) {
+ alloc = alloc > 0 ? (2 * alloc) : 8;
+ pid_t *ntasks = realloc(tasks,
+ sizeof(*tasks) * alloc);
+ if (ntasks == NULL) {
+ free(tasks);
+ return -1;
+ }
+ tasks = ntasks;
+ }
+ if (n >= alloc)
+ abort();
+ tasks[n++] = npid;
+ }
+ }
+
+ closedir(d);
+
+ *ret_tasks = tasks;
+ *ret_n = n;
+ return 0;
+}
+
+/* On native 64-bit system, we need to be careful when handling cross
+ * tracing. This select appropriate pointer depending on host and
+ * target architectures. XXX Really we should abstract this into the
+ * ABI object, as theorized about somewhere on pmachata/revamp
+ * branch. */
+static void *
+select_32_64(struct Process *proc, void *p32, void *p64)
+{
+ if (sizeof(long) == 4 || proc->mask_32bit)
+ return p32;
+ else
+ return p64;
+}
+
+static int
+fetch_dyn64(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
+{
+ if (umovebytes(proc, *addr, ret, sizeof(*ret)) != sizeof(*ret))
+ return -1;
+ *addr += sizeof(*ret);
+ return 0;
+}
+
+static int
+fetch_dyn32(struct Process *proc, arch_addr_t *addr, Elf64_Dyn *ret)
+{
+ Elf32_Dyn dyn;
+ if (umovebytes(proc, *addr, &dyn, sizeof(dyn)) != sizeof(dyn))
+ return -1;
+
+ *addr += sizeof(dyn);
+ ret->d_tag = dyn.d_tag;
+ ret->d_un.d_val = dyn.d_un.d_val;
+
+ return 0;
+}
+
+static int (*
+dyn_fetcher(struct Process *proc))(struct Process *,
+ arch_addr_t *, Elf64_Dyn *)
+{
+ return select_32_64(proc, fetch_dyn32, fetch_dyn64);
+}
+
+int
+proc_find_dynamic_entry_addr(struct Process *proc, arch_addr_t src_addr,
+ int d_tag, arch_addr_t *ret)
+{
+ debug(DEBUG_FUNCTION, "find_dynamic_entry()");
+
+ if (ret == NULL || src_addr == 0 || d_tag < 0)
+ return -1;
+
+ int i = 0;
+ while (1) {
+ Elf64_Dyn entry;
+ if (dyn_fetcher(proc)(proc, &src_addr, &entry) < 0
+ || entry.d_tag == DT_NULL
+ || i++ > 100) { /* Arbitrary cut-off so that we
+ * don't loop forever if the
+ * binary is corrupted. */
+ debug(2, "Couldn't find address for dtag!");
+ return -1;
+ }
+
+ if (entry.d_tag == d_tag) {
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ *ret = (arch_addr_t)(uintptr_t)entry.d_un.d_val;
+ debug(2, "found address: %p in dtag %d", *ret, d_tag);
+ return 0;
+ }
+ }
+}
+
+/* Our own type for representing 32-bit linkmap. We can't rely on the
+ * definition in link.h, because that's only accurate for our host
+ * architecture, not for target architecture (where the traced process
+ * runs). */
+#define LT_LINK_MAP(BITS) \
+ { \
+ Elf##BITS##_Addr l_addr; \
+ Elf##BITS##_Addr l_name; \
+ Elf##BITS##_Addr l_ld; \
+ Elf##BITS##_Addr l_next; \
+ Elf##BITS##_Addr l_prev; \
+ }
+struct lt_link_map_32 LT_LINK_MAP(32);
+struct lt_link_map_64 LT_LINK_MAP(64);
+
+static int
+fetch_lm64(struct Process *proc, arch_addr_t addr,
+ struct lt_link_map_64 *ret)
+{
+ if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
+ return -1;
+ return 0;
+}
+
+static int
+fetch_lm32(struct Process *proc, arch_addr_t addr,
+ struct lt_link_map_64 *ret)
+{
+ struct lt_link_map_32 lm;
+ if (umovebytes(proc, addr, &lm, sizeof(lm)) != sizeof(lm))
+ return -1;
+
+ ret->l_addr = lm.l_addr;
+ ret->l_name = lm.l_name;
+ ret->l_ld = lm.l_ld;
+ ret->l_next = lm.l_next;
+ ret->l_prev = lm.l_prev;
+
+ return 0;
+}
+
+static int (*
+lm_fetcher(struct Process *proc))(struct Process *,
+ arch_addr_t, struct lt_link_map_64 *)
+{
+ return select_32_64(proc, fetch_lm32, fetch_lm64);
+}
+
+/* The same as above holds for struct r_debug. */
+#define LT_R_DEBUG(BITS) \
+ { \
+ int r_version; \
+ Elf##BITS##_Addr r_map; \
+ Elf##BITS##_Addr r_brk; \
+ int r_state; \
+ Elf##BITS##_Addr r_ldbase; \
+ }
+
+struct lt_r_debug_32 LT_R_DEBUG(32);
+struct lt_r_debug_64 LT_R_DEBUG(64);
+
+static int
+fetch_rd64(struct Process *proc, arch_addr_t addr,
+ struct lt_r_debug_64 *ret)
+{
+ if (umovebytes(proc, addr, ret, sizeof(*ret)) != sizeof(*ret))
+ return -1;
+ return 0;
+}
+
+static int
+fetch_rd32(struct Process *proc, arch_addr_t addr,
+ struct lt_r_debug_64 *ret)
+{
+ struct lt_r_debug_32 rd;
+ if (umovebytes(proc, addr, &rd, sizeof(rd)) != sizeof(rd))
+ return -1;
+
+ ret->r_version = rd.r_version;
+ ret->r_map = rd.r_map;
+ ret->r_brk = rd.r_brk;
+ ret->r_state = rd.r_state;
+ ret->r_ldbase = rd.r_ldbase;
+
+ return 0;
+}
+
+static int (*
+rdebug_fetcher(struct Process *proc))(struct Process *,
+ arch_addr_t, struct lt_r_debug_64 *)
+{
+ return select_32_64(proc, fetch_rd32, fetch_rd64);
+}
+
+static int
+fetch_auxv64_entry(int fd, Elf64_auxv_t *ret)
+{
+ /* Reaching EOF is as much problem as not reading whole
+ * entry. */
+ return read(fd, ret, sizeof(*ret)) == sizeof(*ret) ? 0 : -1;
+}
+
+static int
+fetch_auxv32_entry(int fd, Elf64_auxv_t *ret)
+{
+ Elf32_auxv_t auxv;
+ if (read(fd, &auxv, sizeof(auxv)) != sizeof(auxv))
+ return -1;
+
+ ret->a_type = auxv.a_type;
+ ret->a_un.a_val = auxv.a_un.a_val;
+ return 0;
+}
+
+static int (*
+auxv_fetcher(struct Process *proc))(int, Elf64_auxv_t *)
+{
+ return select_32_64(proc, fetch_auxv32_entry, fetch_auxv64_entry);
+}
+
+static void
+crawl_linkmap(struct Process *proc, struct lt_r_debug_64 *dbg)
+{
+ debug (DEBUG_FUNCTION, "crawl_linkmap()");
+
+ if (!dbg || !dbg->r_map) {
+ debug(2, "Debug structure or it's linkmap are NULL!");
+ return;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ arch_addr_t addr = (arch_addr_t)(uintptr_t)dbg->r_map;
+
+ while (addr != 0) {
+ struct lt_link_map_64 rlm;
+ if (lm_fetcher(proc)(proc, addr, &rlm) < 0) {
+ debug(2, "Unable to read link map");
+ return;
+ }
+
+ arch_addr_t key = addr;
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ addr = (arch_addr_t)(uintptr_t)rlm.l_next;
+ if (rlm.l_name == 0) {
+ debug(2, "Name of mapped library is NULL");
+ return;
+ }
+
+ char lib_name[BUFSIZ];
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ umovebytes(proc, (arch_addr_t)(uintptr_t)rlm.l_name,
+ lib_name, sizeof(lib_name));
+
+ /* Library name can be an empty string, in which case
+ * the entry represents either the main binary, or a
+ * VDSO. Unfortunately we can't rely on that, as in
+ * recent glibc, that entry is initialized to VDSO
+ * SONAME.
+ *
+ * It's not clear how to detect VDSO in this case. We
+ * can't assume that l_name of real DSOs will be
+ * either absolute or relative (for LD_LIBRARY_PATH=:
+ * it will be neither). We can't compare l_addr with
+ * AT_SYSINFO_EHDR either, as l_addr is bias (which
+ * also means it's not unique, and therefore useless
+ * for this). We could load VDSO from process image
+ * and at least compare actual SONAMEs. For now, this
+ * kludge is about the best that we can do. */
+ if (*lib_name == 0
+ || strcmp(lib_name, "linux-vdso.so.1") == 0
+ || strcmp(lib_name, "linux-gate.so.1") == 0
+ || strcmp(lib_name, "linux-vdso32.so.1") == 0
+ || strcmp(lib_name, "linux-vdso64.so.1") == 0)
+ continue;
+
+ /* Do we have that library already? */
+ if (proc_each_library(proc, NULL, library_with_key_cb, &key))
+ continue;
+
+ struct library *lib = malloc(sizeof(*lib));
+ if (lib == NULL) {
+ fail:
+ if (lib != NULL)
+ library_destroy(lib);
+ fprintf(stderr, "Couldn't load ELF object %s: %s\n",
+ lib_name, strerror(errno));
+ continue;
+ }
+ library_init(lib, LT_LIBTYPE_DSO);
+
+ if (ltelf_read_library(lib, proc, lib_name, rlm.l_addr) < 0)
+ goto fail;
+
+ lib->key = key;
+ proc_add_library(proc, lib);
+ }
+ return;
+}
+
+static int
+load_debug_struct(struct Process *proc, struct lt_r_debug_64 *ret)
+{
+ debug(DEBUG_FUNCTION, "load_debug_struct");
+
+ if (rdebug_fetcher(proc)(proc, proc->os.debug_addr, ret) < 0) {
+ debug(2, "This process does not have a debug structure!");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+rdebug_bp_on_hit(struct breakpoint *bp, struct Process *proc)
+{
+ debug(DEBUG_FUNCTION, "arch_check_dbg");
+
+ struct lt_r_debug_64 rdbg;
+ if (load_debug_struct(proc, &rdbg) < 0) {
+ debug(2, "Unable to load debug structure!");
+ return;
+ }
+
+ if (rdbg.r_state == RT_CONSISTENT) {
+ debug(2, "Linkmap is now consistent");
+ switch (proc->os.debug_state) {
+ case RT_ADD:
+ debug(2, "Adding DSO to linkmap");
+ crawl_linkmap(proc, &rdbg);
+ break;
+ case RT_DELETE:
+ debug(2, "Removing DSO from linkmap");
+ // XXX unload that library
+ break;
+ default:
+ debug(2, "Unexpected debug state!");
+ }
+ }
+
+ proc->os.debug_state = rdbg.r_state;
+}
+
+#ifndef ARCH_HAVE_FIND_DL_DEBUG
+int
+arch_find_dl_debug(struct Process *proc, arch_addr_t dyn_addr,
+ arch_addr_t *ret)
+{
+ return proc_find_dynamic_entry_addr(proc, dyn_addr, DT_DEBUG, ret);
+}
+#endif
+
+int
+linkmap_init(struct Process *proc, arch_addr_t dyn_addr)
+{
+ debug(DEBUG_FUNCTION, "linkmap_init(%d, dyn_addr=%p)", proc->pid, dyn_addr);
+
+ if (arch_find_dl_debug(proc, dyn_addr, &proc->os.debug_addr) == -1) {
+ debug(2, "Couldn't find debug structure!");
+ return -1;
+ }
+
+ int status;
+ struct lt_r_debug_64 rdbg;
+ if ((status = load_debug_struct(proc, &rdbg)) < 0) {
+ debug(2, "No debug structure or no memory to allocate one!");
+ return status;
+ }
+
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ arch_addr_t addr = (arch_addr_t)(uintptr_t)rdbg.r_brk;
+ if (arch_translate_address_dyn(proc, addr, &addr) < 0)
+ return -1;
+
+ struct breakpoint *rdebug_bp = insert_breakpoint(proc, addr, NULL);
+ static struct bp_callbacks rdebug_callbacks = {
+ .on_hit = rdebug_bp_on_hit,
+ };
+ rdebug_bp->cbs = &rdebug_callbacks;
+
+ crawl_linkmap(proc, &rdbg);
+
+ return 0;
+}
+
+int
+task_kill (pid_t pid, int sig)
+{
+ // Taken from GDB
+ int ret;
+
+ errno = 0;
+ ret = syscall (__NR_tkill, pid, sig);
+ return ret;
+}
+
+void
+process_removed(struct Process *proc)
+{
+ delete_events_for(proc);
+}
+
+int
+process_get_entry(struct Process *proc,
+ arch_addr_t *entryp,
+ arch_addr_t *interp_biasp)
+{
+ PROC_PID_FILE(fn, "/proc/%d/auxv", proc->pid);
+ int fd = open(fn, O_RDONLY);
+ int ret = 0;
+ if (fd == -1) {
+ fail:
+ fprintf(stderr, "couldn't read %s: %s", fn, strerror(errno));
+ ret = -1;
+ done:
+ if (fd != -1)
+ close(fd);
+ return ret;
+ }
+
+ arch_addr_t at_entry = 0;
+ arch_addr_t at_bias = 0;
+ while (1) {
+ Elf64_auxv_t entry = {};
+ if (auxv_fetcher(proc)(fd, &entry) < 0)
+ goto fail;
+
+ switch (entry.a_type) {
+ case AT_BASE:
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ at_bias = (arch_addr_t)(uintptr_t)entry.a_un.a_val;
+ continue;
+
+ case AT_ENTRY:
+ /* XXX The double cast should be removed when
+ * arch_addr_t becomes integral type. */
+ at_entry = (arch_addr_t)(uintptr_t)entry.a_un.a_val;
+ default:
+ continue;
+
+ case AT_NULL:
+ break;
+ }
+ break;
+ }
+
+ if (entryp != NULL)
+ *entryp = at_entry;
+ if (interp_biasp != NULL)
+ *interp_biasp = at_bias;
+ goto done;
+}
+
+int
+os_process_init(struct Process *proc)
+{
+ proc->os.debug_addr = 0;
+ proc->os.debug_state = 0;
+ return 0;
+}
+
+void
+os_process_destroy(struct Process *proc)
+{
+}
+
+int
+os_process_clone(struct Process *retp, struct Process *proc)
+{
+ retp->os = proc->os;
+ return 0;
+}
+
+int
+os_process_exec(struct Process *proc)
+{
+ return 0;
+}
diff --git a/sysdeps/linux-gnu/s390/Makefile b/sysdeps/linux-gnu/s390/Makefile
deleted file mode 100644
index cea1b45..0000000
--- a/sysdeps/linux-gnu/s390/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# S/390 version
-# Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation
-#
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
diff --git a/sysdeps/linux-gnu/s390/Makefile.am b/sysdeps/linux-gnu/s390/Makefile.am
new file mode 100644
index 0000000..22741bd
--- /dev/null
+++ b/sysdeps/linux-gnu/s390/Makefile.am
@@ -0,0 +1,39 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent1.h \
+ signalent.h \
+ syscallent1.h \
+ syscallent.h \
+ syscalls31.h \
+ syscalls64.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/s390/Makefile.in b/sysdeps/linux-gnu/s390/Makefile.in
new file mode 100644
index 0000000..0f55ef5
--- /dev/null
+++ b/sysdeps/linux-gnu/s390/Makefile.in
@@ -0,0 +1,534 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/s390
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo fetch.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent1.h \
+ signalent.h \
+ syscallent1.h \
+ syscallent.h \
+ syscalls31.h \
+ syscalls64.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/s390/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/s390/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/s390/arch.h b/sysdeps/linux-gnu/s390/arch.h
index 03690b8..0d412dc 100644
--- a/sysdeps/linux-gnu/s390/arch.h
+++ b/sysdeps/linux-gnu/s390/arch.h
@@ -1,18 +1,35 @@
/*
-** S/390 version
-** (C) Copyright 2001 IBM Poughkeepsie, IBM Corporation
-*/
+ * This file is part of ltrace.
+ * Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
#define BREAKPOINT_VALUE { 0x00, 0x01 }
#define BREAKPOINT_LENGTH 2
#define DECR_PC_AFTER_BREAK 2
+#define ARCH_ENDIAN_BIG
+#define ARCH_HAVE_FETCH_ARG
+#define ARCH_HAVE_SIZEOF
+#define ARCH_HAVE_ALIGNOF
-#ifdef __s390x__
-#define LT_ELFCLASS ELFCLASS64
-#define LT_ELF_MACHINE EM_S390
-#define LT_ELFCLASS2 ELFCLASS32
-#define LT_ELF_MACHINE2 EM_S390
-#else
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_S390
+
+#ifdef __s390x__
+#define LT_ELFCLASS2 ELFCLASS64
+#define LT_ELF_MACHINE2 EM_S390
#endif
diff --git a/sysdeps/linux-gnu/s390/fetch.c b/sysdeps/linux-gnu/s390/fetch.c
new file mode 100644
index 0000000..fa8f42d
--- /dev/null
+++ b/sysdeps/linux-gnu/s390/fetch.c
@@ -0,0 +1,289 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <asm/ptrace.h>
+#include <sys/ptrace.h>
+#include <sys/ucontext.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "backend.h"
+#include "fetch.h"
+#include "type.h"
+#include "proc.h"
+#include "value.h"
+
+struct fetch_context {
+ struct user_regs_struct regs;
+ arch_addr_t stack_pointer;
+ int greg;
+ int freg;
+};
+
+static int
+s390x(struct fetch_context *ctx)
+{
+ /* +--------+--------+--------+
+ * | PSW.31 | PSW.32 | mode |
+ * +--------+--------+--------+
+ * | 0 | 0 | 24-bit | Not supported in Linux
+ * | 0 | 1 | 31-bit | s390 compatible mode
+ * | 1 | 1 | 64-bit | z/Architecture, "s390x"
+ * +--------+--------+--------+
+ * (Note: The leftmost bit is PSW.0, rightmost PSW.63.)
+ */
+
+#ifdef __s390x__
+ if ((ctx->regs.psw.mask & 0x180000000UL) == 0x180000000UL)
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+fetch_register_banks(struct Process *proc, struct fetch_context *ctx)
+{
+ ptrace_area parea;
+ parea.len = sizeof(ctx->regs);
+ parea.process_addr = (uintptr_t)&ctx->regs;
+ parea.kernel_addr = 0;
+ if (ptrace(PTRACE_PEEKUSR_AREA, proc->pid, &parea, NULL) < 0) {
+ fprintf(stderr, "fetch_register_banks GPR: %s\n",
+ strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+
+static int
+fetch_context_init(struct Process *proc, struct fetch_context *context)
+{
+ context->greg = 2;
+ context->freg = 0;
+ return fetch_register_banks(proc, context);
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *context = malloc(sizeof(*context));
+ if (context == NULL
+ || fetch_context_init(proc, context) < 0) {
+ fprintf(stderr, "arch_fetch_arg_init: %s\n",
+ strerror(errno));
+ free(context);
+ return NULL;
+ }
+
+ context->stack_pointer = get_stack_pointer(proc)
+ + (s390x(context) ? 160 : 96);
+ if (ret_info->type == ARGTYPE_STRUCT)
+ ++context->greg;
+
+ return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc,
+ struct fetch_context *context)
+{
+ struct fetch_context *clone = malloc(sizeof(*context));
+ if (clone == NULL)
+ return NULL;
+ *clone = *context;
+ return clone;
+}
+
+static int
+allocate_stack_slot(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ size_t sz)
+{
+ /* Note: here we shouldn't see large composite types, those
+ * are passed by reference, which is handled below. Here we
+ * only deal with integers, floats, small structs, etc. */
+
+ size_t a;
+ if (s390x(ctx)) {
+ assert(sz <= 8);
+ a = 8;
+ } else {
+ /* Note: double is 8 bytes. */
+ assert(sz <= 8);
+ a = 4;
+ }
+
+ size_t off = sz < a ? a - sz : 0;
+ value_in_inferior(valuep, ctx->stack_pointer + off);
+
+ ctx->stack_pointer += sz > a ? sz : a;
+ return 0;
+}
+
+static void
+copy_gpr(struct fetch_context *ctx, struct value *valuep, int regno)
+{
+ value_set_word(valuep, ctx->regs.gprs[regno]);
+}
+
+static int
+allocate_gpr(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ size_t sz)
+{
+ if (ctx->greg > 6)
+ return allocate_stack_slot(ctx, proc, info, valuep, sz);
+
+ copy_gpr(ctx, valuep, ctx->greg++);
+ return 0;
+}
+
+static int
+allocate_gpr_pair(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ size_t sz)
+{
+ assert(!s390x(ctx));
+ assert(sz <= 8);
+
+ if (ctx->greg > 5) {
+ ctx->greg = 7;
+ return allocate_stack_slot(ctx, proc, info, valuep, sz);
+ }
+
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ unsigned char *ptr = value_get_raw_data(valuep);
+ union {
+ struct {
+ uint32_t a;
+ uint32_t b;
+ };
+ unsigned char buf[8];
+ } u;
+ u.a = ctx->regs.gprs[ctx->greg++];
+ u.b = ctx->regs.gprs[ctx->greg++];
+ memcpy(ptr, u.buf, sz);
+
+ return 0;
+}
+
+static int
+allocate_fpr(struct fetch_context *ctx, struct Process *proc,
+ struct arg_type_info *info, struct value *valuep,
+ size_t sz)
+{
+ int pool = s390x(ctx) ? 6 : 2;
+
+ if (ctx->freg > pool)
+ return allocate_stack_slot(ctx, proc, info, valuep, sz);
+
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ memcpy(value_get_raw_data(valuep),
+ &ctx->regs.fp_regs.fprs[ctx->freg], sz);
+ ctx->freg += 2;
+
+ return 0;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *ctx, enum tof type,
+ struct Process *proc,
+ struct arg_type_info *info, struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ value_set_word(valuep, 0);
+ return 0;
+
+ case ARGTYPE_STRUCT:
+ if (type_get_fp_equivalent(info) != NULL)
+ /* fall through */
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ return allocate_fpr(ctx, proc, info, valuep, sz);
+
+ /* Structures<4 bytes on s390 and structures<8 bytes
+ * on s390x are passed in register. On s390, long
+ * long and structures<8 bytes are passed in two
+ * consecutive registers (if two are available). */
+
+ if (sz <= (s390x(ctx) ? 8 : 4))
+ return allocate_gpr(ctx, proc, info, valuep, sz);
+ else if (sz <= 8)
+ return allocate_gpr_pair(ctx, proc, info, valuep, sz);
+
+ /* fall through */
+
+ case ARGTYPE_ARRAY:
+ if (value_pass_by_reference(valuep) < 0)
+ return -1;
+ /* fall through */
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_POINTER:
+ return allocate_gpr(ctx, proc, info, valuep, sz);
+
+ default:
+ assert(info->type != info->type);
+ abort();
+ }
+ return -1;
+}
+
+int
+arch_fetch_retval(struct fetch_context *ctx, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (info->type == ARGTYPE_STRUCT) {
+ if (value_pass_by_reference(valuep) < 0)
+ return -1;
+ copy_gpr(ctx, valuep, 2);
+ return 0;
+ }
+
+ if (fetch_context_init(proc, ctx) < 0)
+ return -1;
+ return arch_fetch_arg_next(ctx, type, proc, info, valuep);
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+ free(context);
+}
diff --git a/sysdeps/linux-gnu/s390/plt.c b/sysdeps/linux-gnu/s390/plt.c
index 85a1dd1..5f612e5 100644
--- a/sysdeps/linux-gnu/s390/plt.c
+++ b/sysdeps/linux-gnu/s390/plt.c
@@ -1,5 +1,27 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
+#include "proc.h"
#include "common.h"
+#include "library.h"
GElf_Addr
arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
diff --git a/sysdeps/linux-gnu/s390/ptrace.h b/sysdeps/linux-gnu/s390/ptrace.h
index c3cbcb6..ad7e0d6 100644
--- a/sysdeps/linux-gnu/s390/ptrace.h
+++ b/sysdeps/linux-gnu/s390/ptrace.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/s390/regs.c b/sysdeps/linux-gnu/s390/regs.c
index 169893e..0592ccd 100644
--- a/sysdeps/linux-gnu/s390/regs.c
+++ b/sysdeps/linux-gnu/s390/regs.c
@@ -1,7 +1,25 @@
/*
-** S/390 version
-** Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation
-*/
+ * This file is part of ltrace.
+ * Copyright (C) 2002,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ * Copyright (C) 2001 IBM Poughkeepsie, IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
#include "config.h"
@@ -9,6 +27,7 @@
#include <sys/ptrace.h>
#include <asm/ptrace.h>
+#include "proc.h"
#include "common.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
diff --git a/sysdeps/linux-gnu/s390/signalent.h b/sysdeps/linux-gnu/s390/signalent.h
index 35b74f1..218b057 100644
--- a/sysdeps/linux-gnu/s390/signalent.h
+++ b/sysdeps/linux-gnu/s390/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/s390/signalent1.h b/sysdeps/linux-gnu/s390/signalent1.h
index b5b6ca8..0f529bb 100644
--- a/sysdeps/linux-gnu/s390/signalent1.h
+++ b/sysdeps/linux-gnu/s390/signalent1.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "s390/signalent.h"
diff --git a/sysdeps/linux-gnu/s390/syscallent.h b/sysdeps/linux-gnu/s390/syscallent.h
index 5a35d93..03d0541 100644
--- a/sysdeps/linux-gnu/s390/syscallent.h
+++ b/sysdeps/linux-gnu/s390/syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#ifdef __s390x__
#include "s390/syscalls64.h"
#else
diff --git a/sysdeps/linux-gnu/s390/syscallent1.h b/sysdeps/linux-gnu/s390/syscallent1.h
index c9fdc81..8d80a54 100644
--- a/sysdeps/linux-gnu/s390/syscallent1.h
+++ b/sysdeps/linux-gnu/s390/syscallent1.h
@@ -1 +1,21 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "s390/syscalls31.h"
diff --git a/sysdeps/linux-gnu/s390/syscalls31.h b/sysdeps/linux-gnu/s390/syscalls31.h
index 42631eb..46f4cf3 100644
--- a/sysdeps/linux-gnu/s390/syscalls31.h
+++ b/sysdeps/linux-gnu/s390/syscalls31.h
@@ -1,3 +1,24 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Heiko Carstens, IBM Corporation
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"0", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
diff --git a/sysdeps/linux-gnu/s390/syscalls64.h b/sysdeps/linux-gnu/s390/syscalls64.h
index 97be52c..f2ec7f4 100644
--- a/sysdeps/linux-gnu/s390/syscalls64.h
+++ b/sysdeps/linux-gnu/s390/syscalls64.h
@@ -1,3 +1,24 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Heiko Carstens, IBM Corporation
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"0", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
diff --git a/sysdeps/linux-gnu/s390/trace.c b/sysdeps/linux-gnu/s390/trace.c
index 9df2437..b9e05ff 100644
--- a/sysdeps/linux-gnu/s390/trace.c
+++ b/sysdeps/linux-gnu/s390/trace.c
@@ -1,23 +1,38 @@
/*
-** S390 specific part of trace.c
-**
-** Other routines are in ../trace.c and need to be combined
-** at link time with this code.
-**
-** Copyright (C) 2001,2005 IBM Corp.
-*/
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2001,2005 IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
#include "config.h"
-#include <errno.h>
-#include <stdlib.h>
+#include <asm/ptrace.h>
+#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
#include <signal.h>
-#include <sys/ptrace.h>
-#include <asm/ptrace.h>
+#include <stdlib.h>
#include "common.h"
+#include "proc.h"
+#include "type.h"
#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
# define PTRACE_PEEKUSER PTRACE_PEEKUSR
@@ -159,40 +174,84 @@ syscall_p(Process *proc, int status, int *sysnum) {
return 0;
}
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- long ret;
+size_t
+arch_type_sizeof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_CHAR:
+ return 1;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 2;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ return 4;
+
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return proc->e_class == ELFCLASS64 ? 8 : 4;
+
+ case ARGTYPE_FLOAT:
+ return 4;
+ case ARGTYPE_DOUBLE:
+ return 8;
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
- switch (arg_num) {
- case -1: /* return value */
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR2, 0);
- break;
- case 0:
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_ORIGGPR2, 0);
- break;
- case 1:
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR3, 0);
- break;
- case 2:
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR4, 0);
- break;
- case 3:
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR5, 0);
- break;
- case 4:
- ret = ptrace(PTRACE_PEEKUSER, proc->pid, PT_GPR6, 0);
- break;
default:
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(2);
+ assert(info->type != info->type);
+ abort();
}
-#ifdef __s390x__
- if (proc->mask_32bit)
- ret &= 0xffffffff;
-#endif
- return ret;
}
-void
-save_register_args(enum tof type, Process *proc) {
+size_t
+arch_type_alignof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ default:
+ assert(info->type != info->type);
+ break;
+
+ case ARGTYPE_CHAR:
+ return 1;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 2;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ return 4;
+
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return proc->e_class == ELFCLASS64 ? 8 : 4;
+
+ case ARGTYPE_FLOAT:
+ return 4;
+ case ARGTYPE_DOUBLE:
+ return 8;
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
+ }
+ abort();
}
diff --git a/sysdeps/linux-gnu/signalent1.h b/sysdeps/linux-gnu/signalent1.h
new file mode 100644
index 0000000..74d8e19
--- /dev/null
+++ b/sysdeps/linux-gnu/signalent1.h
@@ -0,0 +1 @@
+/* This file is intentionally left blank */
diff --git a/sysdeps/linux-gnu/sparc/Makefile b/sysdeps/linux-gnu/sparc/Makefile
deleted file mode 100644
index b3914e5..0000000
--- a/sysdeps/linux-gnu/sparc/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-OBJ = regs.o trace.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
diff --git a/sysdeps/linux-gnu/sparc/Makefile.am b/sysdeps/linux-gnu/sparc/Makefile.am
new file mode 100644
index 0000000..5c6ecc2
--- /dev/null
+++ b/sysdeps/linux-gnu/sparc/Makefile.am
@@ -0,0 +1,34 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/sparc/Makefile.in b/sysdeps/linux-gnu/sparc/Makefile.in
new file mode 100644
index 0000000..d94a1d8
--- /dev/null
+++ b/sysdeps/linux-gnu/sparc/Makefile.in
@@ -0,0 +1,528 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/sparc
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ syscallent.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/sparc/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/sparc/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/sparc/arch.h b/sysdeps/linux-gnu/sparc/arch.h
index 75251b8..9685d13 100644
--- a/sysdeps/linux-gnu/sparc/arch.h
+++ b/sysdeps/linux-gnu/sparc/arch.h
@@ -1,6 +1,27 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#define BREAKPOINT_VALUE {0x91, 0xd0, 0x20, 0x01}
#define BREAKPOINT_LENGTH 4
#define DECR_PC_AFTER_BREAK 0
+#define ARCH_ENDIAN_BIG
#define LT_ELFCLASS ELFCLASS32
#define LT_ELF_MACHINE EM_SPARC
diff --git a/sysdeps/linux-gnu/sparc/plt.c b/sysdeps/linux-gnu/sparc/plt.c
index f9e6d80..40bbabc 100644
--- a/sysdeps/linux-gnu/sparc/plt.c
+++ b/sysdeps/linux-gnu/sparc/plt.c
@@ -1,4 +1,25 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include <gelf.h>
+#include "proc.h"
#include "common.h"
GElf_Addr
diff --git a/sysdeps/linux-gnu/sparc/ptrace.h b/sysdeps/linux-gnu/sparc/ptrace.h
index bbaf01a..cbc35a6 100644
--- a/sysdeps/linux-gnu/sparc/ptrace.h
+++ b/sysdeps/linux-gnu/sparc/ptrace.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#undef PTRACE_GETREGS
#undef PTRACE_SETREGS
#undef PTRACE_GETFPREGS
diff --git a/sysdeps/linux-gnu/sparc/regs.c b/sysdeps/linux-gnu/sparc/regs.c
index 49d2729..5e5ad20 100644
--- a/sysdeps/linux-gnu/sparc/regs.c
+++ b/sysdeps/linux-gnu/sparc/regs.c
@@ -1,7 +1,29 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <sys/types.h>
#include "ptrace.h"
+#include "proc.h"
#include "common.h"
void *
diff --git a/sysdeps/linux-gnu/sparc/signalent.h b/sysdeps/linux-gnu/sparc/signalent.h
index d30f69e..8555456 100644
--- a/sysdeps/linux-gnu/sparc/signalent.h
+++ b/sysdeps/linux-gnu/sparc/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/sparc/syscallent.h b/sysdeps/linux-gnu/sparc/syscallent.h
index 96eeec9..bb309c6 100644
--- a/sysdeps/linux-gnu/sparc/syscallent.h
+++ b/sysdeps/linux-gnu/sparc/syscallent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"0", /* 0 */
"exit", /* 1 */
"fork", /* 2 */
diff --git a/sysdeps/linux-gnu/sparc/trace.c b/sysdeps/linux-gnu/sparc/trace.c
index 7f05b55..e1725ff 100644
--- a/sysdeps/linux-gnu/sparc/trace.c
+++ b/sysdeps/linux-gnu/sparc/trace.c
@@ -1,3 +1,24 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
#include "config.h"
#include <stdlib.h>
@@ -6,6 +27,7 @@
#include <signal.h>
#include <string.h>
#include "ptrace.h"
+#include "proc.h"
#include "common.h"
void
@@ -44,7 +66,8 @@ syscall_p(Process *proc, int status, int *sysnum) {
}
long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
+gimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info)
+{
proc_archdep *a = (proc_archdep *) proc->arch_ptr;
if (!a->valid) {
fprintf(stderr, "Could not get child registers\n");
@@ -68,14 +91,3 @@ gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
}
return 0;
}
-
-void
-save_register_args(enum tof type, Process *proc) {
- proc_archdep *a = (proc_archdep *) proc->arch_ptr;
- if (a->valid) {
- if (type == LT_TOF_FUNCTION)
- memcpy(a->func_arg, &a->regs.u_regs[UREG_G7], sizeof(a->func_arg));
- else
- memcpy(a->sysc_arg, &a->regs.u_regs[UREG_G7], sizeof(a->sysc_arg));
- }
-}
diff --git a/sysdeps/linux-gnu/syscallent1.h b/sysdeps/linux-gnu/syscallent1.h
new file mode 100644
index 0000000..74d8e19
--- /dev/null
+++ b/sysdeps/linux-gnu/syscallent1.h
@@ -0,0 +1 @@
+/* This file is intentionally left blank */
diff --git a/sysdeps/linux-gnu/trace-defs.h b/sysdeps/linux-gnu/trace-defs.h
new file mode 100644
index 0000000..aa69b83
--- /dev/null
+++ b/sysdeps/linux-gnu/trace-defs.h
@@ -0,0 +1,92 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#ifndef _TRACE_DEFS_H_
+#define _TRACE_DEFS_H_
+#include <sys/ptrace.h>
+
+/* If the system headers did not provide the constants, hard-code the
+ * normal values. */
+#ifndef PTRACE_OLDSETOPTIONS
+# define PTRACE_OLDSETOPTIONS 21
+#endif
+
+#ifndef PTRACE_SETOPTIONS
+# define PTRACE_SETOPTIONS 0x4200
+#endif
+
+#ifndef PTRACE_GETEVENTMSG
+# define PTRACE_GETEVENTMSG 0x4201
+#endif
+
+/* Options set using PTRACE_SETOPTIONS. */
+#ifndef PTRACE_O_TRACESYSGOOD
+# define PTRACE_O_TRACESYSGOOD 0x00000001
+#endif
+
+#ifndef PTRACE_O_TRACEFORK
+# define PTRACE_O_TRACEFORK 0x00000002
+#endif
+
+#ifndef PTRACE_O_TRACEVFORK
+# define PTRACE_O_TRACEVFORK 0x00000004
+#endif
+
+#ifndef PTRACE_O_TRACECLONE
+# define PTRACE_O_TRACECLONE 0x00000008
+#endif
+
+#ifndef PTRACE_O_TRACEEXEC
+# define PTRACE_O_TRACEEXEC 0x00000010
+#endif
+
+#ifndef PTRACE_O_TRACEVFORKDONE
+# define PTRACE_O_TRACEVFORKDONE 0x00000020
+#endif
+
+#ifndef PTRACE_O_TRACEEXIT
+# define PTRACE_O_TRACEEXIT 0x00000040
+#endif
+
+/* Wait extended result codes for the above trace options. */
+#ifndef PTRACE_EVENT_FORK
+# define PTRACE_EVENT_FORK 1
+#endif
+
+#ifndef PTRACE_EVENT_VFORK
+# define PTRACE_EVENT_VFORK 2
+#endif
+
+#ifndef PTRACE_EVENT_CLONE
+# define PTRACE_EVENT_CLONE 3
+#endif
+
+#ifndef PTRACE_EVENT_EXEC
+# define PTRACE_EVENT_EXEC 4
+#endif
+
+#ifndef PTRACE_EVENT_VFORK_DONE
+# define PTRACE_EVENT_VFORK_DONE 5
+#endif
+
+#ifndef PTRACE_EVENT_EXIT
+# define PTRACE_EVENT_EXIT 6
+#endif
+
+#endif /* _TRACE_DEFS_H_ */
diff --git a/sysdeps/linux-gnu/trace.c b/sysdeps/linux-gnu/trace.c
index df5b090..e13b761 100644
--- a/sysdeps/linux-gnu/trace.c
+++ b/sysdeps/linux-gnu/trace.c
@@ -1,104 +1,129 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2007,2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2010 Joe Damato
+ * Copyright (C) 1998,2002,2003,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <asm/unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <unistd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include "ptrace.h"
-#include <asm/unistd.h>
-#include "common.h"
-
-/* If the system headers did not provide the constants, hard-code the normal
- values. */
-#ifndef PTRACE_EVENT_FORK
-
-#define PTRACE_OLDSETOPTIONS 21
-#define PTRACE_SETOPTIONS 0x4200
-#define PTRACE_GETEVENTMSG 0x4201
-
-/* options set using PTRACE_SETOPTIONS */
-#define PTRACE_O_TRACESYSGOOD 0x00000001
-#define PTRACE_O_TRACEFORK 0x00000002
-#define PTRACE_O_TRACEVFORK 0x00000004
-#define PTRACE_O_TRACECLONE 0x00000008
-#define PTRACE_O_TRACEEXEC 0x00000010
-#define PTRACE_O_TRACEVFORKDONE 0x00000020
-#define PTRACE_O_TRACEEXIT 0x00000040
-
-/* Wait extended result codes for the above trace options. */
-#define PTRACE_EVENT_FORK 1
-#define PTRACE_EVENT_VFORK 2
-#define PTRACE_EVENT_CLONE 3
-#define PTRACE_EVENT_EXEC 4
-#define PTRACE_EVENT_VFORK_DONE 5
-#define PTRACE_EVENT_EXIT 6
-
-#endif /* PTRACE_EVENT_FORK */
-
-#ifdef ARCH_HAVE_UMOVELONG
-extern int arch_umovelong (Process *, void *, long *, arg_type_info *);
-int
-umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
- return arch_umovelong (proc, addr, result, info);
-}
-#else
-/* Read a single long from the process's memory address 'addr' */
-int
-umovelong (Process *proc, void *addr, long *result, arg_type_info *info) {
- long pointed_to;
+#ifdef HAVE_LIBSELINUX
+# include <selinux/selinux.h>
+#endif
- errno = 0;
- pointed_to = ptrace (PTRACE_PEEKTEXT, proc->pid, addr, 0);
- if (pointed_to == -1 && errno)
- return -errno;
+#include "linux-gnu/trace.h"
+#include "linux-gnu/trace-defs.h"
+#include "backend.h"
+#include "breakpoint.h"
+#include "debug.h"
+#include "events.h"
+#include "options.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
- *result = pointed_to;
- return 0;
+void
+trace_fail_warning(pid_t pid)
+{
+ /* This was adapted from GDB. */
+#ifdef HAVE_LIBSELINUX
+ static int checked = 0;
+ if (checked)
+ return;
+ checked = 1;
+
+ /* -1 is returned for errors, 0 if it has no effect, 1 if
+ * PTRACE_ATTACH is forbidden. */
+ if (security_get_boolean_active("deny_ptrace") == 1)
+ fprintf(stderr,
+"The SELinux boolean 'deny_ptrace' is enabled, which may prevent ltrace from\n"
+"tracing other processes. You can disable this process attach protection by\n"
+"issuing 'setsebool deny_ptrace=0' in the superuser context.\n");
+#endif /* HAVE_LIBSELINUX */
}
-#endif
void
-trace_me(void) {
- debug(DEBUG_PROCESS, "trace_me: pid=%d\n", getpid());
- if (ptrace(PTRACE_TRACEME, 0, 1, 0) < 0) {
+trace_me(void)
+{
+ debug(DEBUG_PROCESS, "trace_me: pid=%d", getpid());
+ if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
perror("PTRACE_TRACEME");
+ trace_fail_warning(getpid());
exit(1);
}
}
+/* There's a (hopefully) brief period of time after the child process
+ * forks when we can't trace it yet. Here we wait for kernel to
+ * prepare the process. */
int
-trace_pid(pid_t pid) {
- debug(DEBUG_PROCESS, "trace_pid: pid=%d\n", pid);
- if (ptrace(PTRACE_ATTACH, pid, 1, 0) < 0) {
- return -1;
- }
-
+wait_for_proc(pid_t pid)
+{
/* man ptrace: PTRACE_ATTACH attaches to the process specified
in pid. The child is sent a SIGSTOP, but will not
necessarily have stopped by the completion of this call;
use wait() to wait for the child to stop. */
- if (waitpid (pid, NULL, 0) != pid) {
+ if (waitpid(pid, NULL, __WALL) != pid) {
perror ("trace_pid: waitpid");
- exit (1);
+ return -1;
}
return 0;
}
+int
+trace_pid(pid_t pid)
+{
+ debug(DEBUG_PROCESS, "trace_pid: pid=%d", pid);
+ /* This shouldn't emit error messages, as there are legitimate
+ * reasons that the PID can't be attached: like it may have
+ * already ended. */
+ if (ptrace(PTRACE_ATTACH, pid, 0, 0) < 0)
+ return -1;
+
+ return wait_for_proc(pid);
+}
+
void
-trace_set_options(Process *proc, pid_t pid) {
+trace_set_options(struct Process *proc)
+{
if (proc->tracesysgood & 0x80)
return;
- debug(DEBUG_PROCESS, "trace_set_options: pid=%d\n", pid);
+ pid_t pid = proc->pid;
+ debug(DEBUG_PROCESS, "trace_set_options: pid=%d", pid);
long options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |
PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE |
PTRACE_O_TRACEEXEC;
- if (ptrace(PTRACE_SETOPTIONS, pid, 0, options) < 0 &&
- ptrace(PTRACE_OLDSETOPTIONS, pid, 0, options) < 0) {
+ if (ptrace(PTRACE_SETOPTIONS, pid, 0, (void *)options) < 0 &&
+ ptrace(PTRACE_OLDSETOPTIONS, pid, 0, (void *)options) < 0) {
perror("PTRACE_SETOPTIONS");
return;
}
@@ -107,87 +132,1077 @@ trace_set_options(Process *proc, pid_t pid) {
void
untrace_pid(pid_t pid) {
- debug(DEBUG_PROCESS, "untrace_pid: pid=%d\n", pid);
- ptrace(PTRACE_DETACH, pid, 1, 0);
+ debug(DEBUG_PROCESS, "untrace_pid: pid=%d", pid);
+ ptrace(PTRACE_DETACH, pid, 0, 0);
}
void
-continue_after_signal(pid_t pid, int signum) {
- Process *proc;
+continue_after_signal(pid_t pid, int signum)
+{
+ debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d",
+ pid, signum);
+ ptrace(PTRACE_SYSCALL, pid, 0, (void *)(uintptr_t)signum);
+}
- debug(DEBUG_PROCESS, "continue_after_signal: pid=%d, signum=%d", pid, signum);
+static enum ecb_status
+event_for_pid(Event *event, void *data)
+{
+ if (event->proc != NULL && event->proc->pid == (pid_t)(uintptr_t)data)
+ return ecb_yield;
+ return ecb_cont;
+}
- proc = pid2proc(pid);
- if (proc && proc->breakpoint_being_enabled) {
-#if defined __sparc__ || defined __ia64___
- ptrace(PTRACE_SYSCALL, pid, 0, signum);
-#else
- ptrace(PTRACE_SINGLESTEP, pid, 0, signum);
-#endif
+static int
+have_events_for(pid_t pid)
+{
+ return each_qd_event(event_for_pid, (void *)(uintptr_t)pid) != NULL;
+}
+
+void
+continue_process(pid_t pid)
+{
+ debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
+
+ /* Only really continue the process if there are no events in
+ the queue for this process. Otherwise just wait for the
+ other events to arrive. */
+ if (!have_events_for(pid))
+ /* We always trace syscalls to control fork(),
+ * clone(), execve()... */
+ ptrace(PTRACE_SYSCALL, pid, 0, 0);
+ else
+ debug(DEBUG_PROCESS,
+ "putting off the continue, events in que.");
+}
+
+static struct pid_task *
+get_task_info(struct pid_set *pids, pid_t pid)
+{
+ assert(pid != 0);
+ size_t i;
+ for (i = 0; i < pids->count; ++i)
+ if (pids->tasks[i].pid == pid)
+ return &pids->tasks[i];
+
+ return NULL;
+}
+
+static struct pid_task *
+add_task_info(struct pid_set *pids, pid_t pid)
+{
+ if (pids->count == pids->alloc) {
+ size_t ns = (2 * pids->alloc) ?: 4;
+ struct pid_task *n = realloc(pids->tasks,
+ sizeof(*pids->tasks) * ns);
+ if (n == NULL)
+ return NULL;
+ pids->tasks = n;
+ pids->alloc = ns;
+ }
+ struct pid_task * task_info = &pids->tasks[pids->count++];
+ memset(task_info, 0, sizeof(*task_info));
+ task_info->pid = pid;
+ return task_info;
+}
+
+static enum callback_status
+task_stopped(struct Process *task, void *data)
+{
+ enum process_status st = process_status(task->pid);
+ if (data != NULL)
+ *(enum process_status *)data = st;
+
+ /* If the task is already stopped, don't worry about it.
+ * Likewise if it managed to become a zombie or terminate in
+ * the meantime. This can happen when the whole thread group
+ * is terminating. */
+ switch (st) {
+ case ps_invalid:
+ case ps_tracing_stop:
+ case ps_zombie:
+ return CBS_CONT;
+ case ps_sleeping:
+ case ps_stop:
+ case ps_other:
+ return CBS_STOP;
+ }
+
+ abort ();
+}
+
+/* Task is blocked if it's stopped, or if it's a vfork parent. */
+static enum callback_status
+task_blocked(struct Process *task, void *data)
+{
+ struct pid_set *pids = data;
+ struct pid_task *task_info = get_task_info(pids, task->pid);
+ if (task_info != NULL
+ && task_info->vforked)
+ return CBS_CONT;
+
+ return task_stopped(task, NULL);
+}
+
+static Event *process_vfork_on_event(struct event_handler *super, Event *event);
+
+static enum callback_status
+task_vforked(struct Process *task, void *data)
+{
+ if (task->event_handler != NULL
+ && task->event_handler->on_event == &process_vfork_on_event)
+ return CBS_STOP;
+ return CBS_CONT;
+}
+
+static int
+is_vfork_parent(struct Process *task)
+{
+ return each_task(task->leader, NULL, &task_vforked, NULL) != NULL;
+}
+
+static enum callback_status
+send_sigstop(struct Process *task, void *data)
+{
+ struct Process *leader = task->leader;
+ struct pid_set *pids = data;
+
+ /* Look for pre-existing task record, or add new. */
+ struct pid_task *task_info = get_task_info(pids, task->pid);
+ if (task_info == NULL)
+ task_info = add_task_info(pids, task->pid);
+ if (task_info == NULL) {
+ perror("send_sigstop: add_task_info");
+ destroy_event_handler(leader);
+ /* Signal failure upwards. */
+ return CBS_STOP;
+ }
+
+ /* This task still has not been attached to. It should be
+ stopped by the kernel. */
+ if (task->state == STATE_BEING_CREATED)
+ return CBS_CONT;
+
+ /* Don't bother sending SIGSTOP if we are already stopped, or
+ * if we sent the SIGSTOP already, which happens when we are
+ * handling "onexit" and inherited the handler from breakpoint
+ * re-enablement. */
+ enum process_status st;
+ if (task_stopped(task, &st) == CBS_CONT)
+ return CBS_CONT;
+ if (task_info->sigstopped) {
+ if (!task_info->delivered)
+ return CBS_CONT;
+ task_info->delivered = 0;
+ }
+
+ /* Also don't attempt to stop the process if it's a parent of
+ * vforked process. We set up event handler specially to hint
+ * us. In that case parent is in D state, which we use to
+ * weed out unnecessary looping. */
+ if (st == ps_sleeping
+ && is_vfork_parent (task)) {
+ task_info->vforked = 1;
+ return CBS_CONT;
+ }
+
+ if (task_kill(task->pid, SIGSTOP) >= 0) {
+ debug(DEBUG_PROCESS, "send SIGSTOP to %d", task->pid);
+ task_info->sigstopped = 1;
+ } else
+ fprintf(stderr,
+ "Warning: couldn't send SIGSTOP to %d\n", task->pid);
+
+ return CBS_CONT;
+}
+
+/* On certain kernels, detaching right after a singlestep causes the
+ tracee to be killed with a SIGTRAP (that even though the singlestep
+ was properly caught by waitpid. The ugly workaround is to put a
+ breakpoint where IP points and let the process continue. After
+ this the breakpoint can be retracted and the process detached. */
+static void
+ugly_workaround(struct Process *proc)
+{
+ void *ip = get_instruction_pointer(proc);
+ struct breakpoint *sbp = dict_find_entry(proc->leader->breakpoints, ip);
+ if (sbp != NULL)
+ enable_breakpoint(proc, sbp);
+ else
+ insert_breakpoint(proc, ip, NULL);
+ ptrace(PTRACE_CONT, proc->pid, 0, 0);
+}
+
+static void
+process_stopping_done(struct process_stopping_handler *self,
+ struct Process *leader)
+{
+ debug(DEBUG_PROCESS, "process stopping done %d",
+ self->task_enabling_breakpoint->pid);
+
+ if (!self->exiting) {
+ size_t i;
+ for (i = 0; i < self->pids.count; ++i)
+ if (self->pids.tasks[i].pid != 0
+ && (self->pids.tasks[i].delivered
+ || self->pids.tasks[i].sysret))
+ continue_process(self->pids.tasks[i].pid);
+ continue_process(self->task_enabling_breakpoint->pid);
+ }
+
+ if (self->exiting) {
+ ugly_workaround:
+ self->state = psh_ugly_workaround;
+ ugly_workaround(self->task_enabling_breakpoint);
} else {
- ptrace(PTRACE_SYSCALL, pid, 0, signum);
+ switch ((self->ugly_workaround_p)(self)) {
+ case CBS_FAIL:
+ /* xxx handle me */
+ case CBS_STOP:
+ break;
+ case CBS_CONT:
+ goto ugly_workaround;
+ }
+ destroy_event_handler(leader);
}
}
-void
-continue_process(pid_t pid) {
- /* We always trace syscalls to control fork(), clone(), execve()... */
+/* Before we detach, we need to make sure that task's IP is on the
+ * edge of an instruction. So for tasks that have a breakpoint event
+ * in the queue, we adjust the instruction pointer, just like
+ * continue_after_breakpoint does. */
+static enum ecb_status
+undo_breakpoint(Event *event, void *data)
+{
+ if (event != NULL
+ && event->proc->leader == data
+ && event->type == EVENT_BREAKPOINT)
+ set_instruction_pointer(event->proc, event->e_un.brk_addr);
+ return ecb_cont;
+}
- debug(DEBUG_PROCESS, "continue_process: pid=%d", pid);
+static enum callback_status
+untrace_task(struct Process *task, void *data)
+{
+ if (task != data)
+ untrace_pid(task->pid);
+ return CBS_CONT;
+}
+
+static enum callback_status
+remove_task(struct Process *task, void *data)
+{
+ /* Don't untrace leader just yet. */
+ if (task != data)
+ remove_process(task);
+ return CBS_CONT;
+}
+
+static enum callback_status
+retract_breakpoint_cb(struct Process *proc, struct breakpoint *bp, void *data)
+{
+ breakpoint_on_retract(bp, proc);
+ return CBS_CONT;
+}
+
+static void
+detach_process(struct Process *leader)
+{
+ each_qd_event(&undo_breakpoint, leader);
+ disable_all_breakpoints(leader);
+ proc_each_breakpoint(leader, NULL, retract_breakpoint_cb, NULL);
+
+ /* Now untrace the process, if it was attached to by -p. */
+ struct opt_p_t *it;
+ for (it = opt_p; it != NULL; it = it->next) {
+ struct Process *proc = pid2proc(it->pid);
+ if (proc == NULL)
+ continue;
+ if (proc->leader == leader) {
+ each_task(leader, NULL, &untrace_task, NULL);
+ break;
+ }
+ }
+ each_task(leader, NULL, &remove_task, leader);
+ destroy_event_handler(leader);
+ remove_task(leader, NULL);
+}
+
+static void
+handle_stopping_event(struct pid_task *task_info, Event **eventp)
+{
+ /* Mark all events, so that we know whom to SIGCONT later. */
+ if (task_info != NULL)
+ task_info->got_event = 1;
+
+ Event *event = *eventp;
+
+ /* In every state, sink SIGSTOP events for tasks that it was
+ * sent to. */
+ if (task_info != NULL
+ && event->type == EVENT_SIGNAL
+ && event->e_un.signum == SIGSTOP) {
+ debug(DEBUG_PROCESS, "SIGSTOP delivered to %d", task_info->pid);
+ if (task_info->sigstopped
+ && !task_info->delivered) {
+ task_info->delivered = 1;
+ *eventp = NULL; // sink the event
+ } else
+ fprintf(stderr, "suspicious: %d got SIGSTOP, but "
+ "sigstopped=%d and delivered=%d\n",
+ task_info->pid, task_info->sigstopped,
+ task_info->delivered);
+ }
+}
+
+/* Some SIGSTOPs may have not been delivered to their respective tasks
+ * yet. They are still in the queue. If we have seen an event for
+ * that process, continue it, so that the SIGSTOP can be delivered and
+ * caught by ltrace. We don't mind that the process is after
+ * breakpoint (and therefore potentially doesn't have aligned IP),
+ * because the signal will be delivered without the process actually
+ * starting. */
+static void
+continue_for_sigstop_delivery(struct pid_set *pids)
+{
+ size_t i;
+ for (i = 0; i < pids->count; ++i) {
+ if (pids->tasks[i].pid != 0
+ && pids->tasks[i].sigstopped
+ && !pids->tasks[i].delivered
+ && pids->tasks[i].got_event) {
+ debug(DEBUG_PROCESS, "continue %d for SIGSTOP delivery",
+ pids->tasks[i].pid);
+ ptrace(PTRACE_SYSCALL, pids->tasks[i].pid, 0, 0);
+ }
+ }
+}
+
+static int
+event_exit_p(Event *event)
+{
+ return event != NULL && (event->type == EVENT_EXIT
+ || event->type == EVENT_EXIT_SIGNAL);
+}
- ptrace(PTRACE_SYSCALL, pid, 0, 0);
+static int
+event_exit_or_none_p(Event *event)
+{
+ return event == NULL || event_exit_p(event)
+ || event->type == EVENT_NONE;
+}
+
+static int
+await_sigstop_delivery(struct pid_set *pids, struct pid_task *task_info,
+ Event *event)
+{
+ /* If we still didn't get our SIGSTOP, continue the process
+ * and carry on. */
+ if (event != NULL && !event_exit_or_none_p(event)
+ && task_info != NULL && task_info->sigstopped) {
+ debug(DEBUG_PROCESS, "continue %d for SIGSTOP delivery",
+ task_info->pid);
+ /* We should get the signal the first thing
+ * after this, so it should be OK to continue
+ * even if we are over a breakpoint. */
+ ptrace(PTRACE_SYSCALL, task_info->pid, 0, 0);
+
+ } else {
+ /* If all SIGSTOPs were delivered, uninstall the
+ * handler and continue everyone. */
+ /* XXX I suspect that we should check tasks that are
+ * still around. Is things are now, there should be a
+ * race between waiting for everyone to stop and one
+ * of the tasks exiting. */
+ int all_clear = 1;
+ size_t i;
+ for (i = 0; i < pids->count; ++i)
+ if (pids->tasks[i].pid != 0
+ && pids->tasks[i].sigstopped
+ && !pids->tasks[i].delivered) {
+ all_clear = 0;
+ break;
+ }
+ return all_clear;
+ }
+
+ return 0;
+}
+
+static int
+all_stops_accountable(struct pid_set *pids)
+{
+ size_t i;
+ for (i = 0; i < pids->count; ++i)
+ if (pids->tasks[i].pid != 0
+ && !pids->tasks[i].got_event
+ && !have_events_for(pids->tasks[i].pid))
+ return 0;
+ return 1;
+}
+
+/* The protocol is: 0 for success, negative for failure, positive if
+ * default singlestep is to be used. */
+int arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
+ int (*add_cb)(void *addr, void *data),
+ void *add_cb_data);
+
+#ifndef ARCH_HAVE_ATOMIC_SINGLESTEP
+int
+arch_atomic_singlestep(struct Process *proc, struct breakpoint *sbp,
+ int (*add_cb)(void *addr, void *data),
+ void *add_cb_data)
+{
+ return 1;
+}
+#endif
+
+static Event *process_stopping_on_event(struct event_handler *super,
+ Event *event);
+
+static void
+remove_atomic_breakpoints(struct Process *proc)
+{
+ struct process_stopping_handler *self
+ = (void *)proc->leader->event_handler;
+ assert(self != NULL);
+ assert(self->super.on_event == process_stopping_on_event);
+
+ int ct = sizeof(self->atomic_skip_bp_addrs)
+ / sizeof(*self->atomic_skip_bp_addrs);
+ int i;
+ for (i = 0; i < ct; ++i)
+ if (self->atomic_skip_bp_addrs[i] != 0) {
+ delete_breakpoint(proc, self->atomic_skip_bp_addrs[i]);
+ self->atomic_skip_bp_addrs[i] = 0;
+ }
+}
+
+static void
+atomic_singlestep_bp_on_hit(struct breakpoint *bp, struct Process *proc)
+{
+ remove_atomic_breakpoints(proc);
+}
+
+static int
+atomic_singlestep_add_bp(void *addr, void *data)
+{
+ struct process_stopping_handler *self = data;
+ struct Process *proc = self->task_enabling_breakpoint;
+
+ int ct = sizeof(self->atomic_skip_bp_addrs)
+ / sizeof(*self->atomic_skip_bp_addrs);
+ int i;
+ for (i = 0; i < ct; ++i)
+ if (self->atomic_skip_bp_addrs[i] == 0) {
+ self->atomic_skip_bp_addrs[i] = addr;
+ static struct bp_callbacks cbs = {
+ .on_hit = atomic_singlestep_bp_on_hit,
+ };
+ struct breakpoint *bp
+ = insert_breakpoint(proc, addr, NULL);
+ breakpoint_set_callbacks(bp, &cbs);
+ return 0;
+ }
+
+ assert(!"Too many atomic singlestep breakpoints!");
+ abort();
+}
+
+static int
+singlestep(struct process_stopping_handler *self)
+{
+ struct Process *proc = self->task_enabling_breakpoint;
+
+ int status = arch_atomic_singlestep(self->task_enabling_breakpoint,
+ self->breakpoint_being_enabled,
+ &atomic_singlestep_add_bp, self);
+
+ /* Propagate failure and success. */
+ if (status <= 0)
+ return status;
+
+ /* Otherwise do the default action: singlestep. */
+ debug(1, "PTRACE_SINGLESTEP");
+ if (ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0)) {
+ perror("PTRACE_SINGLESTEP");
+ return -1;
+ }
+ return 0;
+}
+
+static void
+post_singlestep(struct process_stopping_handler *self,
+ struct Event **eventp)
+{
+ continue_for_sigstop_delivery(&self->pids);
+
+ if (*eventp != NULL && (*eventp)->type == EVENT_BREAKPOINT)
+ *eventp = NULL; // handled
+
+ struct Process *proc = self->task_enabling_breakpoint;
+
+ remove_atomic_breakpoints(proc);
+ self->breakpoint_being_enabled = NULL;
+}
+
+static void
+singlestep_error(struct process_stopping_handler *self)
+{
+ struct Process *teb = self->task_enabling_breakpoint;
+ struct breakpoint *sbp = self->breakpoint_being_enabled;
+ fprintf(stderr, "%d couldn't continue when handling %s (%p) at %p\n",
+ teb->pid, breakpoint_name(sbp), sbp->addr,
+ get_instruction_pointer(teb));
+ delete_breakpoint(teb->leader, sbp->addr);
+}
+
+static void
+pt_continue(struct process_stopping_handler *self)
+{
+ struct Process *teb = self->task_enabling_breakpoint;
+ debug(1, "PTRACE_CONT");
+ ptrace(PTRACE_CONT, teb->pid, 0, 0);
+}
+
+static void
+pt_singlestep(struct process_stopping_handler *self)
+{
+ if (singlestep(self) < 0)
+ singlestep_error(self);
+}
+
+static void
+disable_and(struct process_stopping_handler *self,
+ void (*do_this)(struct process_stopping_handler *self))
+{
+ struct Process *teb = self->task_enabling_breakpoint;
+ debug(DEBUG_PROCESS, "all stopped, now singlestep/cont %d", teb->pid);
+ if (self->breakpoint_being_enabled->enabled)
+ disable_breakpoint(teb, self->breakpoint_being_enabled);
+ (do_this)(self);
+ self->state = psh_singlestep;
+}
+
+void
+linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self)
+{
+ disable_and(self, &pt_singlestep);
}
void
-continue_enabling_breakpoint(pid_t pid, Breakpoint *sbp) {
- enable_breakpoint(pid, sbp);
- continue_process(pid);
+linux_ptrace_disable_and_continue(struct process_stopping_handler *self)
+{
+ disable_and(self, &pt_continue);
+}
+
+/* This event handler is installed when we are in the process of
+ * stopping the whole thread group to do the pointer re-enablement for
+ * one of the threads. We pump all events to the queue for later
+ * processing while we wait for all the threads to stop. When this
+ * happens, we let the re-enablement thread to PTRACE_SINGLESTEP,
+ * re-enable, and continue everyone. */
+static Event *
+process_stopping_on_event(struct event_handler *super, Event *event)
+{
+ struct process_stopping_handler *self = (void *)super;
+ struct Process *task = event->proc;
+ struct Process *leader = task->leader;
+ struct Process *teb = self->task_enabling_breakpoint;
+
+ debug(DEBUG_PROCESS,
+ "process_stopping_on_event: pid %d; event type %d; state %d",
+ task->pid, event->type, self->state);
+
+ struct pid_task *task_info = get_task_info(&self->pids, task->pid);
+ if (task_info == NULL)
+ fprintf(stderr, "new task??? %d\n", task->pid);
+ handle_stopping_event(task_info, &event);
+
+ int state = self->state;
+ int event_to_queue = !event_exit_or_none_p(event);
+
+ /* Deactivate the entry if the task exits. */
+ if (event_exit_p(event) && task_info != NULL)
+ task_info->pid = 0;
+
+ /* Always handle sysrets. Whether sysret occurred and what
+ * sys it rets from may need to be determined based on process
+ * stack, so we need to keep that in sync with reality. Note
+ * that we don't continue the process after the sysret is
+ * handled. See continue_after_syscall. */
+ if (event != NULL && event->type == EVENT_SYSRET) {
+ debug(1, "%d LT_EV_SYSRET", event->proc->pid);
+ event_to_queue = 0;
+ task_info->sysret = 1;
+ }
+
+ switch (state) {
+ case psh_stopping:
+ /* If everyone is stopped, singlestep. */
+ if (each_task(leader, NULL, &task_blocked,
+ &self->pids) == NULL) {
+ (self->on_all_stopped)(self);
+ state = self->state;
+ }
+ break;
+
+ case psh_singlestep:
+ /* In singlestep state, breakpoint signifies that we
+ * have now stepped, and can re-enable the breakpoint. */
+ if (event != NULL && task == teb) {
+
+ /* If this was caused by a real breakpoint, as
+ * opposed to a singlestep, assume that it's
+ * an artificial breakpoint installed for some
+ * reason for the re-enablement. In that case
+ * handle it. */
+ if (event->type == EVENT_BREAKPOINT) {
+ arch_addr_t ip
+ = get_instruction_pointer(task);
+ struct breakpoint *other
+ = address2bpstruct(leader, ip);
+ if (other != NULL)
+ breakpoint_on_hit(other, task);
+ }
+
+ /* If we got SIGNAL instead of BREAKPOINT,
+ * then this is not singlestep at all. */
+ if (event->type == EVENT_SIGNAL) {
+ do_singlestep:
+ if (singlestep(self) < 0) {
+ singlestep_error(self);
+ post_singlestep(self, &event);
+ goto psh_sinking;
+ }
+ break;
+ } else {
+ switch ((self->keep_stepping_p)(self)) {
+ case CBS_FAIL:
+ /* XXX handle me */
+ case CBS_STOP:
+ break;
+ case CBS_CONT:
+ /* Sink singlestep event. */
+ if (event->type == EVENT_BREAKPOINT)
+ event = NULL;
+ goto do_singlestep;
+ }
+ }
+
+ /* Re-enable the breakpoint that we are
+ * stepping over. */
+ struct breakpoint *sbp = self->breakpoint_being_enabled;
+ if (sbp->enabled)
+ enable_breakpoint(teb, sbp);
+
+ post_singlestep(self, &event);
+ goto psh_sinking;
+ }
+ break;
+
+ psh_sinking:
+ state = self->state = psh_sinking;
+ case psh_sinking:
+ if (await_sigstop_delivery(&self->pids, task_info, event))
+ process_stopping_done(self, leader);
+ break;
+
+ case psh_ugly_workaround:
+ if (event == NULL)
+ break;
+ if (event->type == EVENT_BREAKPOINT) {
+ undo_breakpoint(event, leader);
+ if (task == teb)
+ self->task_enabling_breakpoint = NULL;
+ }
+ if (self->task_enabling_breakpoint == NULL
+ && all_stops_accountable(&self->pids)) {
+ undo_breakpoint(event, leader);
+ detach_process(leader);
+ event = NULL; // handled
+ }
+ }
+
+ if (event != NULL && event_to_queue) {
+ enque_event(event);
+ event = NULL; // sink the event
+ }
+
+ return event;
+}
+
+static void
+process_stopping_destroy(struct event_handler *super)
+{
+ struct process_stopping_handler *self = (void *)super;
+ free(self->pids.tasks);
+}
+
+static enum callback_status
+no(struct process_stopping_handler *self)
+{
+ return CBS_STOP;
+}
+
+int
+process_install_stopping_handler(struct Process *proc, struct breakpoint *sbp,
+ void (*as)(struct process_stopping_handler *),
+ enum callback_status (*ks)
+ (struct process_stopping_handler *),
+ enum callback_status (*uw)
+ (struct process_stopping_handler *))
+{
+ debug(DEBUG_FUNCTION,
+ "process_install_stopping_handler: pid=%d", proc->pid);
+
+ struct process_stopping_handler *handler = calloc(sizeof(*handler), 1);
+ if (handler == NULL)
+ return -1;
+
+ if (as == NULL)
+ as = &linux_ptrace_disable_and_singlestep;
+ if (ks == NULL)
+ ks = &no;
+ if (uw == NULL)
+ uw = &no;
+
+ handler->super.on_event = process_stopping_on_event;
+ handler->super.destroy = process_stopping_destroy;
+ handler->task_enabling_breakpoint = proc;
+ handler->breakpoint_being_enabled = sbp;
+ handler->on_all_stopped = as;
+ handler->keep_stepping_p = ks;
+ handler->ugly_workaround_p = uw;
+
+ install_event_handler(proc->leader, &handler->super);
+
+ if (each_task(proc->leader, NULL, &send_sigstop,
+ &handler->pids) != NULL) {
+ destroy_event_handler(proc);
+ return -1;
+ }
+
+ /* And deliver the first fake event, in case all the
+ * conditions are already fulfilled. */
+ Event ev = {
+ .type = EVENT_NONE,
+ .proc = proc,
+ };
+ process_stopping_on_event(&handler->super, &ev);
+
+ return 0;
}
void
-continue_after_breakpoint(Process *proc, Breakpoint *sbp) {
- if (sbp->enabled)
- disable_breakpoint(proc->pid, sbp);
+continue_after_breakpoint(Process *proc, struct breakpoint *sbp)
+{
+ debug(DEBUG_PROCESS,
+ "continue_after_breakpoint: pid=%d, addr=%p",
+ proc->pid, sbp->addr);
+
set_instruction_pointer(proc, sbp->addr);
+
if (sbp->enabled == 0) {
continue_process(proc->pid);
} else {
- debug(DEBUG_PROCESS, "continue_after_breakpoint: pid=%d, addr=%p", proc->pid, sbp->addr);
- proc->breakpoint_being_enabled = sbp;
#if defined __sparc__ || defined __ia64___
/* we don't want to singlestep here */
continue_process(proc->pid);
#else
- ptrace(PTRACE_SINGLESTEP, proc->pid, 0, 0);
+ if (process_install_stopping_handler
+ (proc, sbp, NULL, NULL, NULL) < 0) {
+ perror("process_stopping_handler_create");
+ /* Carry on not bothering to re-enable. */
+ continue_process(proc->pid);
+ }
#endif
}
}
-/* Read a series of bytes starting at the process's memory address
- 'addr' and continuing until a NUL ('\0') is seen or 'len' bytes
- have been read.
-*/
+/**
+ * Ltrace exit. When we are about to exit, we have to go through all
+ * the processes, stop them all, remove all the breakpoints, and then
+ * detach the processes that we attached to using -p. If we left the
+ * other tasks running, they might hit stray return breakpoints and
+ * produce artifacts, so we better stop everyone, even if it's a bit
+ * of extra work.
+ */
+struct ltrace_exiting_handler
+{
+ struct event_handler super;
+ struct pid_set pids;
+};
+
+static Event *
+ltrace_exiting_on_event(struct event_handler *super, Event *event)
+{
+ struct ltrace_exiting_handler *self = (void *)super;
+ struct Process *task = event->proc;
+ struct Process *leader = task->leader;
+
+ debug(DEBUG_PROCESS,
+ "ltrace_exiting_on_event: pid %d; event type %d",
+ task->pid, event->type);
+
+ struct pid_task *task_info = get_task_info(&self->pids, task->pid);
+ handle_stopping_event(task_info, &event);
+
+ if (event != NULL && event->type == EVENT_BREAKPOINT)
+ undo_breakpoint(event, leader);
+
+ if (await_sigstop_delivery(&self->pids, task_info, event)
+ && all_stops_accountable(&self->pids))
+ detach_process(leader);
+
+ /* Sink all non-exit events. We are about to exit, so we
+ * don't bother with queuing them. */
+ if (event_exit_or_none_p(event))
+ return event;
+
+ return NULL;
+}
+
+static void
+ltrace_exiting_destroy(struct event_handler *super)
+{
+ struct ltrace_exiting_handler *self = (void *)super;
+ free(self->pids.tasks);
+}
+
+static int
+ltrace_exiting_install_handler(struct Process *proc)
+{
+ /* Only install to leader. */
+ if (proc->leader != proc)
+ return 0;
+
+ /* Perhaps we are already installed, if the user passed
+ * several -p options that are tasks of one process. */
+ if (proc->event_handler != NULL
+ && proc->event_handler->on_event == &ltrace_exiting_on_event)
+ return 0;
+
+ /* If stopping handler is already present, let it do the
+ * work. */
+ if (proc->event_handler != NULL) {
+ assert(proc->event_handler->on_event
+ == &process_stopping_on_event);
+ struct process_stopping_handler *other
+ = (void *)proc->event_handler;
+ other->exiting = 1;
+ return 0;
+ }
+
+ struct ltrace_exiting_handler *handler
+ = calloc(sizeof(*handler), 1);
+ if (handler == NULL) {
+ perror("malloc exiting handler");
+ fatal:
+ /* XXXXXXXXXXXXXXXXXXX fixme */
+ return -1;
+ }
+
+ handler->super.on_event = ltrace_exiting_on_event;
+ handler->super.destroy = ltrace_exiting_destroy;
+ install_event_handler(proc->leader, &handler->super);
+
+ if (each_task(proc->leader, NULL, &send_sigstop,
+ &handler->pids) != NULL)
+ goto fatal;
+
+ return 0;
+}
+
+/*
+ * When the traced process vforks, it's suspended until the child
+ * process calls _exit or exec*. In the meantime, the two share the
+ * address space.
+ *
+ * The child process should only ever call _exit or exec*, but we
+ * can't count on that (it's not the role of ltrace to policy, but to
+ * observe). In any case, we will _at least_ have to deal with
+ * removal of vfork return breakpoint (which we have to smuggle back
+ * in, so that the parent can see it, too), and introduction of exec*
+ * return breakpoint. Since we already have both breakpoint actions
+ * to deal with, we might as well support it all.
+ *
+ * The gist is that we pretend that the child is in a thread group
+ * with its parent, and handle it as a multi-threaded case, with the
+ * exception that we know that the parent is blocked, and don't
+ * attempt to stop it. When the child execs, we undo the setup.
+ */
+
+struct process_vfork_handler
+{
+ struct event_handler super;
+ void *bp_addr;
+};
+
+static Event *
+process_vfork_on_event(struct event_handler *super, Event *event)
+{
+ debug(DEBUG_PROCESS,
+ "process_vfork_on_event: pid %d; event type %d",
+ event->proc->pid, event->type);
+
+ struct process_vfork_handler *self = (void *)super;
+ struct breakpoint *sbp;
+ assert(self != NULL);
+
+ switch (event->type) {
+ case EVENT_BREAKPOINT:
+ /* Remember the vfork return breakpoint. */
+ if (self->bp_addr == 0)
+ self->bp_addr = event->e_un.brk_addr;
+ break;
+
+ case EVENT_EXIT:
+ case EVENT_EXIT_SIGNAL:
+ case EVENT_EXEC:
+ /* Smuggle back in the vfork return breakpoint, so
+ * that our parent can trip over it once again. */
+ if (self->bp_addr != 0) {
+ sbp = dict_find_entry(event->proc->leader->breakpoints,
+ self->bp_addr);
+ if (sbp != NULL)
+ assert(sbp->libsym == NULL);
+ /* We don't mind failing that, it's not a big
+ * deal to not display one extra vfork return. */
+ insert_breakpoint(event->proc->parent,
+ self->bp_addr, NULL);
+ }
+
+ continue_process(event->proc->parent->pid);
+
+ /* Remove the leader that we artificially set up
+ * earlier. */
+ change_process_leader(event->proc, event->proc);
+ destroy_event_handler(event->proc);
+
+ default:
+ ;
+ }
+
+ return event;
+}
+
+void
+continue_after_vfork(struct Process *proc)
+{
+ debug(DEBUG_PROCESS, "continue_after_vfork: pid=%d", proc->pid);
+ struct process_vfork_handler *handler = calloc(sizeof(*handler), 1);
+ if (handler == NULL) {
+ perror("malloc vfork handler");
+ /* Carry on not bothering to treat the process as
+ * necessary. */
+ continue_process(proc->parent->pid);
+ return;
+ }
+
+ /* We must set up custom event handler, so that we see
+ * exec/exit events for the task itself. */
+ handler->super.on_event = process_vfork_on_event;
+ install_event_handler(proc, &handler->super);
+
+ /* Make sure that the child is sole thread. */
+ assert(proc->leader == proc);
+ assert(proc->next == NULL || proc->next->leader != proc);
+
+ /* Make sure that the child's parent is properly set up. */
+ assert(proc->parent != NULL);
+ assert(proc->parent->leader != NULL);
+
+ change_process_leader(proc, proc->parent->leader);
+}
+
+static int
+is_mid_stopping(Process *proc)
+{
+ return proc != NULL
+ && proc->event_handler != NULL
+ && proc->event_handler->on_event == &process_stopping_on_event;
+}
+
+void
+continue_after_syscall(struct Process *proc, int sysnum, int ret_p)
+{
+ /* Don't continue if we are mid-stopping. */
+ if (ret_p && (is_mid_stopping(proc) || is_mid_stopping(proc->leader))) {
+ debug(DEBUG_PROCESS,
+ "continue_after_syscall: don't continue %d",
+ proc->pid);
+ return;
+ }
+ continue_process(proc->pid);
+}
+
+/* If ltrace gets SIGINT, the processes directly or indirectly run by
+ * ltrace get it too. We just have to wait long enough for the signal
+ * to be delivered and the process terminated, which we notice and
+ * exit ltrace, too. So there's not much we need to do there. We
+ * want to keep tracing those processes as usual, in case they just
+ * SIG_IGN the SIGINT to do their shutdown etc.
+ *
+ * For processes ran on the background, we want to install an exit
+ * handler that stops all the threads, removes all breakpoints, and
+ * detaches.
+ */
+void
+os_ltrace_exiting(void)
+{
+ struct opt_p_t *it;
+ for (it = opt_p; it != NULL; it = it->next) {
+ struct Process *proc = pid2proc(it->pid);
+ if (proc == NULL || proc->leader == NULL)
+ continue;
+ if (ltrace_exiting_install_handler(proc->leader) < 0)
+ fprintf(stderr,
+ "Couldn't install exiting handler for %d.\n",
+ proc->pid);
+ }
+}
+
int
-umovestr(Process *proc, void *addr, int len, void *laddr) {
+os_ltrace_exiting_sighandler(void)
+{
+ extern int linux_in_waitpid;
+ if (linux_in_waitpid) {
+ os_ltrace_exiting();
+ return 1;
+ }
+ return 0;
+}
+
+size_t
+umovebytes(Process *proc, void *addr, void *laddr, size_t len) {
+
union {
long a;
char c[sizeof(long)];
} a;
- int i;
- int offset = 0;
+ int started = 0;
+ size_t offset = 0, bytes_read = 0;
while (offset < len) {
a.a = ptrace(PTRACE_PEEKTEXT, proc->pid, addr + offset, 0);
- for (i = 0; i < sizeof(long); i++) {
- if (a.c[i] && offset + (signed)i < len) {
- *(char *)(laddr + offset + i) = a.c[i];
- } else {
- *(char *)(laddr + offset + i) = '\0';
- return 0;
- }
+ if (a.a == -1 && errno) {
+ if (started && errno == EIO)
+ return bytes_read;
+ else
+ return -1;
+ }
+ started = 1;
+
+ if (len - offset >= sizeof(long)) {
+ memcpy(laddr + offset, &a.c[0], sizeof(long));
+ bytes_read += sizeof(long);
+ }
+ else {
+ memcpy(laddr + offset, &a.c[0], len - offset);
+ bytes_read += (len - offset);
}
offset += sizeof(long);
}
- *(char *)(laddr + offset) = '\0';
- return 0;
+
+ return bytes_read;
}
diff --git a/sysdeps/linux-gnu/trace.h b/sysdeps/linux-gnu/trace.h
new file mode 100644
index 0000000..88ac33d
--- /dev/null
+++ b/sysdeps/linux-gnu/trace.h
@@ -0,0 +1,121 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef _LTRACE_LINUX_TRACE_H_
+#define _LTRACE_LINUX_TRACE_H_
+
+#include "proc.h"
+
+/* This publishes some Linux-specific data structures used for process
+ * handling. */
+
+/**
+ * This is used for bookkeeping related to PIDs that the event
+ * handlers work with.
+ */
+struct pid_task {
+ pid_t pid; /* This may be 0 for tasks that exited
+ * mid-handling. */
+ int sigstopped : 1;
+ int got_event : 1;
+ int delivered : 1;
+ int vforked : 1;
+ int sysret : 1;
+};
+
+struct pid_set {
+ struct pid_task *tasks;
+ size_t count;
+ size_t alloc;
+};
+
+/**
+ * Breakpoint re-enablement. When we hit a breakpoint, we must
+ * disable it, single-step, and re-enable it. That single-step can be
+ * done only by one task in a task group, while others are stopped,
+ * otherwise the processes would race for who sees the breakpoint
+ * disabled and who doesn't. The following is to keep track of it
+ * all.
+ */
+struct process_stopping_handler
+{
+ struct event_handler super;
+
+ /* The task that is doing the re-enablement. */
+ struct Process *task_enabling_breakpoint;
+
+ /* The pointer being re-enabled. */
+ struct breakpoint *breakpoint_being_enabled;
+
+ /* Artificial atomic skip breakpoint, if any needed. */
+ void *atomic_skip_bp_addrs[2];
+
+ /* When all tasks are stopped, this callback gets called. */
+ void (*on_all_stopped)(struct process_stopping_handler *);
+
+ /* When we get a singlestep event, this is called to decide
+ * whether to stop stepping, or whether to enable the
+ * brakpoint, sink remaining signals, and continue
+ * everyone. */
+ enum callback_status (*keep_stepping_p)
+ (struct process_stopping_handler *);
+
+ /* Whether we need to use ugly workaround to get around
+ * various problems with singlestepping. */
+ enum callback_status (*ugly_workaround_p)
+ (struct process_stopping_handler *);
+
+ enum {
+ /* We are waiting for everyone to land in t/T. */
+ psh_stopping = 0,
+
+ /* We are doing the PTRACE_SINGLESTEP. */
+ psh_singlestep,
+
+ /* We are waiting for all the SIGSTOPs to arrive so
+ * that we can sink them. */
+ psh_sinking,
+
+ /* This is for tracking the ugly workaround. */
+ psh_ugly_workaround,
+ } state;
+
+ int exiting;
+
+ struct pid_set pids;
+};
+
+/* Allocate a process stopping handler, initialize it and install it.
+ * Return 0 on success or a negative value on failure. Pass NULL for
+ * each callback to use a default instead. The default for
+ * ON_ALL_STOPPED is LINUX_PTRACE_DISABLE_AND_SINGLESTEP, the default
+ * for KEEP_STEPPING_P and UGLY_WORKAROUND_P is "no". */
+int process_install_stopping_handler
+ (struct Process *proc, struct breakpoint *sbp,
+ void (*on_all_stopped)(struct process_stopping_handler *),
+ enum callback_status (*keep_stepping_p)
+ (struct process_stopping_handler *),
+ enum callback_status (*ugly_workaround_p)
+ (struct process_stopping_handler *));
+
+void linux_ptrace_disable_and_singlestep(struct process_stopping_handler *self);
+void linux_ptrace_disable_and_continue(struct process_stopping_handler *self);
+
+#endif /* _LTRACE_LINUX_TRACE_H_ */
diff --git a/sysdeps/linux-gnu/x86/Makefile.am b/sysdeps/linux-gnu/x86/Makefile.am
new file mode 100644
index 0000000..ee45bab
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/Makefile.am
@@ -0,0 +1,37 @@
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ signalent1.h \
+ syscallent.h \
+ syscallent1.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
diff --git a/sysdeps/linux-gnu/x86/Makefile.in b/sysdeps/linux-gnu/x86/Makefile.in
new file mode 100644
index 0000000..bb7bc9f
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/Makefile.in
@@ -0,0 +1,532 @@
+# Makefile.in generated by automake 1.11.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
+# Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+# This file is part of ltrace.
+# Copyright (C) 2010 Marc Kleine-Budde, Pengutronix
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+# 02110-1301 USA
+
+
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+subdir = sysdeps/linux-gnu/x86
+DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+ $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/config/m4/libtool.m4 \
+ $(top_srcdir)/config/m4/ltoptions.m4 \
+ $(top_srcdir)/config/m4/ltsugar.m4 \
+ $(top_srcdir)/config/m4/ltversion.m4 \
+ $(top_srcdir)/config/m4/lt~obsolete.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+___libcpu_la_LIBADD =
+am____libcpu_la_OBJECTS = plt.lo regs.lo trace.lo fetch.lo
+___libcpu_la_OBJECTS = $(am____libcpu_la_OBJECTS)
+am__dirstamp = $(am__leading_dot)dirstamp
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/config/autoconf/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+SOURCES = $(___libcpu_la_SOURCES)
+DIST_SOURCES = $(___libcpu_la_SOURCES)
+HEADERS = $(noinst_HEADERS)
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_LDFLAGS = @AM_LDFLAGS@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GREP = @GREP@
+HAVE_VALGRIND = @HAVE_VALGRIND@
+HOST_CPU = @HOST_CPU@
+HOST_OS = @HOST_OS@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+RANLIB = @RANLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+VERSION = @VERSION@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libelf_LD_LIBRARY_PATH = @libelf_LD_LIBRARY_PATH@
+liberty_LIBS = @liberty_LIBS@
+libexecdir = @libexecdir@
+libstdcxx_LIBS = @libstdcxx_LIBS@
+libsupcxx_LIBS = @libsupcxx_LIBS@
+libunwind_LD_LIBRARY_PATH = @libunwind_LD_LIBRARY_PATH@
+libunwind_LIBS = @libunwind_LIBS@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+noinst_LTLIBRARIES = \
+ ../libcpu.la
+
+___libcpu_la_SOURCES = \
+ plt.c \
+ regs.c \
+ trace.c \
+ fetch.c
+
+noinst_HEADERS = \
+ arch.h \
+ ptrace.h \
+ signalent.h \
+ signalent1.h \
+ syscallent.h \
+ syscallent1.h
+
+MAINTAINERCLEANFILES = \
+ Makefile.in
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign sysdeps/linux-gnu/x86/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --foreign sysdeps/linux-gnu/x86/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+../$(am__dirstamp):
+ @$(MKDIR_P) ..
+ @: > ../$(am__dirstamp)
+../libcpu.la: $(___libcpu_la_OBJECTS) $(___libcpu_la_DEPENDENCIES) ../$(am__dirstamp)
+ $(LINK) $(___libcpu_la_OBJECTS) $(___libcpu_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fetch.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/plt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/regs.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/trace.Plo@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+ -rm -rf ../.libs ../_libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: check-am
+all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f ../$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES ctags distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-tags distdir dvi dvi-am html html-am info info-am \
+ install install-am install-data install-data-am install-dvi \
+ install-dvi-am install-exec install-exec-am install-html \
+ install-html-am install-info install-info-am install-man \
+ install-pdf install-pdf-am install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/sysdeps/linux-gnu/x86/arch.h b/sysdeps/linux-gnu/x86/arch.h
new file mode 100644
index 0000000..329cfba
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/arch.h
@@ -0,0 +1,36 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011, 2012 Petr Machata
+ * Copyright (C) 2006 Ian Wienand
+ * Copyright (C) 2004 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#define BREAKPOINT_VALUE {0xcc}
+#define BREAKPOINT_LENGTH 1
+#define DECR_PC_AFTER_BREAK 1
+#define ARCH_HAVE_FETCH_ARG
+#define ARCH_HAVE_SIZEOF
+#define ARCH_HAVE_ALIGNOF
+#define ARCH_ENDIAN_LITTLE
+
+#ifdef __x86_64__
+#define LT_ELFCLASS ELFCLASS64
+#define LT_ELF_MACHINE EM_X86_64
+#endif
+#define LT_ELFCLASS2 ELFCLASS32
+#define LT_ELF_MACHINE2 EM_386
diff --git a/sysdeps/linux-gnu/x86/fetch.c b/sysdeps/linux-gnu/x86/fetch.c
new file mode 100644
index 0000000..4dab4cc
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/fetch.c
@@ -0,0 +1,849 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2011,2012 Petr Machata
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <assert.h>
+#include <gelf.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "backend.h"
+#include "expr.h"
+#include "fetch.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
+#include "value.h"
+
+enum arg_class {
+ CLASS_INTEGER,
+ CLASS_SSE,
+ CLASS_NO,
+ CLASS_MEMORY,
+ CLASS_X87,
+};
+
+enum reg_pool {
+ POOL_FUNCALL,
+ POOL_SYSCALL,
+ /* A common pool for system call and function call return is
+ * enough, the ABI is similar enough. */
+ POOL_RETVAL,
+};
+
+struct fetch_context
+{
+ struct user_regs_struct iregs;
+ struct user_fpregs_struct fpregs;
+
+ void *stack_pointer;
+ size_t ireg; /* Used-up integer registers. */
+ size_t freg; /* Used-up floating registers. */
+
+ union {
+ struct {
+ /* Storage classes for return type. We need
+ * to compute them anyway, so let's keep them
+ * around. */
+ enum arg_class ret_classes[2];
+ ssize_t num_ret_classes;
+ } x86_64;
+ struct {
+ struct value retval;
+ } ix86;
+ } u;
+};
+
+#ifndef __x86_64__
+__attribute__((noreturn)) static void
+i386_unreachable(void)
+{
+ abort();
+}
+#endif
+
+static int
+contains_unaligned_fields(struct arg_type_info *info)
+{
+ /* XXX currently we don't support structure alignment. */
+ return 0;
+}
+
+static int
+has_nontrivial_ctor_dtor(struct arg_type_info *info)
+{
+ /* XXX another unsupported aspect of type info. We might call
+ * these types "class" instead of "struct" in the config
+ * file. */
+ return 0;
+}
+
+static void
+copy_int_register(struct fetch_context *context,
+ struct value *valuep, unsigned long val, size_t offset)
+{
+ if (valuep != NULL) {
+ unsigned char *buf = value_get_raw_data(valuep);
+ memcpy(buf + offset, &val, sizeof(val));
+ }
+ context->ireg++;
+}
+
+static void
+copy_sse_register(struct fetch_context *context, struct value *valuep,
+ int half, size_t sz, size_t offset)
+{
+#ifdef __x86_64__
+ union {
+ uint32_t sse[4];
+ long halves[2];
+ } u;
+ size_t off = 4 * context->freg++;
+ memcpy(u.sse, context->fpregs.xmm_space + off, sizeof(u.sse));
+
+ if (valuep != NULL) {
+ unsigned char *buf = value_get_raw_data(valuep);
+ memcpy(buf + offset, u.halves + half, sz);
+ }
+#else
+ i386_unreachable();
+#endif
+}
+
+static void
+allocate_stack_slot(struct fetch_context *context,
+ struct value *valuep, size_t sz, size_t offset,
+ size_t archw)
+{
+ size_t a = type_alignof(valuep->inferior, valuep->type);
+ if (a < archw)
+ a = archw;
+ context->stack_pointer
+ = (void *)align((unsigned long)context->stack_pointer, a);
+
+ if (valuep != NULL)
+ value_in_inferior(valuep, context->stack_pointer);
+ context->stack_pointer += sz;
+}
+
+static enum arg_class
+allocate_x87(struct fetch_context *context, struct value *valuep,
+ size_t sz, size_t offset, enum reg_pool pool, size_t archw)
+{
+ /* Both i386 and x86_64 ABI only ever really use x87 registers
+ * to return values. Otherwise, the parameter is treated as
+ * if it were CLASS_MEMORY. On x86_64 x87 registers are only
+ * used for returning long double values, which we currently
+ * don't support. */
+
+ if (pool != POOL_RETVAL) {
+ allocate_stack_slot(context, valuep, sz, offset, archw);
+ return CLASS_MEMORY;
+
+ }
+
+ /* If the class is X87, the value is returned on the X87 stack
+ * in %st0 as 80-bit x87 number.
+ *
+ * If the class is X87UP, the value is returned together with
+ * the previous X87 value in %st0.
+ *
+ * If the class is COMPLEX_X87, the real part of the value is
+ * returned in %st0 and the imaginary part in %st1. */
+
+ if (valuep != NULL) {
+ union {
+ long double ld;
+ double d;
+ float f;
+ char buf[0];
+ } u;
+
+ /* The x87 floating point value is in long double
+ * format, so we need to convert in to the right type.
+ * Alternatively we might just leave it as is and
+ * smuggle the long double type into the value (via
+ * value_set_type), but for that we first need to
+ * support long double in the first place. */
+
+#ifdef __x86_64__
+ unsigned int *reg;
+#else
+ long int *reg;
+#endif
+ reg = &context->fpregs.st_space[0];
+ memcpy(&u.ld, reg, sizeof(u));
+ if (valuep->type->type == ARGTYPE_FLOAT)
+ u.f = (float)u.ld;
+ else if (valuep->type->type == ARGTYPE_DOUBLE)
+ u.d = (double)u.ld;
+ else
+ assert(!"Unexpected floating type!"), abort();
+
+ unsigned char *buf = value_get_raw_data(valuep);
+ memcpy(buf + offset, u.buf, sz);
+ }
+ return CLASS_X87;
+}
+
+static enum arg_class
+allocate_integer(struct fetch_context *context, struct value *valuep,
+ size_t sz, size_t offset, enum reg_pool pool)
+{
+#define HANDLE(NUM, WHICH) \
+ case NUM: \
+ copy_int_register(context, valuep, \
+ context->iregs.WHICH, offset); \
+ return CLASS_INTEGER
+
+ switch (pool) {
+ case POOL_FUNCALL:
+#ifdef __x86_64__
+ switch (context->ireg) {
+ HANDLE(0, rdi);
+ HANDLE(1, rsi);
+ HANDLE(2, rdx);
+ HANDLE(3, rcx);
+ HANDLE(4, r8);
+ HANDLE(5, r9);
+ default:
+ allocate_stack_slot(context, valuep, sz, offset, 8);
+ return CLASS_MEMORY;
+ }
+#else
+ i386_unreachable();
+#endif
+
+ case POOL_SYSCALL:
+#ifdef __x86_64__
+ switch (context->ireg) {
+ HANDLE(0, rdi);
+ HANDLE(1, rsi);
+ HANDLE(2, rdx);
+ HANDLE(3, r10);
+ HANDLE(4, r8);
+ HANDLE(5, r9);
+ default:
+ assert(!"More than six syscall arguments???");
+ abort();
+ }
+#else
+ i386_unreachable();
+#endif
+
+ case POOL_RETVAL:
+ switch (context->ireg) {
+#ifdef __x86_64__
+ HANDLE(0, rax);
+ HANDLE(1, rdx);
+#else
+ HANDLE(0, eax);
+#endif
+ default:
+ assert(!"Too many return value classes.");
+ abort();
+ }
+ }
+
+ abort();
+
+#undef HANDLE
+}
+
+static enum arg_class
+allocate_sse(struct fetch_context *context, struct value *valuep,
+ size_t sz, size_t offset, enum reg_pool pool)
+{
+ size_t num_regs = 0;
+ switch (pool) {
+ case POOL_FUNCALL:
+ num_regs = 8;
+ case POOL_SYSCALL:
+ break;
+ case POOL_RETVAL:
+ num_regs = 2;
+ }
+
+ if (context->freg >= num_regs) {
+ /* We shouldn't see overflow for RETVAL or SYSCALL
+ * pool. */
+ assert(pool == POOL_FUNCALL);
+ allocate_stack_slot(context, valuep, sz, offset, 8);
+ return CLASS_MEMORY;
+ } else {
+ copy_sse_register(context, valuep, 0, sz, offset);
+ return CLASS_SSE;
+ }
+}
+
+/* This allocates registers or stack space for another argument of the
+ * class CLS. */
+static enum arg_class
+allocate_class(enum arg_class cls, struct fetch_context *context,
+ struct value *valuep, size_t sz, size_t offset, enum reg_pool pool)
+{
+ switch (cls) {
+ case CLASS_MEMORY:
+ allocate_stack_slot(context, valuep, sz, offset, 8);
+ case CLASS_NO:
+ return cls;
+
+ case CLASS_INTEGER:
+ return allocate_integer(context, valuep, sz, offset, pool);
+
+ case CLASS_SSE:
+ return allocate_sse(context, valuep, sz, offset, pool);
+
+ case CLASS_X87:
+ return allocate_x87(context, valuep, sz, offset, pool, 8);
+ }
+ abort();
+}
+
+static ssize_t
+classify(struct Process *proc, struct fetch_context *context,
+ struct arg_type_info *info, struct value *valuep, enum arg_class classes[],
+ size_t sz, size_t eightbytes);
+
+/* This classifies one eightbyte part of an array or struct. */
+static ssize_t
+classify_eightbyte(struct Process *proc, struct fetch_context *context,
+ struct arg_type_info *info, struct value *valuep,
+ enum arg_class *classp, size_t start, size_t end,
+ struct arg_type_info *(*getter)(struct arg_type_info *,
+ size_t))
+{
+ size_t i;
+ enum arg_class cls = CLASS_NO;
+ for (i = start; i < end; ++i) {
+ enum arg_class cls2;
+ struct arg_type_info *info2 = getter(info, i);
+ size_t sz = type_sizeof(proc, info2);
+ if (sz == (size_t)-1)
+ return -1;
+ if (classify(proc, context, info2, valuep, &cls2, sz, 1) < 0)
+ return -1;
+
+ if (cls == CLASS_NO)
+ cls = cls2;
+ else if (cls2 == CLASS_NO || cls == cls2)
+ ;
+ else if (cls == CLASS_MEMORY || cls2 == CLASS_MEMORY)
+ cls = CLASS_MEMORY;
+ else if (cls == CLASS_INTEGER || cls2 == CLASS_INTEGER)
+ cls = CLASS_INTEGER;
+ else
+ cls = CLASS_SSE;
+ }
+
+ *classp = cls;
+ return 1;
+}
+
+/* This classifies small arrays and structs. */
+static ssize_t
+classify_eightbytes(struct Process *proc, struct fetch_context *context,
+ struct arg_type_info *info, struct value *valuep,
+ enum arg_class classes[], size_t elements,
+ size_t eightbytes,
+ struct arg_type_info *(*getter)(struct arg_type_info *,
+ size_t))
+{
+ if (eightbytes > 1) {
+ /* Where the second eightbyte starts. Number of the
+ * first element in the structure that belongs to the
+ * second eightbyte. */
+ size_t start_2nd = 0;
+ size_t i;
+ for (i = 0; i < elements; ++i)
+ if (type_offsetof(proc, info, i) >= 8) {
+ start_2nd = i;
+ break;
+ }
+
+ enum arg_class cls1, cls2;
+ if (classify_eightbyte(proc, context, info, valuep, &cls1,
+ 0, start_2nd, getter) < 0
+ || classify_eightbyte(proc, context, info, valuep, &cls2,
+ start_2nd, elements, getter) < 0)
+ return -1;
+
+ if (cls1 == CLASS_MEMORY || cls2 == CLASS_MEMORY) {
+ classes[0] = CLASS_MEMORY;
+ return 1;
+ }
+
+ classes[0] = cls1;
+ classes[1] = cls2;
+ return 2;
+ }
+
+ return classify_eightbyte(proc, context, info, valuep, classes,
+ 0, elements, getter);
+}
+
+static struct arg_type_info *
+get_array_field(struct arg_type_info *info, size_t emt)
+{
+ return info->u.array_info.elt_type;
+}
+
+static int
+flatten_structure(struct arg_type_info *flattened, struct arg_type_info *info)
+{
+ size_t i;
+ for (i = 0; i < type_struct_size(info); ++i) {
+ struct arg_type_info *field = type_struct_get(info, i);
+ assert(field != NULL);
+ switch (field->type) {
+ case ARGTYPE_STRUCT:
+ if (flatten_structure(flattened, field) < 0)
+ return -1;
+ break;
+
+ default:
+ if (type_struct_add(flattened, field, 0) < 0)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static ssize_t
+classify(struct Process *proc, struct fetch_context *context,
+ struct arg_type_info *info, struct value *valuep, enum arg_class classes[],
+ size_t sz, size_t eightbytes)
+{
+ switch (info->type) {
+ struct arg_type_info flattened;
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+
+ case ARGTYPE_POINTER:
+ /* and LONGLONG */
+ /* CLASS_INTEGER */
+ classes[0] = CLASS_INTEGER;
+ return 1;
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ /* and DECIMAL, and _m64 */
+ classes[0] = CLASS_SSE;
+ return 1;
+
+ case ARGTYPE_ARRAY:
+ /* N.B. this cannot be top-level array, those decay to
+ * pointers. Therefore, it must be inside structure
+ * that's at most 2 eightbytes long. */
+
+ /* Structures with flexible array members can't be
+ * passed by value. */
+ assert(expr_is_compile_constant(info->u.array_info.length));
+
+ long l;
+ if (expr_eval_constant(info->u.array_info.length, &l) < 0)
+ return -1;
+
+ return classify_eightbytes(proc, context, info, valuep, classes,
+ (size_t)l, eightbytes,
+ get_array_field);
+
+ case ARGTYPE_STRUCT:
+ /* N.B. "big" structs are dealt with in the caller.
+ *
+ * First, we need to flatten the structure. In
+ * struct(float,struct(float,float)), first two floats
+ * both belong to the same eightbyte. */
+ type_init_struct(&flattened);
+
+ ssize_t ret;
+ if (flatten_structure(&flattened, info) < 0) {
+ ret = -1;
+ goto done;
+ }
+ ret = classify_eightbytes(proc, context, &flattened,
+ valuep, classes,
+ type_struct_size(&flattened),
+ eightbytes, type_struct_get);
+ done:
+ type_destroy(&flattened);
+ return ret;
+
+ default:
+ /* Unsupported type. */
+ assert(info->type != info->type);
+ abort();
+ }
+ abort();
+}
+
+static ssize_t
+pass_by_reference(struct value *valuep, enum arg_class classes[])
+{
+ if (valuep != NULL && value_pass_by_reference(valuep) < 0)
+ return -1;
+ classes[0] = CLASS_INTEGER;
+ return 1;
+}
+
+static ssize_t
+classify_argument(struct Process *proc, struct fetch_context *context,
+ struct arg_type_info *info, struct value *valuep,
+ enum arg_class classes[], size_t *sizep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+ *sizep = sz;
+
+ size_t eightbytes = (sz + 7) / 8; /* Round up. */
+
+ /* Arrays decay into pointers. */
+ assert(info->type != ARGTYPE_ARRAY);
+
+ if (info->type == ARGTYPE_STRUCT) {
+ if (eightbytes > 2 || contains_unaligned_fields(info)) {
+ classes[0] = CLASS_MEMORY;
+ return 1;
+ }
+
+ if (has_nontrivial_ctor_dtor(info))
+ return pass_by_reference(valuep, classes);
+ }
+
+ return classify(proc, context, info, valuep, classes, sz, eightbytes);
+}
+
+static int
+fetch_register_banks(struct Process *proc, struct fetch_context *context,
+ int floating)
+{
+ if (ptrace(PTRACE_GETREGS, proc->pid, 0, &context->iregs) < 0)
+ return -1;
+ context->ireg = 0;
+
+ if (floating) {
+ if (ptrace(PTRACE_GETFPREGS, proc->pid,
+ 0, &context->fpregs) < 0)
+ return -1;
+ context->freg = 0;
+ } else {
+ context->freg = -1;
+ }
+
+ return 0;
+}
+
+static int
+arch_fetch_arg_next_32(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+
+ allocate_stack_slot(context, valuep, sz, 0, 4);
+
+ return 0;
+}
+
+static int
+arch_fetch_retval_32(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (fetch_register_banks(proc, context, type == LT_TOF_FUNCTIONR) < 0)
+ return -1;
+
+ struct value *retval = &context->u.ix86.retval;
+ if (retval->type != NULL) {
+ /* Struct return value was extracted when in fetch
+ * init. */
+ memcpy(valuep, &context->u.ix86.retval, sizeof(*valuep));
+ return 0;
+ }
+
+ size_t sz = type_sizeof(proc, info);
+ if (sz == (size_t)-1)
+ return -1;
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ switch (info->type) {
+ enum arg_class cls;
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_CHAR:
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ case ARGTYPE_POINTER:
+ cls = allocate_integer(context, valuep, sz, 0, POOL_RETVAL);
+ assert(cls == CLASS_INTEGER);
+ return 0;
+
+ case ARGTYPE_FLOAT:
+ case ARGTYPE_DOUBLE:
+ cls = allocate_x87(context, valuep, sz, 0, POOL_RETVAL, 4);
+ assert(cls == CLASS_X87);
+ return 0;
+
+ case ARGTYPE_STRUCT: /* Handled above. */
+ default:
+ assert(!"Unexpected i386 retval type!");
+ abort();
+ }
+
+ abort();
+}
+
+static arch_addr_t
+fetch_stack_pointer(struct fetch_context *context)
+{
+ arch_addr_t sp;
+#ifdef __x86_64__
+ sp = (arch_addr_t)context->iregs.rsp;
+#else
+ sp = (arch_addr_t)context->iregs.esp;
+#endif
+ return sp;
+}
+
+struct fetch_context *
+arch_fetch_arg_init_32(struct fetch_context *context,
+ enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ context->stack_pointer = fetch_stack_pointer(context) + 4;
+
+ size_t sz = type_sizeof(proc, ret_info);
+ if (sz == (size_t)-1)
+ return NULL;
+
+ struct value *retval = &context->u.ix86.retval;
+ if (ret_info->type == ARGTYPE_STRUCT) {
+ value_init(retval, proc, NULL, ret_info, 0);
+
+ enum arg_class dummy[2];
+ if (pass_by_reference(retval, dummy) < 0)
+ return NULL;
+ allocate_stack_slot(context, retval, 4, 0, 4);
+
+ } else {
+ value_init_detached(retval, NULL, NULL, 0);
+ }
+
+ return context;
+}
+
+struct fetch_context *
+arch_fetch_arg_init_64(struct fetch_context *ctx, enum tof type,
+ struct Process *proc, struct arg_type_info *ret_info)
+{
+ /* The first stack slot holds a return address. */
+ ctx->stack_pointer = fetch_stack_pointer(ctx) + 8;
+
+ size_t size;
+ ctx->u.x86_64.num_ret_classes
+ = classify_argument(proc, ctx, ret_info, NULL,
+ ctx->u.x86_64.ret_classes, &size);
+ if (ctx->u.x86_64.num_ret_classes == -1)
+ return NULL;
+
+ /* If the class is MEMORY, then the first argument is a hidden
+ * pointer to the allocated storage. */
+ if (ctx->u.x86_64.num_ret_classes > 0
+ && ctx->u.x86_64.ret_classes[0] == CLASS_MEMORY) {
+ /* MEMORY should be the sole class. */
+ assert(ctx->u.x86_64.num_ret_classes == 1);
+ allocate_integer(ctx, NULL, size, 0, POOL_FUNCALL);
+ }
+
+ return ctx;
+}
+
+struct fetch_context *
+arch_fetch_arg_init(enum tof type, struct Process *proc,
+ struct arg_type_info *ret_info)
+{
+ struct fetch_context *ctx = malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ return NULL;
+
+ assert(type != LT_TOF_FUNCTIONR
+ && type != LT_TOF_SYSCALLR);
+ if (fetch_register_banks(proc, ctx, type == LT_TOF_FUNCTION) < 0) {
+ fail:
+ free(ctx);
+ return NULL;
+ }
+
+ struct fetch_context *ret;
+ if (proc->e_machine == EM_386)
+ ret = arch_fetch_arg_init_32(ctx, type, proc, ret_info);
+ else
+ ret = arch_fetch_arg_init_64(ctx, type, proc, ret_info);
+ if (ret == NULL)
+ goto fail;
+ return ret;
+}
+
+struct fetch_context *
+arch_fetch_arg_clone(struct Process *proc, struct fetch_context *context)
+{
+ struct fetch_context *ret = malloc(sizeof(*ret));
+ if (ret == NULL)
+ return NULL;
+ return memcpy(ret, context, sizeof(*ret));
+}
+
+static int
+arch_fetch_pool_arg_next(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep, enum reg_pool pool)
+{
+ enum arg_class classes[2];
+ size_t sz, sz1;
+ ssize_t i;
+ ssize_t nclasses = classify_argument(proc, context, info, valuep,
+ classes, &sz);
+ if (nclasses == -1)
+ return -1;
+ if (value_reserve(valuep, sz) == NULL)
+ return -1;
+
+ /* If there are no registers available for any eightbyte of an
+ * argument, the whole argument is passed on the stack. If
+ * registers have already been assigned for some eightbytes of
+ * such an argument, the assignments get reverted. */
+ struct fetch_context tmp_context = *context;
+ int revert;
+ if (nclasses == 1) {
+ revert = allocate_class(classes[0], &tmp_context,
+ valuep, sz, 0, pool) != classes[0];
+ } else {
+ revert = 0;
+ for (i = 0; i < nclasses; ++i) {
+ sz1 = (size_t)(8 * (i + 1)) > sz ? sz - 8 * i : 8;
+ if (allocate_class(classes[i], &tmp_context, valuep,
+ sz1, 8 * i, pool) != classes[i])
+ revert = 1;
+ }
+ }
+
+ if (nclasses > 1 && revert)
+ allocate_class(CLASS_MEMORY, context, valuep, sz, 0, pool);
+ else
+ *context = tmp_context; /* Commit. */
+
+ return 0;
+}
+
+int
+arch_fetch_fun_retval(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ assert(type != LT_TOF_FUNCTION
+ && type != LT_TOF_SYSCALL);
+ if (value_reserve(valuep, 8 * context->u.x86_64.num_ret_classes) == NULL
+ || fetch_register_banks(proc, context,
+ type == LT_TOF_FUNCTIONR) < 0)
+ return -1;
+
+ if (context->u.x86_64.num_ret_classes == 1
+ && context->u.x86_64.ret_classes[0] == CLASS_MEMORY)
+ pass_by_reference(valuep, context->u.x86_64.ret_classes);
+
+ size_t sz = type_sizeof(proc, valuep->type);
+ if (sz == (size_t)-1)
+ return -1;
+
+ ssize_t i;
+ size_t sz1 = context->u.x86_64.num_ret_classes == 1 ? sz : 8;
+ for (i = 0; i < context->u.x86_64.num_ret_classes; ++i) {
+ enum arg_class cls
+ = allocate_class(context->u.x86_64.ret_classes[i],
+ context, valuep, sz1,
+ 8 * i, POOL_RETVAL);
+ assert(cls == context->u.x86_64.ret_classes[i]);
+ }
+ return 0;
+}
+
+int
+arch_fetch_arg_next(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (proc->e_machine == EM_386)
+ return arch_fetch_arg_next_32(context, type, proc,
+ info, valuep);
+
+ switch (type) {
+ case LT_TOF_FUNCTION:
+ case LT_TOF_FUNCTIONR:
+ return arch_fetch_pool_arg_next(context, type, proc,
+ info, valuep, POOL_FUNCALL);
+
+ case LT_TOF_SYSCALL:
+ case LT_TOF_SYSCALLR:
+ return arch_fetch_pool_arg_next(context, type, proc,
+ info, valuep, POOL_SYSCALL);
+ }
+
+ abort();
+}
+
+int
+arch_fetch_retval(struct fetch_context *context, enum tof type,
+ struct Process *proc, struct arg_type_info *info,
+ struct value *valuep)
+{
+ if (proc->e_machine == EM_386)
+ return arch_fetch_retval_32(context, type, proc, info, valuep);
+
+ return arch_fetch_fun_retval(context, type, proc, info, valuep);
+}
+
+void
+arch_fetch_arg_done(struct fetch_context *context)
+{
+ if (context != NULL)
+ free(context);
+}
diff --git a/sysdeps/linux-gnu/x86/plt.c b/sysdeps/linux-gnu/x86/plt.c
new file mode 100644
index 0000000..dc6f183
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/plt.c
@@ -0,0 +1,34 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <gelf.h>
+#include "proc.h"
+#include "common.h"
+#include "library.h"
+
+GElf_Addr
+arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
+ return lte->plt_addr + (ndx + 1) * 16;
+}
+
+void *
+sym2addr(Process *proc, struct library_symbol *sym) {
+ return sym->enter_addr;
+}
diff --git a/sysdeps/linux-gnu/x86/ptrace.h b/sysdeps/linux-gnu/x86/ptrace.h
new file mode 100644
index 0000000..dc4734a
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/ptrace.h
@@ -0,0 +1,21 @@
+/*
+ * This file is part of ltrace.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include <sys/ptrace.h>
+#include <sys/user.h>
diff --git a/sysdeps/linux-gnu/x86/regs.c b/sysdeps/linux-gnu/x86/regs.c
new file mode 100644
index 0000000..ca6470b
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/regs.c
@@ -0,0 +1,116 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 1998,2002,2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/ptrace.h>
+#include <sys/reg.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "backend.h"
+#include "proc.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+#ifdef __x86_64__
+# define XIP (8 * RIP)
+# define XSP (8 * RSP)
+#else
+# define XIP (4 * EIP)
+# define XSP (4 * UESP)
+#endif
+
+static arch_addr_t
+conv_32(arch_addr_t val)
+{
+ /* XXX Drop the multiple double casts when arch_addr_t
+ * becomes integral. */
+ return (arch_addr_t)(uintptr_t)(uint32_t)(uintptr_t)val;
+}
+
+void *
+get_instruction_pointer(struct Process *proc)
+{
+ long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, XIP, 0);
+ if (proc->e_machine == EM_386)
+ ret &= 0xffffffff;
+ return (void *)ret;
+}
+
+void
+set_instruction_pointer(struct Process *proc, arch_addr_t addr)
+{
+ if (proc->e_machine == EM_386)
+ addr = conv_32(addr);
+ ptrace(PTRACE_POKEUSER, proc->pid, XIP, addr);
+}
+
+void *
+get_stack_pointer(struct Process *proc)
+{
+ long sp = ptrace(PTRACE_PEEKUSER, proc->pid, XSP, 0);
+ if (sp == -1 && errno) {
+ fprintf(stderr, "Couldn't read SP register: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ /* XXX Drop the multiple double casts when arch_addr_t
+ * becomes integral. */
+ arch_addr_t ret = (arch_addr_t)(uintptr_t)sp;
+ if (proc->e_machine == EM_386)
+ ret = conv_32(ret);
+ return ret;
+}
+
+void *
+get_return_addr(struct Process *proc, void *sp)
+{
+ long a = ptrace(PTRACE_PEEKTEXT, proc->pid, sp, 0);
+ if (a == -1 && errno) {
+ fprintf(stderr, "Couldn't read return value: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ /* XXX Drop the multiple double casts when arch_addr_t
+ * becomes integral. */
+ arch_addr_t ret = (arch_addr_t)(uintptr_t)a;
+ if (proc->e_machine == EM_386)
+ ret = conv_32(ret);
+ return ret;
+}
+
+void
+set_return_addr(Process *proc, void *addr) {
+ if (proc->e_machine == EM_386)
+ addr = (void *)((long int)addr & 0xffffffff);
+ ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr);
+}
diff --git a/sysdeps/linux-gnu/x86_64/signalent.h b/sysdeps/linux-gnu/x86/signalent.h
index d58a36c..9b8baa0 100644
--- a/sysdeps/linux-gnu/x86_64/signalent.h
+++ b/sysdeps/linux-gnu/x86/signalent.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/i386/signalent.h b/sysdeps/linux-gnu/x86/signalent1.h
index 5395f82..31699db 100644
--- a/sysdeps/linux-gnu/i386/signalent.h
+++ b/sysdeps/linux-gnu/x86/signalent1.h
@@ -1,3 +1,23 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
"SIG_0", /* 0 */
"SIGHUP", /* 1 */
"SIGINT", /* 2 */
diff --git a/sysdeps/linux-gnu/x86/syscallent.h b/sysdeps/linux-gnu/x86/syscallent.h
new file mode 100644
index 0000000..345fe20
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/syscallent.h
@@ -0,0 +1,370 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/* This file is for i386 system call names. */
+ "restart_syscall", /* 0 */
+ "exit", /* 1 */
+ "fork", /* 2 */
+ "read", /* 3 */
+ "write", /* 4 */
+ "open", /* 5 */
+ "close", /* 6 */
+ "waitpid", /* 7 */
+ "creat", /* 8 */
+ "link", /* 9 */
+ "unlink", /* 10 */
+ "execve", /* 11 */
+ "chdir", /* 12 */
+ "time", /* 13 */
+ "mknod", /* 14 */
+ "chmod", /* 15 */
+ "lchown", /* 16 */
+ "break", /* 17 */
+ "oldstat", /* 18 */
+ "lseek", /* 19 */
+ "getpid", /* 20 */
+ "mount", /* 21 */
+ "umount", /* 22 */
+ "setuid", /* 23 */
+ "getuid", /* 24 */
+ "stime", /* 25 */
+ "ptrace", /* 26 */
+ "alarm", /* 27 */
+ "oldfstat", /* 28 */
+ "pause", /* 29 */
+ "utime", /* 30 */
+ "stty", /* 31 */
+ "gtty", /* 32 */
+ "access", /* 33 */
+ "nice", /* 34 */
+ "ftime", /* 35 */
+ "sync", /* 36 */
+ "kill", /* 37 */
+ "rename", /* 38 */
+ "mkdir", /* 39 */
+ "rmdir", /* 40 */
+ "dup", /* 41 */
+ "pipe", /* 42 */
+ "times", /* 43 */
+ "prof", /* 44 */
+ "brk", /* 45 */
+ "setgid", /* 46 */
+ "getgid", /* 47 */
+ "signal", /* 48 */
+ "geteuid", /* 49 */
+ "getegid", /* 50 */
+ "acct", /* 51 */
+ "umount2", /* 52 */
+ "lock", /* 53 */
+ "ioctl", /* 54 */
+ "fcntl", /* 55 */
+ "mpx", /* 56 */
+ "setpgid", /* 57 */
+ "ulimit", /* 58 */
+ "oldolduname", /* 59 */
+ "umask", /* 60 */
+ "chroot", /* 61 */
+ "ustat", /* 62 */
+ "dup2", /* 63 */
+ "getppid", /* 64 */
+ "getpgrp", /* 65 */
+ "setsid", /* 66 */
+ "sigaction", /* 67 */
+ "sgetmask", /* 68 */
+ "ssetmask", /* 69 */
+ "setreuid", /* 70 */
+ "setregid", /* 71 */
+ "sigsuspend", /* 72 */
+ "sigpending", /* 73 */
+ "sethostname", /* 74 */
+ "setrlimit", /* 75 */
+ "getrlimit", /* 76 */
+ "getrusage", /* 77 */
+ "gettimeofday", /* 78 */
+ "settimeofday", /* 79 */
+ "getgroups", /* 80 */
+ "setgroups", /* 81 */
+ "select", /* 82 */
+ "symlink", /* 83 */
+ "oldlstat", /* 84 */
+ "readlink", /* 85 */
+ "uselib", /* 86 */
+ "swapon", /* 87 */
+ "reboot", /* 88 */
+ "readdir", /* 89 */
+ "mmap", /* 90 */
+ "munmap", /* 91 */
+ "truncate", /* 92 */
+ "ftruncate", /* 93 */
+ "fchmod", /* 94 */
+ "fchown", /* 95 */
+ "getpriority", /* 96 */
+ "setpriority", /* 97 */
+ "profil", /* 98 */
+ "statfs", /* 99 */
+ "fstatfs", /* 100 */
+ "ioperm", /* 101 */
+ "socketcall", /* 102 */
+ "syslog", /* 103 */
+ "setitimer", /* 104 */
+ "getitimer", /* 105 */
+ "stat", /* 106 */
+ "lstat", /* 107 */
+ "fstat", /* 108 */
+ "olduname", /* 109 */
+ "iopl", /* 110 */
+ "vhangup", /* 111 */
+ "idle", /* 112 */
+ "vm86old", /* 113 */
+ "wait4", /* 114 */
+ "swapoff", /* 115 */
+ "sysinfo", /* 116 */
+ "ipc", /* 117 */
+ "fsync", /* 118 */
+ "sigreturn", /* 119 */
+ "clone", /* 120 */
+ "setdomainname", /* 121 */
+ "uname", /* 122 */
+ "modify_ldt", /* 123 */
+ "adjtimex", /* 124 */
+ "mprotect", /* 125 */
+ "sigprocmask", /* 126 */
+ "create_module", /* 127 */
+ "init_module", /* 128 */
+ "delete_module", /* 129 */
+ "get_kernel_syms", /* 130 */
+ "quotactl", /* 131 */
+ "getpgid", /* 132 */
+ "fchdir", /* 133 */
+ "bdflush", /* 134 */
+ "sysfs", /* 135 */
+ "personality", /* 136 */
+ "afs_syscall", /* 137 */
+ "setfsuid", /* 138 */
+ "setfsgid", /* 139 */
+ "_llseek", /* 140 */
+ "getdents", /* 141 */
+ "_newselect", /* 142 */
+ "flock", /* 143 */
+ "msync", /* 144 */
+ "readv", /* 145 */
+ "writev", /* 146 */
+ "getsid", /* 147 */
+ "fdatasync", /* 148 */
+ "_sysctl", /* 149 */
+ "mlock", /* 150 */
+ "munlock", /* 151 */
+ "mlockall", /* 152 */
+ "munlockall", /* 153 */
+ "sched_setparam", /* 154 */
+ "sched_getparam", /* 155 */
+ "sched_setscheduler", /* 156 */
+ "sched_getscheduler", /* 157 */
+ "sched_yield", /* 158 */
+ "sched_get_priority_max", /* 159 */
+ "sched_get_priority_min", /* 160 */
+ "sched_rr_get_interval", /* 161 */
+ "nanosleep", /* 162 */
+ "mremap", /* 163 */
+ "setresuid", /* 164 */
+ "getresuid", /* 165 */
+ "vm86", /* 166 */
+ "query_module", /* 167 */
+ "poll", /* 168 */
+ "nfsservctl", /* 169 */
+ "setresgid", /* 170 */
+ "getresgid", /* 171 */
+ "prctl", /* 172 */
+ "rt_sigreturn", /* 173 */
+ "rt_sigaction", /* 174 */
+ "rt_sigprocmask", /* 175 */
+ "rt_sigpending", /* 176 */
+ "rt_sigtimedwait", /* 177 */
+ "rt_sigqueueinfo", /* 178 */
+ "rt_sigsuspend", /* 179 */
+ "pread64", /* 180 */
+ "pwrite64", /* 181 */
+ "chown", /* 182 */
+ "getcwd", /* 183 */
+ "capget", /* 184 */
+ "capset", /* 185 */
+ "sigaltstack", /* 186 */
+ "sendfile", /* 187 */
+ "getpmsg", /* 188 */
+ "putpmsg", /* 189 */
+ "vfork", /* 190 */
+ "ugetrlimit", /* 191 */
+ "mmap2", /* 192 */
+ "truncate64", /* 193 */
+ "ftruncate64", /* 194 */
+ "stat64", /* 195 */
+ "lstat64", /* 196 */
+ "fstat64", /* 197 */
+ "lchown32", /* 198 */
+ "getuid32", /* 199 */
+ "getgid32", /* 200 */
+ "geteuid32", /* 201 */
+ "getegid32", /* 202 */
+ "setreuid32", /* 203 */
+ "setregid32", /* 204 */
+ "getgroups32", /* 205 */
+ "setgroups32", /* 206 */
+ "fchown32", /* 207 */
+ "setresuid32", /* 208 */
+ "getresuid32", /* 209 */
+ "setresgid32", /* 210 */
+ "getresgid32", /* 211 */
+ "chown32", /* 212 */
+ "setuid32", /* 213 */
+ "setgid32", /* 214 */
+ "setfsuid32", /* 215 */
+ "setfsgid32", /* 216 */
+ "pivot_root", /* 217 */
+ "mincore", /* 218 */
+ "madvise1", /* 219 */
+ "getdents64", /* 220 */
+ "fcntl64", /* 221 */
+ "222", /* 222 */
+ "223", /* 223 */
+ "gettid", /* 224 */
+ "readahead", /* 225 */
+ "setxattr", /* 226 */
+ "lsetxattr", /* 227 */
+ "fsetxattr", /* 228 */
+ "getxattr", /* 229 */
+ "lgetxattr", /* 230 */
+ "fgetxattr", /* 231 */
+ "listxattr", /* 232 */
+ "llistxattr", /* 233 */
+ "flistxattr", /* 234 */
+ "removexattr", /* 235 */
+ "lremovexattr", /* 236 */
+ "fremovexattr", /* 237 */
+ "tkill", /* 238 */
+ "sendfile64", /* 239 */
+ "futex", /* 240 */
+ "sched_setaffinity", /* 241 */
+ "sched_getaffinity", /* 242 */
+ "set_thread_area", /* 243 */
+ "get_thread_area", /* 244 */
+ "io_setup", /* 245 */
+ "io_destroy", /* 246 */
+ "io_getevents", /* 247 */
+ "io_submit", /* 248 */
+ "io_cancel", /* 249 */
+ "fadvise64", /* 250 */
+ "251", /* 251 */
+ "exit_group", /* 252 */
+ "lookup_dcookie", /* 253 */
+ "epoll_create", /* 254 */
+ "epoll_ctl", /* 255 */
+ "epoll_wait", /* 256 */
+ "remap_file_pages", /* 257 */
+ "set_tid_address", /* 258 */
+ "timer_create", /* 259 */
+ "260", /* 260 */
+ "261", /* 261 */
+ "262", /* 262 */
+ "263", /* 263 */
+ "264", /* 264 */
+ "265", /* 265 */
+ "266", /* 266 */
+ "267", /* 267 */
+ "statfs64", /* 268 */
+ "fstatfs64", /* 269 */
+ "tgkill", /* 270 */
+ "utimes", /* 271 */
+ "fadvise64_64", /* 272 */
+ "vserver", /* 273 */
+ "mbind", /* 274 */
+ "get_mempolicy", /* 275 */
+ "set_mempolicy", /* 276 */
+ "mq_open", /* 277 */
+ "278", /* 278 */
+ "279", /* 279 */
+ "280", /* 280 */
+ "281", /* 281 */
+ "282", /* 282 */
+ "kexec_load", /* 283 */
+ "waitid", /* 284 */
+ "285", /* 285 */
+ "add_key", /* 286 */
+ "request_key", /* 287 */
+ "keyctl", /* 288 */
+ "ioprio_set", /* 289 */
+ "ioprio_get", /* 290 */
+ "inotify_init", /* 291 */
+ "inotify_add_watch", /* 292 */
+ "inotify_rm_watch", /* 293 */
+ "migrate_pages", /* 294 */
+ "openat", /* 295 */
+ "mkdirat", /* 296 */
+ "mknodat", /* 297 */
+ "fchownat", /* 298 */
+ "futimesat", /* 299 */
+ "fstatat64", /* 300 */
+ "unlinkat", /* 301 */
+ "renameat", /* 302 */
+ "linkat", /* 303 */
+ "symlinkat", /* 304 */
+ "readlinkat", /* 305 */
+ "fchmodat", /* 306 */
+ "faccessat", /* 307 */
+ "pselect6", /* 308 */
+ "ppoll", /* 309 */
+ "unshare", /* 310 */
+ "set_robust_list", /* 311 */
+ "get_robust_list", /* 312 */
+ "splice", /* 313 */
+ "sync_file_range", /* 314 */
+ "tee", /* 315 */
+ "vmsplice", /* 316 */
+ "move_pages", /* 317 */
+ "getcpu", /* 318 */
+ "epoll_pwait", /* 319 */
+ "utimensat", /* 320 */
+ "signalfd", /* 321 */
+ "timerfd_create", /* 322 */
+ "eventfd", /* 323 */
+ "fallocate", /* 324 */
+ "timerfd_settime", /* 325 */
+ "timerfd_gettime", /* 326 */
+ "signalfd4", /* 327 */
+ "eventfd2", /* 328 */
+ "epoll_create1", /* 329 */
+ "dup3", /* 330 */
+ "pipe2", /* 331 */
+ "inotify_init1", /* 332 */
+ "preadv", /* 333 */
+ "pwritev", /* 334 */
+ "rt_tgsigqueueinfo", /* 335 */
+ "perf_event_open", /* 336 */
+ "recvmmsg", /* 337 */
+ "fanotify_init", /* 338 */
+ "fanotify_mark", /* 339 */
+ "prlimit64", /* 340 */
+ "name_to_handle_at", /* 341 */
+ "open_by_handle_at", /* 342 */
+ "clock_adjtime", /* 343 */
+ "syncfs", /* 344 */
+ "sendmmsg", /* 345 */
+ "setns", /* 346 */
+ "process_vm_readv", /* 347 */
+ "process_vm_writev", /* 348 */
diff --git a/sysdeps/linux-gnu/x86/syscallent1.h b/sysdeps/linux-gnu/x86/syscallent1.h
new file mode 100644
index 0000000..91ae8d6
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/syscallent1.h
@@ -0,0 +1,333 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+/* This file is for x86_64 system call names. */
+ "read", /* 0 */
+ "write", /* 1 */
+ "open", /* 2 */
+ "close", /* 3 */
+ "stat", /* 4 */
+ "fstat", /* 5 */
+ "lstat", /* 6 */
+ "poll", /* 7 */
+ "lseek", /* 8 */
+ "mmap", /* 9 */
+ "mprotect", /* 10 */
+ "munmap", /* 11 */
+ "brk", /* 12 */
+ "rt_sigaction", /* 13 */
+ "rt_sigprocmask", /* 14 */
+ "rt_sigreturn", /* 15 */
+ "ioctl", /* 16 */
+ "pread", /* 17 */
+ "pwrite", /* 18 */
+ "readv", /* 19 */
+ "writev", /* 20 */
+ "access", /* 21 */
+ "pipe", /* 22 */
+ "select", /* 23 */
+ "sched_yield", /* 24 */
+ "mremap", /* 25 */
+ "msync", /* 26 */
+ "mincore", /* 27 */
+ "madvise", /* 28 */
+ "shmget", /* 29 */
+ "shmat", /* 30 */
+ "shmctl", /* 31 */
+ "dup", /* 32 */
+ "dup2", /* 33 */
+ "pause", /* 34 */
+ "nanosleep", /* 35 */
+ "getitimer", /* 36 */
+ "alarm", /* 37 */
+ "setitimer", /* 38 */
+ "getpid", /* 39 */
+ "sendfile", /* 40 */
+ "socket", /* 41 */
+ "connect", /* 42 */
+ "accept", /* 43 */
+ "sendto", /* 44 */
+ "recvfrom", /* 45 */
+ "sendmsg", /* 46 */
+ "recvmsg", /* 47 */
+ "shutdown", /* 48 */
+ "bind", /* 49 */
+ "listen", /* 50 */
+ "getsockname", /* 51 */
+ "getpeername", /* 52 */
+ "socketpair", /* 53 */
+ "setsockopt", /* 54 */
+ "getsockopt", /* 55 */
+ "clone", /* 56 */
+ "fork", /* 57 */
+ "vfork", /* 58 */
+ "execve", /* 59 */
+ "exit", /* 60 */
+ "wait4", /* 61 */
+ "kill", /* 62 */
+ "uname", /* 63 */
+ "semget", /* 64 */
+ "semop", /* 65 */
+ "semctl", /* 66 */
+ "shmdt", /* 67 */
+ "msgget", /* 68 */
+ "msgsnd", /* 69 */
+ "msgrcv", /* 70 */
+ "msgctl", /* 71 */
+ "fcntl", /* 72 */
+ "flock", /* 73 */
+ "fsync", /* 74 */
+ "fdatasync", /* 75 */
+ "truncate", /* 76 */
+ "ftruncate", /* 77 */
+ "getdents", /* 78 */
+ "getcwd", /* 79 */
+ "chdir", /* 80 */
+ "fchdir", /* 81 */
+ "rename", /* 82 */
+ "mkdir", /* 83 */
+ "rmdir", /* 84 */
+ "creat", /* 85 */
+ "link", /* 86 */
+ "unlink", /* 87 */
+ "symlink", /* 88 */
+ "readlink", /* 89 */
+ "chmod", /* 90 */
+ "fchmod", /* 91 */
+ "chown", /* 92 */
+ "fchown", /* 93 */
+ "lchown", /* 94 */
+ "umask", /* 95 */
+ "gettimeofday", /* 96 */
+ "getrlimit", /* 97 */
+ "getrusage", /* 98 */
+ "sysinfo", /* 99 */
+ "times", /* 100 */
+ "ptrace", /* 101 */
+ "getuid", /* 102 */
+ "syslog", /* 103 */
+ "getgid", /* 104 */
+ "setuid", /* 105 */
+ "setgid", /* 106 */
+ "geteuid", /* 107 */
+ "getegid", /* 108 */
+ "setpgid", /* 109 */
+ "getppid", /* 110 */
+ "getpgrp", /* 111 */
+ "setsid", /* 112 */
+ "setreuid", /* 113 */
+ "setregid", /* 114 */
+ "getgroups", /* 115 */
+ "setgroups", /* 116 */
+ "setresuid", /* 117 */
+ "getresuid", /* 118 */
+ "setresgid", /* 119 */
+ "getresgid", /* 120 */
+ "getpgid", /* 121 */
+ "setfsuid", /* 122 */
+ "setfsgid", /* 123 */
+ "getsid", /* 124 */
+ "capget", /* 125 */
+ "capset", /* 126 */
+ "rt_sigpending", /* 127 */
+ "rt_sigtimedwait", /* 128 */
+ "rt_sigqueueinfo", /* 129 */
+ "rt_sigsuspend", /* 130 */
+ "sigaltstack", /* 131 */
+ "utime", /* 132 */
+ "mknod", /* 133 */
+ "uselib", /* 134 */
+ "personality", /* 135 */
+ "ustat", /* 136 */
+ "statfs", /* 137 */
+ "fstatfs", /* 138 */
+ "sysfs", /* 139 */
+ "getpriority", /* 140 */
+ "setpriority", /* 141 */
+ "sched_setparam", /* 142 */
+ "sched_getparam", /* 143 */
+ "sched_setscheduler", /* 144 */
+ "sched_getscheduler", /* 145 */
+ "sched_get_priority_max", /* 146 */
+ "sched_get_priority_min", /* 147 */
+ "sched_rr_get_interval", /* 148 */
+ "mlock", /* 149 */
+ "munlock", /* 150 */
+ "mlockall", /* 151 */
+ "munlockall", /* 152 */
+ "vhangup", /* 153 */
+ "modify_ldt", /* 154 */
+ "pivot_root", /* 155 */
+ "_sysctl", /* 156 */
+ "prctl", /* 157 */
+ "arch_prctl", /* 158 */
+ "adjtimex", /* 159 */
+ "setrlimit", /* 160 */
+ "chroot", /* 161 */
+ "sync", /* 162 */
+ "acct", /* 163 */
+ "settimeofday", /* 164 */
+ "mount", /* 165 */
+ "umount2", /* 166 */
+ "swapon", /* 167 */
+ "swapoff", /* 168 */
+ "reboot", /* 169 */
+ "sethostname", /* 170 */
+ "setdomainname", /* 171 */
+ "iopl", /* 172 */
+ "ioperm", /* 173 */
+ "create_module", /* 174 */
+ "init_module", /* 175 */
+ "delete_module", /* 176 */
+ "get_kernel_syms", /* 177 */
+ "query_module", /* 178 */
+ "quotactl", /* 179 */
+ "nfsservctl", /* 180 */
+ "getpmsg", /* 181 */
+ "putpmsg", /* 182 */
+ "afs_syscall", /* 183 */
+ "tuxcall", /* 184 */
+ "security", /* 185 */
+ "gettid", /* 186 */
+ "readahead", /* 187 */
+ "setxattr", /* 188 */
+ "lsetxattr", /* 189 */
+ "fsetxattr", /* 190 */
+ "getxattr", /* 191 */
+ "lgetxattr", /* 192 */
+ "fgetxattr", /* 193 */
+ "listxattr", /* 194 */
+ "llistxattr", /* 195 */
+ "flistxattr", /* 196 */
+ "removexattr", /* 197 */
+ "lremovexattr", /* 198 */
+ "fremovexattr", /* 199 */
+ "tkill", /* 200 */
+ "time", /* 201 */
+ "futex", /* 202 */
+ "sched_setaffinity", /* 203 */
+ "sched_getaffinity", /* 204 */
+ "set_thread_area", /* 205 */
+ "io_setup", /* 206 */
+ "io_destroy", /* 207 */
+ "io_getevents", /* 208 */
+ "io_submit", /* 209 */
+ "io_cancel", /* 210 */
+ "get_thread_area", /* 211 */
+ "lookup_dcookie", /* 212 */
+ "epoll_create", /* 213 */
+ "epoll_ctl", /* 214 */
+ "epoll_wait", /* 215 */
+ "remap_file_pages", /* 216 */
+ "getdents64", /* 217 */
+ "set_tid_address", /* 218 */
+ "restart_syscall", /* 219 */
+ "semtimedop", /* 220 */
+ "fadvise64", /* 221 */
+ "timer_create", /* 222 */
+ "timer_settime", /* 223 */
+ "timer_gettime", /* 224 */
+ "timer_getoverrun", /* 225 */
+ "timer_delete", /* 226 */
+ "clock_settime", /* 227 */
+ "clock_gettime", /* 228 */
+ "clock_getres", /* 229 */
+ "clock_nanosleep", /* 230 */
+ "exit_group", /* 231 */
+ "epoll_wait", /* 232 */
+ "epoll_ctl", /* 233 */
+ "tgkill", /* 234 */
+ "utimes", /* 235 */
+ "vserver", /* 236 */
+ "mbind", /* 237 */
+ "set_mempolicy", /* 238 */
+ "get_mempolicy", /* 239 */
+ "mq_open", /* 240 */
+ "mq_unlink", /* 241 */
+ "mq_timedsend", /* 242 */
+ "mq_timedreceive", /* 243 */
+ "mq_notify", /* 244 */
+ "mq_getsetattr", /* 245 */
+ "kexec_load", /* 246 */
+ "waitid", /* 247 */
+ "add_key", /* 248 */
+ "request_key", /* 249 */
+ "keyctl", /* 250 */
+ "ioprio_set", /* 251 */
+ "ioprio_get", /* 252 */
+ "inotify_init", /* 253 */
+ "inotify_add_watch", /* 254 */
+ "inotify_rm_watch", /* 255 */
+ "migrate_pages", /* 256 */
+ "openat", /* 257 */
+ "mkdirat", /* 258 */
+ "mknodat", /* 259 */
+ "fchownat", /* 260 */
+ "futimesat", /* 261 */
+ "newfstatat", /* 262 */
+ "unlinkat", /* 263 */
+ "renameat", /* 264 */
+ "linkat", /* 265 */
+ "symlinkat", /* 266 */
+ "readlinkat", /* 267 */
+ "fchmodat", /* 268 */
+ "faccessat", /* 269 */
+ "pselect6", /* 270 */
+ "ppoll", /* 271 */
+ "unshare", /* 272 */
+ "set_robust_list", /* 273 */
+ "get_robust_list", /* 274 */
+ "splice", /* 275 */
+ "tee", /* 276 */
+ "sync_file_range", /* 277 */
+ "vmsplice", /* 278 */
+ "move_pages", /* 279 */
+ "utimensat", /* 280 */
+ "epoll_pwait", /* 281 */
+ "signalfd", /* 282 */
+ "timerfd_create", /* 283 */
+ "eventfd", /* 284 */
+ "fallocate", /* 285 */
+ "timerfd_settime", /* 286 */
+ "timerfd_gettime", /* 287 */
+ "accept4", /* 288 */
+ "signalfd4", /* 289 */
+ "eventfd2", /* 290 */
+ "epoll_create1", /* 291 */
+ "dup3", /* 292 */
+ "pipe2", /* 293 */
+ "inotify_init1", /* 294 */
+ "preadv", /* 295 */
+ "pwritev", /* 296 */
+ "rt_tgsigqueueinfo", /* 297 */
+ "perf_event_open", /* 298 */
+ "recvmmsg", /* 299 */
+ "fanotify_init", /* 300 */
+ "fanotify_mark", /* 301 */
+ "prlimit64", /* 302 */
+ "name_to_handle_at", /* 303 */
+ "open_by_handle_at", /* 304 */
+ "clock_adjtime", /* 305 */
+ "syncfs", /* 306 */
+ "sendmmsg", /* 307 */
+ "setns", /* 308 */
+ "getcpu", /* 309 */
+ "process_vm_readv", /* 310 */
+ "process_vm_writev", /* 311 */
diff --git a/sysdeps/linux-gnu/x86/trace.c b/sysdeps/linux-gnu/x86/trace.c
new file mode 100644
index 0000000..ed8bdb4
--- /dev/null
+++ b/sysdeps/linux-gnu/x86/trace.c
@@ -0,0 +1,191 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2010,2011,2012 Petr Machata, Red Hat Inc.
+ * Copyright (C) 2004,2008,2009 Juan Cespedes
+ * Copyright (C) 2006 Ian Wienand
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <sys/reg.h>
+#include <sys/wait.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include "backend.h"
+#include "debug.h"
+#include "proc.h"
+#include "ptrace.h"
+#include "type.h"
+
+#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
+# define PTRACE_PEEKUSER PTRACE_PEEKUSR
+#endif
+
+#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
+# define PTRACE_POKEUSER PTRACE_POKEUSR
+#endif
+
+#ifdef __x86_64__
+# define ORIG_XAX (8 * ORIG_RAX)
+#else
+# define ORIG_XAX (4 * ORIG_EAX)
+#endif
+
+#ifdef __x86_64__
+static const int x86_64 = 1;
+#else
+static const int x86_64 = 0;
+#endif
+
+void
+get_arch_dep(struct Process *proc)
+{
+ /* Unfortunately there are still remnants of mask_32bit uses
+ * around. */
+
+ if (proc->e_machine == EM_X86_64) {
+ proc->mask_32bit = 0;
+ proc->personality = 1;
+ } else if (x86_64) { /* x86_64/i386 */
+ proc->mask_32bit = 1;
+ proc->personality = 0;
+ } else {
+ proc->mask_32bit = 0;
+ proc->personality = 0;
+ }
+}
+
+/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
+ */
+int
+syscall_p(struct Process *proc, int status, int *sysnum)
+{
+ if (WIFSTOPPED(status)
+ && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
+ struct callstack_element *elem = NULL;
+ if (proc->callstack_depth > 0)
+ elem = proc->callstack + proc->callstack_depth - 1;
+
+ long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, ORIG_XAX, 0);
+ if (ret == -1) {
+ if (errno)
+ return -1;
+ /* Otherwise, ORIG_RAX == -1 means that the
+ * system call should not be restarted. In
+ * that case rely on what we have on
+ * stack. */
+ if (elem != NULL && elem->is_syscall)
+ ret = elem->c_un.syscall;
+ }
+
+ *sysnum = ret;
+ debug(DEBUG_FUNCTION, "sysnum=%ld %p %d", ret,
+ get_instruction_pointer(proc), errno);
+ if (elem != NULL && elem->is_syscall
+ && elem->c_un.syscall == *sysnum)
+ return 2;
+
+ if (*sysnum >= 0)
+ return 1;
+ }
+ return 0;
+}
+
+size_t
+arch_type_sizeof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ case ARGTYPE_VOID:
+ return 0;
+
+ case ARGTYPE_CHAR:
+ return 1;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 2;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ return 4;
+
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+ case ARGTYPE_FLOAT:
+ return 4;
+ case ARGTYPE_DOUBLE:
+ return 8;
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
+
+ default:
+ assert(info->type != info->type);
+ abort();
+ }
+}
+
+size_t
+arch_type_alignof(struct Process *proc, struct arg_type_info *info)
+{
+ if (proc == NULL)
+ return (size_t)-2;
+
+ switch (info->type) {
+ default:
+ assert(info->type != info->type);
+ abort();
+ break;
+
+ case ARGTYPE_CHAR:
+ return 1;
+
+ case ARGTYPE_SHORT:
+ case ARGTYPE_USHORT:
+ return 2;
+
+ case ARGTYPE_INT:
+ case ARGTYPE_UINT:
+ return 4;
+
+ case ARGTYPE_LONG:
+ case ARGTYPE_ULONG:
+ case ARGTYPE_POINTER:
+ return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+ case ARGTYPE_FLOAT:
+ return 4;
+ case ARGTYPE_DOUBLE:
+ return proc->e_machine == EM_X86_64 ? 8 : 4;
+
+ case ARGTYPE_ARRAY:
+ case ARGTYPE_STRUCT:
+ /* Use default value. */
+ return (size_t)-2;
+ }
+}
diff --git a/sysdeps/linux-gnu/x86_64/Makefile b/sysdeps/linux-gnu/x86_64/Makefile
deleted file mode 100644
index 0a19c97..0000000
--- a/sysdeps/linux-gnu/x86_64/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-OBJ = trace.o regs.o plt.o
-
-all: arch.o
-
-arch.o: $(OBJ)
- $(CC) -nostdlib -r -o arch.o $(OBJ)
-
-clean:
- $(RM) $(OBJ) arch.o
diff --git a/sysdeps/linux-gnu/x86_64/arch.h b/sysdeps/linux-gnu/x86_64/arch.h
deleted file mode 100644
index 255395c..0000000
--- a/sysdeps/linux-gnu/x86_64/arch.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#define BREAKPOINT_VALUE {0xcc}
-#define BREAKPOINT_LENGTH 1
-#define DECR_PC_AFTER_BREAK 1
-
-#define LT_ELFCLASS ELFCLASS64
-#define LT_ELF_MACHINE EM_X86_64
-#define LT_ELFCLASS2 ELFCLASS32
-#define LT_ELF_MACHINE2 EM_386
-
-/* __NR_fork, __NR_clone, __NR_clone2, __NR_vfork and __NR_execve
- from asm-i386/unistd.h. */
-#define FORK_EXEC_SYSCALLS , { 2, 120, -1, 190, 11 }
diff --git a/sysdeps/linux-gnu/x86_64/ffcheck.c b/sysdeps/linux-gnu/x86_64/ffcheck.c
deleted file mode 100644
index e69de29..0000000
--- a/sysdeps/linux-gnu/x86_64/ffcheck.c
+++ /dev/null
diff --git a/sysdeps/linux-gnu/x86_64/plt.c b/sysdeps/linux-gnu/x86_64/plt.c
deleted file mode 100644
index b53ff44..0000000
--- a/sysdeps/linux-gnu/x86_64/plt.c
+++ /dev/null
@@ -1,12 +0,0 @@
-#include <gelf.h>
-#include "common.h"
-
-GElf_Addr
-arch_plt_sym_val(struct ltelf *lte, size_t ndx, GElf_Rela * rela) {
- return lte->plt_addr + (ndx + 1) * 16;
-}
-
-void *
-sym2addr(Process *proc, struct library_symbol *sym) {
- return sym->enter_addr;
-}
diff --git a/sysdeps/linux-gnu/x86_64/ptrace.h b/sysdeps/linux-gnu/x86_64/ptrace.h
deleted file mode 100644
index c3cbcb6..0000000
--- a/sysdeps/linux-gnu/x86_64/ptrace.h
+++ /dev/null
@@ -1 +0,0 @@
-#include <sys/ptrace.h>
diff --git a/sysdeps/linux-gnu/x86_64/regs.c b/sysdeps/linux-gnu/x86_64/regs.c
deleted file mode 100644
index ed1f118..0000000
--- a/sysdeps/linux-gnu/x86_64/regs.c
+++ /dev/null
@@ -1,54 +0,0 @@
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/ptrace.h>
-#include <sys/reg.h>
-
-#include "common.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void *
-get_instruction_pointer(Process *proc) {
- long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RIP, 0);
- if (proc->mask_32bit)
- ret &= 0xffffffff;
- return (void *)ret;
-}
-
-void
-set_instruction_pointer(Process *proc, void *addr) {
- if (proc->mask_32bit)
- addr = (void *)((long int)addr & 0xffffffff);
- ptrace(PTRACE_POKEUSER, proc->pid, 8 * RIP, addr);
-}
-
-void *
-get_stack_pointer(Process *proc) {
- long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSP, 0);
- if (proc->mask_32bit)
- ret &= 0xffffffff;
- return (void *)ret;
-}
-
-void *
-get_return_addr(Process *proc, void *stack_pointer) {
- unsigned long int ret;
- ret = ptrace(PTRACE_PEEKTEXT, proc->pid, stack_pointer, 0);
- if (proc->mask_32bit)
- ret &= 0xffffffff;
- return (void *)ret;
-}
-
-void
-set_return_addr(Process *proc, void *addr) {
- if (proc->mask_32bit)
- addr = (void *)((long int)addr & 0xffffffff);
- ptrace(PTRACE_POKETEXT, proc->pid, proc->stack_pointer, addr);
-}
diff --git a/sysdeps/linux-gnu/x86_64/signalent1.h b/sysdeps/linux-gnu/x86_64/signalent1.h
deleted file mode 100644
index 5ead946..0000000
--- a/sysdeps/linux-gnu/x86_64/signalent1.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "i386/signalent.h"
diff --git a/sysdeps/linux-gnu/x86_64/syscallent.h b/sysdeps/linux-gnu/x86_64/syscallent.h
deleted file mode 100644
index 5e5f88a..0000000
--- a/sysdeps/linux-gnu/x86_64/syscallent.h
+++ /dev/null
@@ -1,256 +0,0 @@
-"read", /* 0 */
- "write", /* 1 */
- "open", /* 2 */
- "close", /* 3 */
- "stat", /* 4 */
- "fstat", /* 5 */
- "lstat", /* 6 */
- "poll", /* 7 */
- "lseek", /* 8 */
- "mmap", /* 9 */
- "mprotect", /* 10 */
- "munmap", /* 11 */
- "brk", /* 12 */
- "rt_sigaction", /* 13 */
- "rt_sigprocmask", /* 14 */
- "rt_sigreturn", /* 15 */
- "ioctl", /* 16 */
- "pread", /* 17 */
- "pwrite", /* 18 */
- "readv", /* 19 */
- "writev", /* 20 */
- "access", /* 21 */
- "pipe", /* 22 */
- "select", /* 23 */
- "sched_yield", /* 24 */
- "mremap", /* 25 */
- "msync", /* 26 */
- "mincore", /* 27 */
- "madvise", /* 28 */
- "shmget", /* 29 */
- "shmat", /* 30 */
- "shmctl", /* 31 */
- "dup", /* 32 */
- "dup2", /* 33 */
- "pause", /* 34 */
- "nanosleep", /* 35 */
- "getitimer", /* 36 */
- "alarm", /* 37 */
- "setitimer", /* 38 */
- "getpid", /* 39 */
- "sendfile", /* 40 */
- "socket", /* 41 */
- "connect", /* 42 */
- "accept", /* 43 */
- "sendto", /* 44 */
- "recvfrom", /* 45 */
- "sendmsg", /* 46 */
- "recvmsg", /* 47 */
- "shutdown", /* 48 */
- "bind", /* 49 */
- "listen", /* 50 */
- "getsockname", /* 51 */
- "getpeername", /* 52 */
- "socketpair", /* 53 */
- "setsockopt", /* 54 */
- "getsockopt", /* 55 */
- "clone", /* 56 */
- "fork", /* 57 */
- "vfork", /* 58 */
- "execve", /* 59 */
- "exit", /* 60 */
- "wait4", /* 61 */
- "kill", /* 62 */
- "uname", /* 63 */
- "semget", /* 64 */
- "semop", /* 65 */
- "semctl", /* 66 */
- "shmdt", /* 67 */
- "msgget", /* 68 */
- "msgsnd", /* 69 */
- "msgrcv", /* 70 */
- "msgctl", /* 71 */
- "fcntl", /* 72 */
- "flock", /* 73 */
- "fsync", /* 74 */
- "fdatasync", /* 75 */
- "truncate", /* 76 */
- "ftruncate", /* 77 */
- "getdents", /* 78 */
- "getcwd", /* 79 */
- "chdir", /* 80 */
- "fchdir", /* 81 */
- "rename", /* 82 */
- "mkdir", /* 83 */
- "rmdir", /* 84 */
- "creat", /* 85 */
- "link", /* 86 */
- "unlink", /* 87 */
- "symlink", /* 88 */
- "readlink", /* 89 */
- "chmod", /* 90 */
- "fchmod", /* 91 */
- "chown", /* 92 */
- "fchown", /* 93 */
- "lchown", /* 94 */
- "umask", /* 95 */
- "gettimeofday", /* 96 */
- "getrlimit", /* 97 */
- "getrusage", /* 98 */
- "sysinfo", /* 99 */
- "times", /* 100 */
- "ptrace", /* 101 */
- "getuid", /* 102 */
- "syslog", /* 103 */
- "getgid", /* 104 */
- "setuid", /* 105 */
- "setgid", /* 106 */
- "geteuid", /* 107 */
- "getegid", /* 108 */
- "setpgid", /* 109 */
- "getppid", /* 110 */
- "getpgrp", /* 111 */
- "setsid", /* 112 */
- "setreuid", /* 113 */
- "setregid", /* 114 */
- "getgroups", /* 115 */
- "setgroups", /* 116 */
- "setresuid", /* 117 */
- "getresuid", /* 118 */
- "setresgid", /* 119 */
- "getresgid", /* 120 */
- "getpgid", /* 121 */
- "setfsuid", /* 122 */
- "setfsgid", /* 123 */
- "getsid", /* 124 */
- "capget", /* 125 */
- "capset", /* 126 */
- "rt_sigpending", /* 127 */
- "rt_sigtimedwait", /* 128 */
- "rt_sigqueueinfo", /* 129 */
- "rt_sigsuspend", /* 130 */
- "sigaltstack", /* 131 */
- "utime", /* 132 */
- "mknod", /* 133 */
- "uselib", /* 134 */
- "personality", /* 135 */
- "ustat", /* 136 */
- "statfs", /* 137 */
- "fstatfs", /* 138 */
- "sysfs", /* 139 */
- "getpriority", /* 140 */
- "setpriority", /* 141 */
- "sched_setparam", /* 142 */
- "sched_getparam", /* 143 */
- "sched_setscheduler", /* 144 */
- "sched_getscheduler", /* 145 */
- "sched_get_priority_max", /* 146 */
- "sched_get_priority_min", /* 147 */
- "sched_rr_get_interval", /* 148 */
- "mlock", /* 149 */
- "munlock", /* 150 */
- "mlockall", /* 151 */
- "munlockall", /* 152 */
- "vhangup", /* 153 */
- "modify_ldt", /* 154 */
- "pivot_root", /* 155 */
- "_sysctl", /* 156 */
- "prctl", /* 157 */
- "arch_prctl", /* 158 */
- "adjtimex", /* 159 */
- "setrlimit", /* 160 */
- "chroot", /* 161 */
- "sync", /* 162 */
- "acct", /* 163 */
- "settimeofday", /* 164 */
- "mount", /* 165 */
- "umount2", /* 166 */
- "swapon", /* 167 */
- "swapoff", /* 168 */
- "reboot", /* 169 */
- "sethostname", /* 170 */
- "setdomainname", /* 171 */
- "iopl", /* 172 */
- "ioperm", /* 173 */
- "create_module", /* 174 */
- "init_module", /* 175 */
- "delete_module", /* 176 */
- "get_kernel_syms", /* 177 */
- "query_module", /* 178 */
- "quotactl", /* 179 */
- "nfsservctl", /* 180 */
- "getpmsg", /* 181 */
- "putpmsg", /* 182 */
- "afs_syscall", /* 183 */
- "tuxcall", /* 184 */
- "security", /* 185 */
- "gettid", /* 186 */
- "readahead", /* 187 */
- "setxattr", /* 188 */
- "lsetxattr", /* 189 */
- "fsetxattr", /* 190 */
- "getxattr", /* 191 */
- "lgetxattr", /* 192 */
- "fgetxattr", /* 193 */
- "listxattr", /* 194 */
- "llistxattr", /* 195 */
- "flistxattr", /* 196 */
- "removexattr", /* 197 */
- "lremovexattr", /* 198 */
- "fremovexattr", /* 199 */
- "tkill", /* 200 */
- "time", /* 201 */
- "futex", /* 202 */
- "sched_setaffinity", /* 203 */
- "sched_getaffinity", /* 204 */
- "set_thread_area", /* 205 */
- "io_setup", /* 206 */
- "io_destroy", /* 207 */
- "io_getevents", /* 208 */
- "io_submit", /* 209 */
- "io_cancel", /* 210 */
- "get_thread_area", /* 211 */
- "lookup_dcookie", /* 212 */
- "epoll_create", /* 213 */
- "epoll_ctl", /* 214 */
- "epoll_wait", /* 215 */
- "remap_file_pages", /* 216 */
- "getdents64", /* 217 */
- "set_tid_address", /* 218 */
- "restart_syscall", /* 219 */
- "semtimedop", /* 220 */
- "fadvise64", /* 221 */
- "timer_create", /* 222 */
- "timer_settime", /* 223 */
- "timer_gettime", /* 224 */
- "timer_getoverrun", /* 225 */
- "timer_delete", /* 226 */
- "clock_settime", /* 227 */
- "clock_gettime", /* 228 */
- "clock_getres", /* 229 */
- "clock_nanosleep", /* 230 */
- "exit_group", /* 231 */
- "epoll_wait", /* 232 */
- "epoll_ctl", /* 233 */
- "tgkill", /* 234 */
- "utimes", /* 235 */
- "vserver", /* 236 */
- "mbind", /* 237 */
- "set_mempolicy", /* 238 */
- "get_mempolicy", /* 239 */
- "mq_open", /* 240 */
- "mq_unlink", /* 241 */
- "mq_timedsend", /* 242 */
- "mq_timedreceive", /* 243 */
- "mq_notify", /* 244 */
- "mq_getsetattr", /* 245 */
- "kexec_load", /* 246 */
- "waitid", /* 247 */
- "add_key", /* 248 */
- "request_key", /* 249 */
- "keyctl", /* 250 */
- "ioprio_set", /* 251 */
- "ioprio_get", /* 252 */
- "inotify_init", /* 253 */
- "inotify_add_watch", /* 254 */
- "inotify_rm_watch", /* 255 */
diff --git a/sysdeps/linux-gnu/x86_64/syscallent1.h b/sysdeps/linux-gnu/x86_64/syscallent1.h
deleted file mode 100644
index d8dd9f7..0000000
--- a/sysdeps/linux-gnu/x86_64/syscallent1.h
+++ /dev/null
@@ -1 +0,0 @@
-#include "i386/syscallent.h"
diff --git a/sysdeps/linux-gnu/x86_64/trace.c b/sysdeps/linux-gnu/x86_64/trace.c
deleted file mode 100644
index 189734d..0000000
--- a/sysdeps/linux-gnu/x86_64/trace.c
+++ /dev/null
@@ -1,144 +0,0 @@
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <sys/ptrace.h>
-#include <sys/reg.h>
-
-#include "common.h"
-
-#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
-# define PTRACE_PEEKUSER PTRACE_PEEKUSR
-#endif
-
-#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
-# define PTRACE_POKEUSER PTRACE_POKEUSR
-#endif
-
-void
-get_arch_dep(Process *proc) {
- unsigned long cs;
- if (proc->arch_ptr)
- return;
- cs = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * CS, 0);
- if (cs == 0x23) {
- proc->mask_32bit = 1;
- proc->personality = 1;
- }
- proc->arch_ptr = (void *)1;
-}
-
-/* Returns 1 if syscall, 2 if sysret, 0 otherwise.
- */
-int
-syscall_p(Process *proc, int status, int *sysnum) {
- if (WIFSTOPPED(status)
- && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
- *sysnum = ptrace(PTRACE_PEEKUSER, proc->pid, 8 * ORIG_RAX, 0);
-
- if (proc->callstack_depth > 0 &&
- proc->callstack[proc->callstack_depth - 1].is_syscall &&
- proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) {
- return 2;
- }
-
- if (*sysnum >= 0) {
- return 1;
- }
- }
- return 0;
-}
-
-static unsigned int
-gimme_arg32(enum tof type, Process *proc, int arg_num) {
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RAX, 0);
- }
-
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- return ptrace(PTRACE_PEEKTEXT, proc->pid,
- proc->stack_pointer + 4 * (arg_num + 1), 0);
- } else if (type == LT_TOF_SYSCALL || type == LT_TOF_SYSCALLR) {
- switch (arg_num) {
- case 0:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RBX, 0);
- case 1:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RCX, 0);
- case 2:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
- case 3:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
- case 4:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
- case 5:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RBP, 0);
- default:
- fprintf(stderr,
- "gimme_arg32 called with wrong arguments\n");
- exit(2);
- }
- }
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
-}
-
-long
-gimme_arg(enum tof type, Process *proc, int arg_num, arg_type_info *info) {
- if (proc->mask_32bit)
- return (unsigned int)gimme_arg32(type, proc, arg_num);
-
- if (arg_num == -1) { /* return value */
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RAX, 0);
- }
-
- if (type == LT_TOF_FUNCTION || type == LT_TOF_FUNCTIONR) {
- switch (arg_num) {
- case 0:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
- case 1:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
- case 2:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
- case 3:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RCX, 0);
- case 4:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0);
- case 5:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0);
- default:
- return ptrace(PTRACE_PEEKTEXT, proc->pid,
- proc->stack_pointer + 8 * (arg_num - 6 +
- 1), 0);
- }
- } else if (type == LT_TOF_SYSCALL || LT_TOF_SYSCALLR) {
- switch (arg_num) {
- case 0:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDI, 0);
- case 1:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RSI, 0);
- case 2:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * RDX, 0);
- case 3:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R10, 0);
- case 4:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R8, 0);
- case 5:
- return ptrace(PTRACE_PEEKUSER, proc->pid, 8 * R9, 0);
- default:
- fprintf(stderr,
- "gimme_arg called with wrong arguments\n");
- exit(2);
- }
- } else {
- fprintf(stderr, "gimme_arg called with wrong arguments\n");
- exit(1);
- }
-
- return 0;
-}
-
-void
-save_register_args(enum tof type, Process *proc) {
-}
diff --git a/sysdeps/sysdep.h b/sysdeps/sysdep.h
new file mode 100644
index 0000000..e8e287f
--- /dev/null
+++ b/sysdeps/sysdep.h
@@ -0,0 +1,66 @@
+/*
+ * This file is part of ltrace.
+ * Copyright (C) 2012 Petr Machata, Red Hat Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ */
+
+#ifndef LTRACE_SYSDEP_H
+#define LTRACE_SYSDEP_H
+
+#include <arch.h>
+#ifndef ARCH_HAVE_ADDRESS_TYPES
+/* We should in general be able to trace 64-bit processes with 32-bit
+ * ltrace. (At least PPC has several PTRACE requests related to
+ * tracing 64-on-32, so presumably it should be possible.) But ltrace
+ * is currently hopelessly infested with using void* for host address.
+ * So keep with it, for now. */
+typedef void *arch_addr_t;
+#endif
+
+#include <os.h>
+
+#ifndef ARCH_HAVE_LTELF_DATA
+struct arch_ltelf_data {
+};
+#endif
+
+#ifndef ARCH_HAVE_BREAKPOINT_DATA
+struct arch_breakpoint_data {
+};
+#endif
+
+#ifndef ARCH_HAVE_LIBRARY_SYMBOL_DATA
+struct arch_library_symbol_data {
+};
+#endif
+
+#ifndef ARCH_HAVE_LIBRARY_DATA
+struct arch_library_data {
+};
+#endif
+
+#ifndef OS_HAVE_PROCESS_DATA
+struct os_process_data {
+};
+#endif
+
+#ifndef ARCH_HAVE_PROCESS_DATA
+struct arch_process_data {
+};
+#endif
+
+#endif /* LTRACE_SYSDEP_H */