diff -Nru python-ptrace-0.7/AUTHORS python-ptrace-0.9.3/AUTHORS --- python-ptrace-0.7/AUTHORS 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/AUTHORS 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -python-ptrace authors -===================== - -Anthony Gelibert - fix cptrace on Apple -Dimitris Glynos - follow gdb.py commands -Jakub Wilk - fix for GNU/kFreeBSD -Mark Seaborn - Create -i option for strace -Mickaël Guérin aka KAeL - OpenBSD port -teythoon - convert all classes to new-style classes -T. Bursztyka aka Tuna - x86_64 port -Victor Stinner - python-ptrace author and maintainer - - -Thanks -====== - - * procps authors (top and uptime programs) - diff -Nru python-ptrace-0.7/ChangeLog python-ptrace-0.9.3/ChangeLog --- python-ptrace-0.7/ChangeLog 2014-03-05 13:44:29.000000000 +0000 +++ python-ptrace-0.9.3/ChangeLog 1970-01-01 00:00:00.000000000 +0000 @@ -1,156 +0,0 @@ -Changelog -========= - -python-ptrace 0.7 (2013-03-05) ------------------------------- - -* Experimental support of Python 3.3 in the same code base -* Drop support of Python 2.5 -* Remove the ptrace.compatibility module -* Fix Process.readStruct() and Process.readArray() on x86_64 -* Experimental support of ARM architecture (Linux EAPI), - strace.py has been tested on Raspberry Pi (armv6l) - -python-ptrace 0.6.6 (2013-12-16) --------------------------------- - -* Fix os_tools.RUNNING_LINUX for Python 2.x compiled on Linux kernel 3.x -* Support FreeBSD on x86_64 -* Add missing prototype of the unlinkat() system call. Patch written by - Matthew Fernandez. - -python-ptrace 0.6.5 (2013-06-06) --------------------------------- - -* syscall: fix parsing socketcall on Linux x86 -* syscall: fix protoype of socket() - -python-ptrace 0.6.4 (2012-02-26) --------------------------------- - -* Convert all classes to new-style classes, patch written by teythoon -* Fix compilation on Apple, patch written by Anthony Gelibert -* Support GNU/kFreeBSD, patch written by Jakub Wilk -* Support sockaddr_in6 (IPv6 address) - -python-ptrace 0.6.3 (2011-02-16) --------------------------------- - -* Support distrom3 -* Support Python 3 -* Rename strace.py option --socketcall to --socket, and fix this option for - FreeBSD and Linux/64 bits -* Add MANIFEST.in: include all files in source distribution (tests, cptrace - module, ...) - -python-ptrace 0.6.2 (2009-11-09) --------------------------------- - -* Fix 64 bits sub registers (set mask for eax, ebx, ecx, edx) - -python-ptrace 0.6.1 (2009-11-07) --------------------------------- - -* Create follow, showfollow, resetfollow, xray commands in gdb.py. Patch - written by Dimitris Glynos -* Project website moved to http://bitbucket.org/haypo/python-ptrace/ -* Replace types (u)intXX_t by c_(u)intXX -* Create MemoryMapping.search() method and MemoryMapping now keeps a weak - reference to the process - -python-ptrace 0.6 (2009-02-13) ------------------------------- - -User visible changes: - -* python-ptrace now depends on Python 2.5 -* Invalid memory access: add fault address in the name -* Update Python 3.0 conversion patch -* Create -i (--show-ip) option to strace.py: show instruction pointer -* Add a new example (itrace.py) written by Mark Seaborn and based - on strace.py - -API changes: - -* PtraceSyscall: store the instruction pointer at syscall enter (if the - option instr_pointer=True, disabled by default) -* Remove PROC_DIRNAME and procFilename() from ptrace.linux_proc - -Bugfixes: - -* Fix locateProgram() for relative path -* Fix interpretation of memory fault on MOSVW instruction (source is ESI and - destination is EDI, and not the inverse!) - -python-ptrace 0.5 (2008-09-13) ------------------------------- - -Visible changes: - -* Write an example (the most simple debugger) and begin to document the code -* gdb.py: create "dbginfo" command -* Parse socket syscalls on FreeBSD -* On invalid memory access (SIGSEGV), eval the dereference expression to get - the fault address on OS without siginfo (eg. FreeBSD) -* Fixes to get minimal Windows support: fix imports, fix locateProgram() - -Other changes: - -* Break the API: - - Rename PtraceDebugger.traceSysgood() to PtraceDebugger.enableSysgood() - - Rename PtraceDebugger.trace_sysgood to PtraceDebugger.use_sysgood - - Remove PtraceProcess.readCode() -* Create createChild() function which close all files except stdin, - stdout and stderr -* On FreeBSD, on process exit recalls waitpid(pid) to avoid zombi process - - -python-ptrace 0.4.2 (2008-08-28) --------------------------------- - -* BUGFIX: Fix typo in gdb.py (commands => command_str), it wasn't possible to - write more than one command... -* BUGIFX: Fix typo in SignalInfo class (remove "self."). When a process - received a signal SIGCHLD (because of a fork), the debugger exited because - of this bug. -* BUGFIX: Debugger._wait() return abnormal process exit as a normal event, - the event is not raised as an exception -* PtraceSignal: don't clear preformatted arguments (eg. arguments of execve) - -python-ptrace 0.4.1 (2008-08-23) --------------------------------- - -* The project has a new dedicated website: http://python-ptrace.hachoir.org/ -* Create cptrace: optional Python binding of ptrace written in C (faster - than ptrace, the Python binding written in Python with ctypes) -* Add name attribute to SignalInfo classes -* Fixes to help Python 3.0 compatibility: don't use sys.exc_clear() - (was useless) in writeBacktrace() -* ProcessState: create utime, stime, starttime attributes - -python-ptrace 0.4.0 (2008-08-19) --------------------------------- - -Visible changes: - -* Rename the project to "python-ptrace" (old name was "Ptrace) -* strace.py: create --ignore-regex option -* PtraceSignal: support SIGBUS, display the related registers and - the instruction -* Support execve() syscall tracing - -Developer changes: - -* New API is incompatible with 0.3.2 -* PtraceProcess.waitProcessEvent() accepts optional blocking=False argument -* PtraceProcess.getreg()/setreg() are able to read/write i386 and x86-64 - "sub-registers" like al or bx -* Remove iterProc() function, replaced by openProc() with explicit - call to .close() to make sure that files are closed -* Create searchProcessesByName() -* Replace CPU_PPC constant by CPU_POWERPC and create CPU_PPC32 and CPU_PPC64 -* Create MemoryMapping object, used by readMappings() and findStack() methods - of PtraceProcess -* Always define all PtraceProcess methods but raise an error if the function - is not implemented - diff -Nru python-ptrace-0.7/cptrace/cptrace.c python-ptrace-0.9.3/cptrace/cptrace.c --- python-ptrace-0.7/cptrace/cptrace.c 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/cptrace/cptrace.c 2017-02-10 11:22:40.000000000 +0000 @@ -21,6 +21,7 @@ unsigned long *result) { unsigned long ret; + errno = 0; ret = ptrace(request, pid, arg1, arg2); if ((long)ret == -1) { /** diff -Nru python-ptrace-0.7/cptrace/version.py python-ptrace-0.9.3/cptrace/version.py --- python-ptrace-0.7/cptrace/version.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/cptrace/version.py 2017-02-10 11:22:40.000000000 +0000 @@ -1,4 +1,4 @@ PACKAGE = "cptrace" VERSION = "0.6.1" -WEBSITE = "http://python-ptrace.hachoir.org/" +WEBSITE = "http://python-ptrace.readthedocs.io/" LICENSE = "GNU GPL v2" diff -Nru python-ptrace-0.7/debian/changelog python-ptrace-0.9.3/debian/changelog --- python-ptrace-0.7/debian/changelog 2014-08-21 18:58:06.000000000 +0000 +++ python-ptrace-0.9.3/debian/changelog 2018-04-29 12:41:32.000000000 +0000 @@ -1,3 +1,21 @@ +python-ptrace (0.9.3-2) unstable; urgency=medium + + * Fix spelling error + * Add python3 package (Closes: #782949) + + -- Pierre Chifflier Sun, 29 Apr 2018 14:41:32 +0200 + +python-ptrace (0.9.3-1) unstable; urgency=medium + + * New upstream version 0.9.3 (Closes: #814262) + * Remove patch 10-set_errno_to_0_if_no_error, merged upstream + * Refreshed quilt patches + * Update homepage (Closes: #888910) + * Change priority from extra to optional + * Bump Standards Version to 4.1.4 + + -- Pierre Chifflier Sun, 29 Apr 2018 14:24:08 +0200 + python-ptrace (0.7-1) unstable; urgency=medium * Imported Upstream version 0.7 diff -Nru python-ptrace-0.7/debian/control python-ptrace-0.9.3/debian/control --- python-ptrace-0.7/debian/control 2014-08-21 09:26:20.000000000 +0000 +++ python-ptrace-0.9.3/debian/control 2018-04-29 12:35:55.000000000 +0000 @@ -1,11 +1,12 @@ Source: python-ptrace Section: python -Priority: extra +Priority: optional Maintainer: Pierre Chifflier Build-Depends: debhelper (>= 9), - python-all (>= 2.3.5-11) -Standards-Version: 3.9.5 -Homepage: http://fusil.hachoir.org/trac/wiki/Ptrace + python-all (>= 2.3.5-11), + python3-dev +Standards-Version: 4.1.4 +Homepage: https://github.com/vstinner/python-ptrace Package: python-ptrace Architecture: all @@ -14,7 +15,7 @@ Provides: ${python:Provides} Description: Python bindings for ptrace This package provides Python bindings for the ptrace library. It allows - to control, debug, or modify processes using the ptrace syscall. + controlling, debugging, or modifying processes using the ptrace syscall. . Features: * High level Python object API @@ -24,3 +25,25 @@ * Can use distorm disassembler * Dump registers, memory mappings, stack, etc. * Syscall tracer and parser (strace command) + . + This package provides the ptrace Python module for Python 2.x. + +Package: python3-ptrace +Architecture: all +XB-Python-Version: ${python3:Versions} +Depends: ${python3:Depends}, ${misc:Depends} +Provides: ${python3:Provides} +Description: Python 3 bindings for ptrace + This package provides Python bindings for the ptrace library. It allows + controlling, debugging, or modifying processes using the ptrace syscall. + . + Features: + * High level Python object API + * Able to control multiple processes: catch fork events + * Read/write bytes to arbitrary addresses + * Execution step by step using ptrace_singlestep() or hardware int 3 + * Can use distorm disassembler + * Dump registers, memory mappings, stack, etc. + * Syscall tracer and parser (strace command) + . + This package provides the ptrace Python module for Python 3.x. diff -Nru python-ptrace-0.7/debian/patches/10-set_errno_to_0_if_no_error.patch python-ptrace-0.9.3/debian/patches/10-set_errno_to_0_if_no_error.patch --- python-ptrace-0.7/debian/patches/10-set_errno_to_0_if_no_error.patch 2012-05-06 20:06:39.000000000 +0000 +++ python-ptrace-0.9.3/debian/patches/10-set_errno_to_0_if_no_error.patch 1970-01-01 00:00:00.000000000 +0000 @@ -1,48 +0,0 @@ -Index: python-ptrace/cptrace/cptrace.c -=================================================================== ---- python-ptrace.orig/cptrace/cptrace.c 2012-04-28 12:03:07.145652296 +0200 -+++ python-ptrace/cptrace/cptrace.c 2012-04-28 16:40:15.941112538 +0200 -@@ -21,6 +21,7 @@ - unsigned long *result) - { - unsigned long ret; -+ errno = 0; - ret = ptrace(request, pid, arg1, arg2); - if ((long)ret == -1) { - /** -Index: python-ptrace/ptrace/binding/func.py -=================================================================== ---- python-ptrace.orig/ptrace/binding/func.py 2011-06-11 16:24:42.000000000 +0200 -+++ python-ptrace/ptrace/binding/func.py 2012-04-28 16:40:25.897112573 +0200 -@@ -118,6 +118,7 @@ - except ImportError: - HAS_CPTRACE = False - from ctypes import c_long, c_ulong -+ from ctypes import get_errno, set_errno - from ptrace.ctypes_libc import libc - - # Load ptrace() function from the system C library -@@ -134,6 +135,7 @@ - errno = get_errno() - raise PtraceError(message, errno=errno, pid=pid) - else: -+ set_errno(0) - result = _ptrace(command, pid, arg1, arg2) - result_signed = c_long(result).value - if result_signed == -1: -Index: python-ptrace/ptrace/ctypes_libc.py -=================================================================== ---- python-ptrace.orig/ptrace/ctypes_libc.py 2011-06-11 16:24:22.000000000 +0200 -+++ python-ptrace/ptrace/ctypes_libc.py 2012-04-28 16:40:25.897112573 +0200 -@@ -4,9 +4,9 @@ - - libc: the loaded library - """ - --from ctypes import cdll -+from ctypes import CDLL - from ctypes.util import find_library - - LIBC_FILENAME = find_library('c') --libc = cdll.LoadLibrary(LIBC_FILENAME) -+libc = CDLL(LIBC_FILENAME, use_errno=True) - diff -Nru python-ptrace-0.7/debian/patches/20-fix-egginfo-sources.patch python-ptrace-0.9.3/debian/patches/20-fix-egginfo-sources.patch --- python-ptrace-0.7/debian/patches/20-fix-egginfo-sources.patch 2014-08-21 09:25:01.000000000 +0000 +++ python-ptrace-0.9.3/debian/patches/20-fix-egginfo-sources.patch 2018-04-29 12:11:01.000000000 +0000 @@ -2,15 +2,15 @@ =================================================================== --- python-ptrace.orig/python_ptrace.egg-info/SOURCES.txt +++ python-ptrace/python_ptrace.egg-info/SOURCES.txt -@@ -8,6 +8,7 @@ README.cptrace - TODO +@@ -4,6 +4,7 @@ README.rst gdb.py pyflakes.sh + runtests.py +setup.cfg setup.py setup_cptrace.py strace.py -@@ -90,4 +91,4 @@ tests/crash/invalid_read.c +@@ -101,4 +102,4 @@ tests/crash/invalid_read.c tests/crash/invalid_write.c tests/crash/pthread.c tests/crash/socket_ipv4_tcp.c diff -Nru python-ptrace-0.7/debian/patches/series python-ptrace-0.9.3/debian/patches/series --- python-ptrace-0.7/debian/patches/series 2014-08-21 09:24:40.000000000 +0000 +++ python-ptrace-0.9.3/debian/patches/series 2018-04-29 12:09:27.000000000 +0000 @@ -1,2 +1 @@ -10-set_errno_to_0_if_no_error.patch 20-fix-egginfo-sources.patch diff -Nru python-ptrace-0.7/debian/rules python-ptrace-0.9.3/debian/rules --- python-ptrace-0.7/debian/rules 2012-05-06 20:06:39.000000000 +0000 +++ python-ptrace-0.9.3/debian/rules 2018-04-29 12:37:01.000000000 +0000 @@ -2,12 +2,14 @@ # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 +export PYBUILD_NAME=ptrace override_dh_auto_install: dh_auto_install # do not install examples as real executables rm -rf $(CURDIR)/debian/python-ptrace/usr/bin + rm -rf $(CURDIR)/debian/python3-ptrace/usr/bin %: - dh $@ --with=python2 + dh $@ --with=python2,python3 --buildsystem=pybuild diff -Nru python-ptrace-0.7/doc/authors.rst python-ptrace-0.9.3/doc/authors.rst --- python-ptrace-0.7/doc/authors.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/authors.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,21 @@ ++++++++ +Authors ++++++++ + +Contributors +============ + +* Anthony Gelibert - fix cptrace on Apple +* Dimitris Glynos - follow gdb.py commands +* Jakub Wilk - fix for GNU/kFreeBSD +* Mark Seaborn - Create -i option for strace +* Mickaël Guérin aka KAeL - OpenBSD port +* teythoon - convert all classes to new-style classes +* T. Bursztyka aka Tuna - x86_64 port +* Victor Stinner - python-ptrace author and maintainer + +Thanks +====== + +* procps authors (top and uptime programs) + diff -Nru python-ptrace-0.7/doc/changelog.rst python-ptrace-0.9.3/doc/changelog.rst --- python-ptrace-0.7/doc/changelog.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/changelog.rst 2017-09-19 09:00:40.000000000 +0000 @@ -0,0 +1,212 @@ +.. _changelog: + +Changelog +========= + +python-ptrace 0.9.3 (2017-09-19) +-------------------------------- + +* Issue #42: Fix test_strace.py: tolerate the openat() syscall. + +python-ptrace 0.9.2 (2017-02-12) +-------------------------------- + +* Issue #35: Fix strace.py when tracing multiple processes: use the correct + process. Fix suggested by Daniel Trnka. + +python-ptrace 0.9.1 (2016-10-12) +-------------------------------- + +* Added tracing of processes created with the clone syscall (commonly known as + threads). +* gdb.py: add ``gcore`` command, dump the process memory. +* Allow command names without absolute path. +* Fix ptrace binding: clear errno before calling ptrace(). +* Fix PtraceSyscall.exit() for unknown error code +* Project moved to GitHub: https://github.com/haypo/python-ptrace +* Remove the ``ptrace.ctypes_errno`` module: use directly + the ``ctypes.get_errno()`` function +* Remove the ``ptrace.ctypes_errno`` module: use directly + ``ctypes.c_int8``, ``ctypes.c_uint32``, ... types + +python-ptrace 0.9 (2016-04-23) +------------------------------ + +* Add all Linux syscall prototypes +* Add error symbols (e.g. ENOENT), in addition to error text, for strace +* Fix open mode so O_RDONLY shows if it's the only file access mode +* Python 3: fix formatting of string syscall arguments (ex: filenames), decode + bytes from the locale encoding +* Issue #17: syscall parser now supports O_CLOEXEC and SOCK_CLOEXEC, fix unit + tests on Python 3.4 and newer + +python-ptrace 0.8.1 (2014-10-30) +-------------------------------- + +* Update MANIFEST.in to include all files +* Fix to support Python 3.5 + +python-ptrace 0.8 (2014-10-05) +------------------------------ + +* Issue #9: Rewrite waitProcessEvent() and waitSignals() methods of + PtraceProcess to not call waitpid() with pid=-1. There is a race condition + with waitpid(-1) and fork, the status of the child process may be returned + before the debugger is noticed of the creation of the new child process. +* Issue #10: Fix PtraceProcess.readBytes() for processes not created by the + debugger (ex: fork) if the kernel blocks access to private mappings of + /proc/pid/mem. Fallback to PTRACE_PEEKTEXT which is slower but a debugger + tracing the process is always allowed to use it. + +python-ptrace 0.7 (2013-03-05) +------------------------------ + +* Experimental support of Python 3.3 in the same code base +* Drop support of Python 2.5 +* Remove the ptrace.compatibility module +* Fix Process.readStruct() and Process.readArray() on x86_64 +* Experimental support of ARM architecture (Linux EAPI), + strace.py has been tested on Raspberry Pi (armv6l) + +python-ptrace 0.6.6 (2013-12-16) +-------------------------------- + +* Fix os_tools.RUNNING_LINUX for Python 2.x compiled on Linux kernel 3.x +* Support FreeBSD on x86_64 +* Add missing prototype of the unlinkat() system call. Patch written by + Matthew Fernandez. + +python-ptrace 0.6.5 (2013-06-06) +-------------------------------- + +* syscall: fix parsing socketcall on Linux x86 +* syscall: fix prototype of socket() + +python-ptrace 0.6.4 (2012-02-26) +-------------------------------- + +* Convert all classes to new-style classes, patch written by teythoon +* Fix compilation on Apple, patch written by Anthony Gelibert +* Support GNU/kFreeBSD, patch written by Jakub Wilk +* Support sockaddr_in6 (IPv6 address) + +python-ptrace 0.6.3 (2011-02-16) +-------------------------------- + +* Support distrom3 +* Support Python 3 +* Rename strace.py option --socketcall to --socket, and fix this option for + FreeBSD and Linux/64 bits +* Add MANIFEST.in: include all files in source distribution (tests, cptrace + module, ...) + +python-ptrace 0.6.2 (2009-11-09) +-------------------------------- + +* Fix 64 bits sub registers (set mask for eax, ebx, ecx, edx) + +python-ptrace 0.6.1 (2009-11-07) +-------------------------------- + +* Create follow, showfollow, resetfollow, xray commands in gdb.py. Patch + written by Dimitris Glynos +* Project website moved to http://bitbucket.org/haypo/python-ptrace/ +* Replace types (u)intXX_t by c_(u)intXX +* Create MemoryMapping.search() method and MemoryMapping now keeps a weak + reference to the process + +python-ptrace 0.6 (2009-02-13) +------------------------------ + +User visible changes: + +* python-ptrace now depends on Python 2.5 +* Invalid memory access: add fault address in the name +* Update Python 3.0 conversion patch +* Create -i (--show-ip) option to strace.py: show instruction pointer +* Add a new example (itrace.py) written by Mark Seaborn and based + on strace.py + +API changes: + +* PtraceSyscall: store the instruction pointer at syscall enter (if the + option instr_pointer=True, disabled by default) +* Remove PROC_DIRNAME and procFilename() from ptrace.linux_proc + +Bugfixes: + +* Fix locateProgram() for relative path +* Fix interpretation of memory fault on MOSVW instruction (source is ESI and + destination is EDI, and not the inverse!) + +python-ptrace 0.5 (2008-09-13) +------------------------------ + +Visible changes: + +* Write an example (the most simple debugger) and begin to document the code +* gdb.py: create "dbginfo" command +* Parse socket syscalls on FreeBSD +* On invalid memory access (SIGSEGV), eval the dereference expression to get + the fault address on OS without siginfo (e.g. FreeBSD) +* Fixes to get minimal Windows support: fix imports, fix locateProgram() + +Other changes: + +* Break the API: + - Rename PtraceDebugger.traceSysgood() to PtraceDebugger.enableSysgood() + - Rename PtraceDebugger.trace_sysgood to PtraceDebugger.use_sysgood + - Remove PtraceProcess.readCode() +* Create createChild() function which close all files except stdin, + stdout and stderr +* On FreeBSD, on process exit recalls waitpid(pid) to avoid zombi process + + +python-ptrace 0.4.2 (2008-08-28) +-------------------------------- + +* BUGFIX: Fix typo in gdb.py (commands => command_str), it wasn't possible to + write more than one command... +* BUGFIX: Fix typo in SignalInfo class (remove "self."). When a process + received a signal SIGCHLD (because of a fork), the debugger exited because + of this bug. +* BUGFIX: Debugger._wait() return abnormal process exit as a normal event, + the event is not raised as an exception +* PtraceSignal: don't clear preformatted arguments (e.g. arguments of execve) + +python-ptrace 0.4.1 (2008-08-23) +-------------------------------- + +* The project has a new dedicated website: http://python-ptrace.hachoir.org/ +* Create cptrace: optional Python binding of ptrace written in C (faster + than ptrace, the Python binding written in Python with ctypes) +* Add name attribute to SignalInfo classes +* Fixes to help Python 3.0 compatibility: don't use sys.exc_clear() + (was useless) in writeBacktrace() +* ProcessState: create utime, stime, starttime attributes + +python-ptrace 0.4.0 (2008-08-19) +-------------------------------- + +Visible changes: + +* Rename the project to "python-ptrace" (old name was "Ptrace) +* strace.py: create --ignore-regex option +* PtraceSignal: support SIGBUS, display the related registers and + the instruction +* Support execve() syscall tracing + +Developer changes: + +* New API is incompatible with 0.3.2 +* PtraceProcess.waitProcessEvent() accepts optional blocking=False argument +* PtraceProcess.getreg()/setreg() are able to read/write i386 and x86-64 + "sub-registers" like al or bx +* Remove iterProc() function, replaced by openProc() with explicit + call to .close() to make sure that files are closed +* Create searchProcessesByName() +* Replace CPU_PPC constant by CPU_POWERPC and create CPU_PPC32 and CPU_PPC64 +* Create MemoryMapping object, used by readMappings() and findStack() methods + of PtraceProcess +* Always define all PtraceProcess methods but raise an error if the function + is not implemented diff -Nru python-ptrace-0.7/doc/conf.py python-ptrace-0.9.3/doc/conf.py --- python-ptrace-0.7/doc/conf.py 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/conf.py 2017-02-12 18:08:46.000000000 +0000 @@ -0,0 +1,240 @@ +# -*- coding: utf-8 -*- +# +# python-ptrace documentation build configuration file, created by +# sphinx-quickstart on Mon Mar 31 10:08:56 2014. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'python-ptrace' +copyright = u'2014, Victor Stinner' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = release = '0.9.3' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'python-ptracedoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'python-ptrace.tex', u'python-ptrace Documentation', + u'Victor Stinner', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'python-ptrace', u'python-ptrace Documentation', + [u'Victor Stinner'], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------------ + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + ('index', 'python-ptrace', u'python-ptrace Documentation', + u'Victor Stinner', 'python-ptrace', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' diff -Nru python-ptrace-0.7/doc/cptrace.rst python-ptrace-0.9.3/doc/cptrace.rst --- python-ptrace-0.7/doc/cptrace.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/cptrace.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,18 @@ ++++++++++++++++++++++ +cptrace Python module ++++++++++++++++++++++ + +Python binding for ptrace written in C. + +Example +======= + +Dummy example: :: + + >>> import cptrace + >>> cptrace.ptrace(1, 1) + Traceback (most recent call last): + File "", line 1, in + ValueError: ptrace(request=1, pid=1, 0x(nil), 0x(nil)) error #1: Operation not permitted + + diff -Nru python-ptrace-0.7/doc/gdb.rst python-ptrace-0.9.3/doc/gdb.rst --- python-ptrace-0.7/doc/gdb.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/gdb.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,108 @@ +++++++ +gdb.py +++++++ + +``gdb.py`` is a command line debugger *similar to gdb*, but with fewer +features: no symbol support, no C language support, no thread support, etc. + +Some commands +============= + +* ``cont``: continue execution +* ``stepi``: execute one instruction +* ``step``: execute one instruction, but don't enter into calls + +Type ``help`` to list all available commands. + + +Features +======== + +* print command displays value as decimal and hexadecimal, but also the related + memory mapping (if any):: + + (gdb) print $eip + Decimal: 3086383120 + Hexadecimal: 0xb7f67810 + Address is part of mapping: 0xb7f67000-0xb7f81000 => /lib/ld-2.6.1.so (r-xp) + +* Nice output of signal: see [[signal|python-ptrace signal handling]] +* Syscall tracer with command "sys": see `python-ptrace system call tracer `. Short example:: + + (gdb) sys + long access(char* filename='/etc/ld.so.nohwcap' at 0xb7f7f35b, int mode=F_OK) = -2 (No such file or directory) + +* Supports multiple processes:: + + (gdb) proclist + (active) + + (gdb) proc + Process ID: 24187 (parent: 24182) + Process state: T (traced) + Process command line: [['tests/fork_execve'] + (...) + (gdb)|switch; proc + Switch to + Process ID: 24188 (parent: 24187) + Process state: T (traced) + Process command line: ['/bin/ls']] + (...) + +* Allow multiple commands on the same line using ";" separator:: + + (gdb) print $eax; set $ax=0xdead; print $eax + Decimal: 0 + Hexadecimal: 0x00000000 + Set $ax to 57005 + Decimal: 57005 + Hexadecimal: 0x0000dead + +* Only written in pure Python code, so it's easy to extend +* Expression parser supports all arithmetic operator (``a+b``, ``a/b``, ``a< + Quit gdb. + diff -Nru python-ptrace-0.7/doc/index.rst python-ptrace-0.9.3/doc/index.rst --- python-ptrace-0.7/doc/index.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/index.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,101 @@ +============= +python-ptrace +============= + +python-ptrace is a debugger using ptrace (Linux, BSD and Darwin system call to +trace processes) written in Python. + +* `python-ptrace documentation + `_ +* `python-ptrace at GitHub + `_ +* `python-ptrace at the Python Cheeseshop (PyPI) + `_ + +python-ptrace is an opensource project written in Python under GNU GPLv2 +license. + + +Features +======== + +* High level Python object API : PtraceDebugger and PtraceProcess +* Able to control multiple processes: catch fork events on Linux +* Read/write bytes to arbitrary address: take care of memory alignment and + split bytes to cpu word +* Execution step by step using ptrace_singlestep() or hardware interruption 3 +* Can use `distorm `_ disassembler +* Dump registers, memory mappings, stack, etc. +* :ref:`Syscall tracer and parser ` (strace.py command) + +Status: + +* Supported operating systems: Linux, FreeBSD, OpenBSD +* Supported architectures: x86, x86_64 (Linux), PPC (Linux), ARM (Linux EAPI) + +Missing features: + +* Symbols: it's not possible to break on a function or read a variable value +* No C language support: debugger shows assembler code, not your C (C++ or other language) code! +* No thread support + + +Table of Contents +================= + +.. toctree:: + :maxdepth: 2 + + install + usage + syscall + gdb + process_events + ptrace_signal + cptrace + authors + changelog + todo + + +Links +===== + +Project using python-ptrace +--------------------------- + +* `Fusil the fuzzer `_ + + +python-ptrace announces +----------------------- + +* `fuzzing mailing list `_ +* `reverse-engineering.net `_ + +ptrace usage +------------ + +* Sandboxing: `Plash `_ + +Similar projects +---------------- + +* `vtrace `_: Python library (Windows and Linux) supporting threads +* `subterfuge `_ by Mike Coleman: Python library (Linux): contains Python binding of ptrace written in C for Python 2.1/2.2. It doesn't work with Python 2.5 (old project, not maintained since 2002) +* `strace `_ program (Linux, BSD) +* ltrace program (Linux) +* truss program (Solaris and BSD) +* `pytstop `_ by Philippe Biondi: debugger similar to gdb but in very alpha stage (e.g. no disassembler), using ptrace Python binding written in C (from subterfuge) +* `strace.py `_ by Philippe Biondi +* `Fenris `_: suite of tools suitable for code analysis, debugging, protocol analysis, reverse engineering, forensics, diagnostics, security audits, vulnerability research +* `PyDBG `_: Windows debugger written in pure Python + +Interesting articles +----------------------- + +* (fr) `Surveiller les connexions avec auditd `_ (2007) +* `Playing with ptrace() for fun and profit `_ (2006) +* `PTRACE_SETOPTIONS tests `_ (2005) +* `Process Tracing Using Ptrace `_ (2002) + diff -Nru python-ptrace-0.7/doc/install.rst python-ptrace-0.9.3/doc/install.rst --- python-ptrace-0.7/doc/install.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/install.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,100 @@ ++++++++++++++++++++++ +Install python-ptrace ++++++++++++++++++++++ + +Linux packages +============== + +* Debian: `python-ptrace Debian package `_. +* Mandriva: `python-ptrace Mandriva package `_ +* OpenEmbedded: `python-ptrace recipe `_ +* Arch Linux: `python-ptrace Arch Linux package `_ +* Gentoo: `dev-python/python-ptrace `_ + +See also `python-ptrace on Python Package Index (PyPI) `_ + +Install from source +=================== + +Download tarball +---------------- + +Get the latest tarball at the `Python Package Index (PyPI) +`_. + +Download development version +---------------------------- + +Download the development version using Git:: + + git clone https://github.com/haypo/python-ptrace.git + +`Browse python-ptrace source code +`_. + + +python-ptrace dependencies +-------------------------- + +* Python 2.6+/3.3+: + http://python.org/ +* distorm disassembler (optional) + http://www.ragestorm.net/distorm/ + + +Installation +------------ + +Type as root:: + + python setup.py install + +Or using sudo program:: + + sudo python setup.py install + + +cptrace +======= + +For faster debug and to avoid ctypes, you can also install cptrace: Python +binding of the ptrace() function written in C:: + + python setup_cptrace.py install + + +Run tests +========= + +Run tests with tox +------------------ + +The `tox project `_ can be used to build a +virtual environment run tests against different Python versions (Python 2 and +Python 3). + +To run all tests on Python 2 and Python 3, just type:: + + tox + +To only run tests on Python 2.7, type:: + + tox -e py2 + +Available environments: + +* ``py2``: Python 2 +* ``py3``: Python 3 + + +Run tests manually +------------------ + +Type:: + + python runtests.py + python test_doc.py + +It's also possible to run a specific test:: + + PYTHONPATH=$PWD python tests/test_strace.py diff -Nru python-ptrace-0.7/doc/make.bat python-ptrace-0.9.3/doc/make.bat --- python-ptrace-0.7/doc/make.bat 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/make.bat 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,190 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +set I18NSPHINXOPTS=%SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\python-ptrace.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\python-ptrace.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff -Nru python-ptrace-0.7/doc/Makefile python-ptrace-0.9.3/doc/Makefile --- python-ptrace-0.7/doc/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/Makefile 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,153 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/python-ptrace.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/python-ptrace.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/python-ptrace" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/python-ptrace" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff -Nru python-ptrace-0.7/doc/process_events.rst python-ptrace-0.9.3/doc/process_events.rst --- python-ptrace-0.7/doc/process_events.rst 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/doc/process_events.rst 2017-02-10 11:22:40.000000000 +0000 @@ -1,18 +1,22 @@ +++++++++++++++++++++++++++++ +python-ptrace process events +++++++++++++++++++++++++++++ + Process events ============== All process events are based on ProcessEvent class. - * ProcessExit: process exited with an exitcode, killed by a signal - or exited abnormally - * ProcessSignal: process received a signal - * NewProcessEvent: new process created, eg. after a fork() syscall +* ProcessExit: process exited with an exitcode, killed by a signal + or exited abnormally +* ProcessSignal: process received a signal +* NewProcessEvent: new process created, e.g. after a fork() syscall Attributes: - * All events have a "process" attribute - * ProcessExit has "exitcode" and "signum" attributes (both can be None) - * ProcessSignal has "signum" and "name" attributes +* All events have a "process" attribute +* ProcessExit has "exitcode" and "signum" attributes (both can be None) +* ProcessSignal has "signum" and "name" attributes For NewProcessEvent, use process.parent attribute to get the parent process. diff -Nru python-ptrace-0.7/doc/ptrace_signal.rst python-ptrace-0.9.3/doc/ptrace_signal.rst --- python-ptrace-0.7/doc/ptrace_signal.rst 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/doc/ptrace_signal.rst 2017-02-10 11:22:40.000000000 +0000 @@ -1,19 +1,116 @@ -++++++++++++ -PtraceSignal -++++++++++++ +.. _signal: ++++++++++++++++++++++++++++++ +python-ptrace signal handling ++++++++++++++++++++++++++++++ Introduction ============ -PtraceSignal tries to display useful informations when a signal is received. -Depending on the signal number, it show different informations. +PtraceSignal tries to display useful information when a signal is received. +Depending on the signal number, it shows different information. It uses the current instruction decoded as assembler code to understand why the signal is raised. Only Intel x86 (i386, maybe x86_64) is supported now. +When a process receives a signal, python-ptrace tries to explain why the signal was emitted. + +General information (not shown for all signals, e.g. not for SIGABRT): + +* CPU instruction causing the crash +* CPU registers related to the crash +* Memory mappings of the memory addresses + +Categorize signals: + +* SIGFPE + + - Division by zero + +* SIGSEGV, SIGBUS + + - Invalid memory read + - Invalid memory write + - Stack overflow + - Invalid memory access + +* SIGABRT + + - Program abort + +* SIGCHLD + + - Child process exit + +Examples +======== + +Division by zero (SIGFPE) +------------------------- + +:: + + Signal: SIGFPE + Division by zero + - instruction: IDIV DWORD [[EBP-0x8] + - register ebp=0xbfdc4a98 + +Invalid memory read/write (SIGSEGV) +----------------------------------- + +:: + + Signal: SIGSEGV + Invalid read from 0x00000008 + - instruction: MOV EAX, [EAX+0x8]] + - mapping: 0x00000008 is not mapped in memory + - register eax=0x00000000 + +:: + + PID: 23766 + Signal: SIGSEGV + Invalid write to 0x00000008 (size=4 bytes) + - instruction: MOV DWORD [[EAX+0x8],|0x2a + - mapping: 0x00000008..0x0000000b is not mapped in memory + - register eax=0x00000000 + +Given information: + +* Address of the segmentation fault +* (if possible) Size of the invalid memory read/write +* CPU instruction causing the crash +* CPU registers related to the crash +* Memory mappings of the related memory address + +Stack overflow (SIGSEGV) +------------------------ + +:: + + Signal: SIGSEGV + STACK OVERFLOW! Stack pointer is in 0xbf534000-0xbfd34000 => [stack]] (rw-p) + - instruction: MOV BYTE [[EBP-0x1004],|0x0 + - mapping: 0xbf533430 is not mapped in memory + - register =0xbf533430 + - register ebp=0xbf534448 + +Child exit (SIGCHLD) +-------------------- + +:: + + PID: 24008 + Signal: SIGCHLD + Child process 24009 exited normally + Signal sent by user 1000 + +Information: + +* Child process identifier +* Child process user identifier Examples ======== @@ -39,3 +136,12 @@ Signal: SIGABRT Program received signal SIGABRT, Aborted. +Source code +=========== + +See: + +* ``ptrace/debugger/ptrace_signal.py`` +* ``ptrace/debugger/signal_reason.py`` + + diff -Nru python-ptrace-0.7/doc/syscall.rst python-ptrace-0.9.3/doc/syscall.rst --- python-ptrace-0.7/doc/syscall.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/syscall.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,84 @@ +.. _syscall: + ++++++++++++++++++++++++++++++ +Trace system calls (syscalls) ++++++++++++++++++++++++++++++ + +python-ptrace can trace system calls using ``PTRACE_SYSCALL``. + +PtraceSyscall +============= + +ptrace.syscall module contains PtraceSyscall class: it's a parser of Linux +syscalls similar to strace program. + +Example:: + + connect(5, , 28) = 0 + open('/usr/lib/i686/cmov/libcrypto.so.0.9.8', 0, 0 ) = 4 + mmap2(0xb7e87000, 81920, 3, 2066, 4, 297) = 0xb7e87000 + rt_sigaction(SIGWINCH, 0xbfb7d4a8, 0xbfb7d41c, 8) = 0 + +You can get more information: result type, value address, argument types, and +argument names. + +Examples:: + + long open(const char* filename='/usr/lib/i686/cmov/libcrypto.so.0.9.8' at 0xb7efc027, int flags=0, int mode=0 ) = 4 + long fstat64(unsigned long fd=4, struct stat* buf=0xbfa46e2c) = 0 + long set_robust_list(struct robust_list_head* head=0xb7be5710, size_t len_ptr=12) = 0 + + +strace.py +========= + +Program strace.py is very close to strace program: display syscalls of a program. Example: + + +Features +-------- + +* Nice output of signal: see [[signal|python-ptrace signal handling]] +* Supports multiple processes +* Can trace running process +* Can display arguments name, type and address +* Option ``--filename`` to show only syscall using file names +* Option ``--socketcall`` to show only syscall related to network (socket usage) +* Option ``--syscalls`` to list all known syscalls + + +Example +------- + +:: + + $ ./strace.py /bin/ls + execve(/bin/ls, [['/bin/ls'],|[/* 40 vars */]]) = 756 + brk(0) = 0x0805c000 + access('/etc/ld.so.nohwcap', 0) = -2 (No such file or directory) + mmap2(NULL, 8192, 3, 34, -1, 0) = 0xb7f56000 + access('/etc/ld.so.preload', 4) = -2 (No such file or directory) + (...) + close(1) = 0 + munmap(0xb7c5c000, 4096) = 0 + exit_group(0) + ---done--- + + +Options +------- + +The program has many options. Example with ``--socketcall`` (display only +network functions):: + + $ ./strace.py --socketcall nc localhost 8080 + execve(/bin/nc, [['/bin/nc',|'localhost', '8080']], [[/*|40 vars */]]) = 12948 + socket(AF_FILE, SOCK_STREAM, 0) = 3 + connect(3, , 110) = -2 (No such file or directory) + socket(AF_FILE, SOCK_STREAM, 0) = 3 + connect(3, , 110) = -2 (No such file or directory) + socket(AF_INET, SOCK_STREAM, 6) = 3 + setsockopt(3, SOL_SOCKET, SO_REUSEADDR, 3217455272L, 4) = 0 + connect(3, , 16) = -111 (Connection refused) + (...) + diff -Nru python-ptrace-0.7/doc/todo.rst python-ptrace-0.9.3/doc/todo.rst --- python-ptrace-0.7/doc/todo.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/todo.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,53 @@ +TODO +==== + +Main tasks +---------- + +* Fix strace.py --socketcall: SyscallState.enter() calls ignore_callback + before socketcall are proceed +* Support other backends: + + - GDB MI: http://code.google.com/p/pygdb/ + - ktrace: (FreeBSD and Darwin): would help Darwin support + - utrace (new Linux debugger): http://sourceware.org/systemtap/wiki/utrace + - vtrace? + - PyDBG: works on Windows + +* Backtrace symbols: + + - GNU BFD? + - elfsh? + - addr2line program? + - See dl_iterate_phdr() function of libdl + +* Support other disassemblers (than distorm), and so both Intel syntax (Intel and AT&T) + + - BFD + - http://www.ragestorm.net/distorm/ + - libasm (ERESI) + - libdisasm (bastard) + - http://www.woodmann.com/collaborative/tools/index.php/Category:X86_Disassembler_Libraries + +* Support threads: other backends (than python-ptrace) already support threads + + +Minor tasks +----------- + +* Fix gdb.py "step" command on a jump. Example where step will never stop:: + + (gdb) where + ASM 0xb7e3b917: JMP 0xb7e3b8c4 (eb ab) + ASM 0xb7e3b919: LEA ESI, [ESI+0x0] (8db426 00000000) + +* Remove gdb.py "except PtraceError, err: if err.errno == ESRCH" hack, + process death detection should be done by PtraceProcess or PtraceDebugger +* Use Intel hardware breakpoints: set vtrace source code +* Support Darwin: + + - ktrace? need to recompile Darwin kernel with KTRACE option + - get registers: http://unixjunkie.blogspot.com/2006/01/darwin-ptrace-and-registers.html + - PT_DENY_ATTACH: http://steike.com/code/debugging-itunes-with-gdb/ + - PT_DENY_ATTACH: http://landonf.bikemonkey.org/code/macosx/ptrace_deny_attach.20041010201303.11809.mojo.html + diff -Nru python-ptrace-0.7/doc/usage.rst python-ptrace-0.9.3/doc/usage.rst --- python-ptrace-0.7/doc/usage.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/doc/usage.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,76 @@ ++++++++++++++++++++ +python-ptrace usage ++++++++++++++++++++ + +Hello World +=========== + +Short example attaching a running process. It gets the instruction pointer, +executes a single step, and gets the new instruction pointer:: + + import ptrace.debugger + import signal + import subprocess + import sys + + def debugger_example(pid): + debugger = ptrace.debugger.PtraceDebugger() + + print("Attach the running process %s" % pid) + process = debugger.addProcess(pid, False) + # process is a PtraceProcess instance + print("IP before: %#x" % process.getInstrPointer()) + + print("Execute a single step") + process.singleStep() + # singleStep() gives back control to the process. We have to wait + # until the process is trapped again to retrieve the control on the + # process. + process.waitSignals(signal.SIGTRAP) + print("IP after: %#x" % process.getInstrPointer()) + + process.detach() + debugger.quit() + + def main(): + args = [sys.executable, '-c', 'import time; time.sleep(60)'] + child_popen = subprocess.Popen(args) + debugger_example(child_popen.pid) + child_popen.kill() + child_popen.wait() + + if __name__ == "__main__": + main() + + +API +=== + +PtraceProcess +------------- + +The PtraceProcess class is an helper to manipulate a traced process. + +Example:: + + tracer = PtraceProcess(pid) # attach the process + tracer.singleStep() # execute one instruction + tracer.cont() # continue execution + tracer.syscall() # break at next syscall + tracer.detach() # detach process + + # Get status + tracer.getreg('al') # get AL register value + regs = tracer.getregs() # read all registers + bytes = tracer.readBytes(regs.ax, 10) # read 10 bytes + tracer.dumpCode() # dump code (as assembler or hexa is the disassembler is missing) + tracer.dumpStack() # dump stack (memory words around ESP) + + # Modify the process + shellcode = '...' + ip = tracer.getInstrPointer() # get EIP/RIP register + bytes = tracer.writeBytes(ip, shellcode) # write some bytes + tracer.setreg('ebx', 0) # set EBX register value to zero + +Read ``ptrace/debugger/process.py`` source code to see more methods. + diff -Nru python-ptrace-0.7/gdb.py python-ptrace-0.9.3/gdb.py --- python-ptrace-0.7/gdb.py 2014-03-05 13:22:31.000000000 +0000 +++ python-ptrace-0.9.3/gdb.py 2017-02-10 11:41:08.000000000 +0000 @@ -2,8 +2,8 @@ from __future__ import print_function from ptrace import PtraceError from ptrace.debugger import (PtraceDebugger, Application, - ProcessExit, NewProcessEvent, ProcessSignal, - ProcessExecution, ProcessError) + ProcessExit, NewProcessEvent, ProcessSignal, + ProcessExecution, ProcessError) from optparse import OptionParser from os import getpid from sys import stdout, stderr, exit @@ -13,7 +13,7 @@ from ptrace.binding import HAS_PTRACE_SINGLESTEP from ptrace.disasm import HAS_DISASSEMBLER from ptrace.ctypes_tools import (truncateWord, - formatWordHex, formatAddress, formatAddressRange, word2bytes) + formatWordHex, formatAddress, formatAddressRange, word2bytes) from ptrace.process_tools import dumpProcessInfo from ptrace.tools import inverseDict from ptrace.func_call import FunctionCallOptions @@ -38,14 +38,14 @@ if stdout.isatty(): try: # Use readline for better raw_input() - import readline + import readline # noqa except ImportError: pass # Match a register name: $eax, $gp0, $orig_eax REGISTER_REGEX = re.compile(r"\$[a-z]+[a-z0-9_]+") -#BYTES_REGEX = re.compile(r"""(?:'([^'\\]*)'|"([^"\\]*)")""") +# BYTES_REGEX = re.compile(r"""(?:'([^'\\]*)'|"([^"\\]*)")""") SIGNALS = inverseDict(SIGNAMES) # name -> signum @@ -62,9 +62,10 @@ # current process info ("regs", "display registers"), - ("where", "display true code content (show breakpoints effects on code). eg. 'where $eip', 'where $eip $eip+20'"), + ("where", "display true code content (show breakpoints effects on code). e.g. 'where $eip', 'where $eip $eip+20'"), ("print", "display a value (print )"), ("hexdump", "dump memory as specified address or address range (hexdump
or hexdump )"), + ("gcore", "generate core file of the process"), ("where2", "display original code content (don't show effects of breakpoint on code)"), ("stack", "display stack content"), ("backtrace", "dump the backtrace"), @@ -77,11 +78,11 @@ ("delete", "delete a breakpoint (delete
)"), # processes - ("attach", 'attach a new process (eg. "attach 2390")'), + ("attach", 'attach a new process (e.g. "attach 2390")'), ("proclist", "list of traced processes"), ("switch", "switch active process (switch or switch )"), - ("follow", r'''follow a term (eg. "follow '\x12\x14\x27\x13'")'''), + ("follow", r'''follow a term (e.g. "follow '\x12\x14\x27\x13'")'''), ("showfollow", 'show all "followed" terms'), ("resetfollow", 'reset all "followed" terms'), ("xray", 'show addresses of (and possible pointers to) "followed" terms'), @@ -92,6 +93,7 @@ ("help", "display this help"), ) + def formatAscii(data): def asciiChar(byte): if 32 <= byte <= 126: @@ -103,6 +105,7 @@ else: return u''.join(asciiChar(ord(byte)) for byte in data) + def formatHexa(data): if RUNNING_PYTHON3: return u' '.join(u"%02x" % byte for byte in data) @@ -111,6 +114,8 @@ # finds possible pointer values in process memory space, # pointing to address + + def getPointers(process, address): address = word2bytes(address) procmaps = readProcessMappings(process) @@ -118,7 +123,9 @@ for found in pm.search(address): yield found + class Gdb(Application): + def __init__(self): Application.__init__(self) @@ -146,7 +153,8 @@ self._setupLog(stdout) def parseOptions(self): - parser = OptionParser(usage="%prog [options] -- program [arg1 arg2 ...]") + parser = OptionParser( + usage="%prog [options] -- program [arg1 arg2 ...]") self.createCommonOptions(parser) self.createLogOptions(parser) self.options, self.program = parser.parse_args() @@ -255,8 +263,8 @@ def parseBytes(self, text): # FIXME: Validate input -# if not BYTES_REGEX.match(text): -# raise ValueError('Follow text must be enclosed in quotes!') + # if not BYTES_REGEX.match(text): + # raise ValueError('Follow text must be enclosed in quotes!') if PY3: text = 'b' + text.lstrip() value = eval(text) @@ -284,7 +292,7 @@ def xray(self): for process, procmap, address, term in self._xray(): pointers = " ".join(formatAddress(ptr_addr) - for ptr_addr in getPointers(process, address)) + for ptr_addr in getPointers(process, address)) print("term[%s] pid[%i] %s %s pointers: %s" % ( repr(term), process.pid, procmap, formatAddress(address), @@ -304,6 +312,8 @@ self.process.dumpRegs() elif command == "stack": self.process.dumpStack() + elif command == "gcore": + self.gcore(self.process) elif command == "backtrace": errmsg = self.backtrace() elif command == "where" or command.startswith("where "): @@ -363,12 +373,12 @@ except KeyError: pass try: - return SIGNALS["SIG"+command] + return SIGNALS["SIG" + command] except KeyError: pass try: return self.parseInteger(command) - except ValueError as err: + except ValueError: raise ValueError("Invalid signal number: %r" % command) def signal(self, command): @@ -399,6 +409,26 @@ error("Address is part of mapping: %s" % map) return None + def gcore(self, process): + import re + childPid = str(process).split('#')[-1][:-1] + maps_file = open("/proc/" + childPid + "/maps", 'r') + mem_file = open("/proc/" + childPid + "/mem", 'r', 0) + from sys import argv + dump = open("/vmdump/" + argv[1] + ".dump", "wb") + for line in maps_file.readlines(): # for each mapped region + m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line) + if m.group(3) == 'r': # if this is a readable region + if "/lib" not in line and "/usr" not in line: # for eliminating of shared libs + start = int(m.group(1), 16) + end = int(m.group(2), 16) + mem_file.seek(start) # seek to region start + chunk = mem_file.read(end - start) # read region contents + dump.write(chunk,) # dump contents to standard output + maps_file.close() + mem_file.close() + dump.close() + def hexdump(self, command): max_line = 20 width = (terminalWidth() - len(formatAddress(1)) - 3) // 4 @@ -412,11 +442,11 @@ end_address = self.parseInteger(parts[1]) if end_address <= start_address: raise ValueError('End address (%s) is smaller than start address(%s)!' - % (formatAddress(end_address), formatAddress(start_address))) + % (formatAddress(end_address), formatAddress(start_address))) except ValueError as err: return str(err) size = end_address - start_address - max_size = width*max_line + max_size = width * max_line if max_size < size: limited = max_size end_address = start_address + max_size @@ -425,7 +455,7 @@ start_address = self.parseInteger(command) except ValueError as err: return str(err) - end_address = start_address + 5*width + end_address = start_address + 5 * width read_error = None address = start_address @@ -437,7 +467,7 @@ # Format bytes hexa = formatHexa(memory) - hexa = hexa.ljust(width*3-1, ' ') + hexa = hexa.ljust(width * 3 - 1, ' ') ascii = formatAscii(memory) ascii = ascii.ljust(width, ' ') @@ -505,7 +535,7 @@ return 'Register name (%s) have to start with "$"' % key key = key[1:] except ValueError as err: - return "Invalid command: %r" % command + return "Invalid command: %r" % command try: value = self.parseInteger(value) except ValueError as err: @@ -532,7 +562,7 @@ try: pid = self.parseInteger(text) except ValueError as err: - return str(err) + return str(err) process = self.debugger.addProcess(pid, False) self.switchProcess(process) @@ -573,7 +603,7 @@ def newProcess(self, event): error("New process: %s" % event.process) - # FIXME: This function doesn't work multiple multiple processes + # FIXME: This function doesn't work with multiple processes # especially when a parent waits for a child def syscallTrace(self): # Trace until syscall enter @@ -602,7 +632,7 @@ try: address = self.parseInteger(command) except ValueError as err: - return str(err) + return str(err) errmsg = self.step(False, address) if errmsg: return errmsg @@ -622,7 +652,7 @@ try: pid = self.parseInteger(command) except ValueError as err: - return str(err) + return str(err) try: process = self.debugger[pid] self.switchProcess(process) @@ -705,7 +735,8 @@ error('') error("Value can be an hexadecimal/decimal number or a register name ($reg)") error("You can use operators a+b, a-b, a*b, a/b, a<>b, a**b, and parenthesis in expressions") - error('Use ";" to write multiple commands on the same line (eg. "step; print $eax")') + error( + 'Use ";" to write multiple commands on the same line (e.g. "step; print $eax")') def processSignal(self, event): event.display() @@ -854,6 +885,6 @@ error("Quit gdb.") self.restoreTerminal() + if __name__ == "__main__": Gdb().main() - diff -Nru python-ptrace-0.7/INSTALL python-ptrace-0.9.3/INSTALL --- python-ptrace-0.7/INSTALL 2014-03-05 12:15:17.000000000 +0000 +++ python-ptrace-0.9.3/INSTALL 1970-01-01 00:00:00.000000000 +0000 @@ -1,29 +0,0 @@ -ptrace dependencies -=================== - - * Python 2.5+: - http://python.org/ - * distorm disassembler (optional) - http://www.ragestorm.net/distorm/ - - -Installation -============ - -Type as root: :: - - ./setup.py install - -Or using sudo program: :: - - sudo python setup.py install - - -cptrace -======= - -For faster debug and to avoid ctypes, you can also install cptrace: Python -binding of the ptrace() function written in C: :: - - python setup_cptrace.py install - diff -Nru python-ptrace-0.7/MANIFEST.in python-ptrace-0.9.3/MANIFEST.in --- python-ptrace-0.7/MANIFEST.in 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/MANIFEST.in 2017-02-10 11:22:40.000000000 +0000 @@ -5,15 +5,23 @@ include MANIFEST.in include README.cptrace include TODO -include conv_python3.0.sh +include tox.ini include cptrace/Makefile include cptrace/cptrace.c include cptrace/version.py -include doc/*.rst + +include doc/*.rst doc/conf.py doc/make.bat doc/Makefile + include examples/itrace.py include examples/simple_dbg.py include pyflakes.sh include python3.0.patch include setup_cptrace.py + +# Tests +include runtests.py include test_doc.py +include tests/test_*.py include tests/crash/*.c +include tests/crash/BSDmakefile +include tests/crash/Makefile diff -Nru python-ptrace-0.7/PKG-INFO python-ptrace-0.9.3/PKG-INFO --- python-ptrace-0.7/PKG-INFO 2014-03-05 13:46:11.000000000 +0000 +++ python-ptrace-0.9.3/PKG-INFO 2017-09-19 09:03:19.000000000 +0000 @@ -1,202 +1,37 @@ Metadata-Version: 1.1 Name: python-ptrace -Version: 0.7 +Version: 0.9.3 Summary: python binding of ptrace -Home-page: http://bitbucket.org/haypo/python-ptrace/wiki/Home +Home-page: http://python-ptrace.readthedocs.io/ Author: Victor Stinner Author-email: UNKNOWN License: GNU GPL v2 -Download-URL: http://bitbucket.org/haypo/python-ptrace/wiki/Home -Description: python-ptrace is a Python binding of ptrace library. - - The binding works on: - - * Linux version 2.6.20 on i386, x86_64, PPC (may works on Linux 2.4.x - and 2.6.x) - * Linux version 2.4 on PPC - * FreeBSD version 7.0RC1 on i386 (may works on FreeBSD 5.x/6.x) - * OpenBSD version 4.2 on i386 - - Features: - - * High level Python object API : !PtraceDebugger and !PtraceProcess - * Able to control multiple processes: catch fork events on Linux - * Read/write bytes to arbitrary address: take care of memory alignment and - split bytes to cpu word - * Execution step by step using ptrace_singlestep() or hardware interruption 3 - * Can use distorm (http://www.ragestorm.net/distorm/) disassembler - * Dump registers, memory mappings, stack, etc. - * Syscall tracer and parser (strace command) - - Website: http://bitbucket.org/haypo/python-ptrace/wiki/Home - - - Installation - ============ - - Read INSTALL documentation file. - - Documentation +Download-URL: http://python-ptrace.readthedocs.io/ +Description-Content-Type: UNKNOWN +Description: ============= + python-ptrace ============= - Browse doc/ and examples/ directories. - - Changelog - ========= - - python-ptrace 0.7 (2013-03-05) - ------------------------------ - - * Experimental support of Python 3.3 in the same code base - * Drop support of Python 2.5 - * Remove the ptrace.compatibility module - * Fix Process.readStruct() and Process.readArray() on x86_64 - * Experimental support of ARM architecture (Linux EAPI), - strace.py has been tested on Raspberry Pi (armv6l) - - python-ptrace 0.6.6 (2013-12-16) - -------------------------------- - - * Fix os_tools.RUNNING_LINUX for Python 2.x compiled on Linux kernel 3.x - * Support FreeBSD on x86_64 - * Add missing prototype of the unlinkat() system call. Patch written by - Matthew Fernandez. - - python-ptrace 0.6.5 (2013-06-06) - -------------------------------- - - * syscall: fix parsing socketcall on Linux x86 - * syscall: fix protoype of socket() - - python-ptrace 0.6.4 (2012-02-26) - -------------------------------- - - * Convert all classes to new-style classes, patch written by teythoon - * Fix compilation on Apple, patch written by Anthony Gelibert - * Support GNU/kFreeBSD, patch written by Jakub Wilk - * Support sockaddr_in6 (IPv6 address) - - python-ptrace 0.6.3 (2011-02-16) - -------------------------------- - - * Support distrom3 - * Support Python 3 - * Rename strace.py option --socketcall to --socket, and fix this option for - FreeBSD and Linux/64 bits - * Add MANIFEST.in: include all files in source distribution (tests, cptrace - module, ...) - - python-ptrace 0.6.2 (2009-11-09) - -------------------------------- - - * Fix 64 bits sub registers (set mask for eax, ebx, ecx, edx) - - python-ptrace 0.6.1 (2009-11-07) - -------------------------------- - - * Create follow, showfollow, resetfollow, xray commands in gdb.py. Patch - written by Dimitris Glynos - * Project website moved to http://bitbucket.org/haypo/python-ptrace/ - * Replace types (u)intXX_t by c_(u)intXX - * Create MemoryMapping.search() method and MemoryMapping now keeps a weak - reference to the process - - python-ptrace 0.6 (2009-02-13) - ------------------------------ - - User visible changes: - - * python-ptrace now depends on Python 2.5 - * Invalid memory access: add fault address in the name - * Update Python 3.0 conversion patch - * Create -i (--show-ip) option to strace.py: show instruction pointer - * Add a new example (itrace.py) written by Mark Seaborn and based - on strace.py - - API changes: - - * PtraceSyscall: store the instruction pointer at syscall enter (if the - option instr_pointer=True, disabled by default) - * Remove PROC_DIRNAME and procFilename() from ptrace.linux_proc - - Bugfixes: - - * Fix locateProgram() for relative path - * Fix interpretation of memory fault on MOSVW instruction (source is ESI and - destination is EDI, and not the inverse!) - - python-ptrace 0.5 (2008-09-13) - ------------------------------ - - Visible changes: - - * Write an example (the most simple debugger) and begin to document the code - * gdb.py: create "dbginfo" command - * Parse socket syscalls on FreeBSD - * On invalid memory access (SIGSEGV), eval the dereference expression to get - the fault address on OS without siginfo (eg. FreeBSD) - * Fixes to get minimal Windows support: fix imports, fix locateProgram() - - Other changes: - - * Break the API: - - Rename PtraceDebugger.traceSysgood() to PtraceDebugger.enableSysgood() - - Rename PtraceDebugger.trace_sysgood to PtraceDebugger.use_sysgood - - Remove PtraceProcess.readCode() - * Create createChild() function which close all files except stdin, - stdout and stderr - * On FreeBSD, on process exit recalls waitpid(pid) to avoid zombi process - - - python-ptrace 0.4.2 (2008-08-28) - -------------------------------- - - * BUGFIX: Fix typo in gdb.py (commands => command_str), it wasn't possible to - write more than one command... - * BUGIFX: Fix typo in SignalInfo class (remove "self."). When a process - received a signal SIGCHLD (because of a fork), the debugger exited because - of this bug. - * BUGFIX: Debugger._wait() return abnormal process exit as a normal event, - the event is not raised as an exception - * PtraceSignal: don't clear preformatted arguments (eg. arguments of execve) - - python-ptrace 0.4.1 (2008-08-23) - -------------------------------- - - * The project has a new dedicated website: http://python-ptrace.hachoir.org/ - * Create cptrace: optional Python binding of ptrace written in C (faster - than ptrace, the Python binding written in Python with ctypes) - * Add name attribute to SignalInfo classes - * Fixes to help Python 3.0 compatibility: don't use sys.exc_clear() - (was useless) in writeBacktrace() - * ProcessState: create utime, stime, starttime attributes - - python-ptrace 0.4.0 (2008-08-19) - -------------------------------- - - Visible changes: - - * Rename the project to "python-ptrace" (old name was "Ptrace) - * strace.py: create --ignore-regex option - * PtraceSignal: support SIGBUS, display the related registers and - the instruction - * Support execve() syscall tracing - - Developer changes: - - * New API is incompatible with 0.3.2 - * PtraceProcess.waitProcessEvent() accepts optional blocking=False argument - * PtraceProcess.getreg()/setreg() are able to read/write i386 and x86-64 - "sub-registers" like al or bx - * Remove iterProc() function, replaced by openProc() with explicit - call to .close() to make sure that files are closed - * Create searchProcessesByName() - * Replace CPU_PPC constant by CPU_POWERPC and create CPU_PPC32 and CPU_PPC64 - * Create MemoryMapping object, used by readMappings() and findStack() methods - of PtraceProcess - * Always define all PtraceProcess methods but raise an error if the function - is not implemented + .. image:: https://img.shields.io/pypi/v/python-ptrace.svg + :alt: Latest release on the Python Cheeseshop (PyPI) + :target: https://pypi.python.org/pypi/python-ptrace + + .. image:: https://travis-ci.org/haypo/python-ptrace.svg?branch=master + :alt: Build status of python-ptrace on Travis CI + :target: https://travis-ci.org/haypo/python-ptrace + + python-ptrace is a debugger using ptrace (Linux, BSD and Darwin system call to + trace processes) written in Python. + + * `python-ptrace documentation + `_ + * `python-ptrace at GitHub + `_ + * `python-ptrace at the Python Cheeseshop (PyPI) + `_ + python-ptrace is an opensource project written in Python under GNU GPLv2 + license. Platform: UNKNOWN Classifier: Intended Audience :: Developers diff -Nru python-ptrace-0.7/ptrace/binding/cpu.py python-ptrace-0.9.3/ptrace/binding/cpu.py --- python-ptrace-0.7/ptrace/binding/cpu.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/cpu.py 2017-02-10 11:38:49.000000000 +0000 @@ -20,18 +20,18 @@ CPU_FRAME_POINTER = "rbp" CPU_SUB_REGISTERS = { # main register name, shift, mask - 'al': ('rax', 0, 0xff), - 'bl': ('rbx', 0, 0xff), - 'cl': ('rcx', 0, 0xff), - 'dl': ('rdx', 0, 0xff), - 'ah': ('rax', 8, 0xff), - 'bh': ('rbx', 8, 0xff), - 'ch': ('rcx', 8, 0xff), - 'dh': ('rdx', 8, 0xff), - 'ax': ('rax', 0, 0xffff), - 'bx': ('rbx', 0, 0xffff), - 'cx': ('rcx', 0, 0xffff), - 'dx': ('rdx', 0, 0xffff), + 'al': ('rax', 0, 0xff), + 'bl': ('rbx', 0, 0xff), + 'cl': ('rcx', 0, 0xff), + 'dl': ('rdx', 0, 0xff), + 'ah': ('rax', 8, 0xff), + 'bh': ('rbx', 8, 0xff), + 'ch': ('rcx', 8, 0xff), + 'dh': ('rdx', 8, 0xff), + 'ax': ('rax', 0, 0xffff), + 'bx': ('rbx', 0, 0xffff), + 'cx': ('rcx', 0, 0xffff), + 'dx': ('rdx', 0, 0xffff), 'eax': ('rax', 32, None), 'ebx': ('rbx', 32, None), 'ecx': ('rcx', 32, None), @@ -69,4 +69,3 @@ 'of': ('eflags', 11, 1), 'iopl': ('eflags', 12, 2), }) - diff -Nru python-ptrace-0.7/ptrace/binding/freebsd_struct.py python-ptrace-0.9.3/ptrace/binding/freebsd_struct.py --- python-ptrace-0.7/ptrace/binding/freebsd_struct.py 2013-08-28 00:11:48.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/freebsd_struct.py 2017-02-10 11:38:51.000000000 +0000 @@ -1,6 +1,6 @@ from ctypes import (Structure, - c_int, c_uint, c_ulong, c_void_p, - c_uint16, c_uint32, c_size_t) + c_int, c_uint, c_ulong, c_void_p, + c_uint16, c_uint32, c_size_t) from ptrace.cpu_info import CPU_X86_64 PIOD_READ_D = 1 @@ -11,34 +11,35 @@ # /usr/include/machine/reg.h if CPU_X86_64: register_t = c_ulong + class reg(Structure): _fields_ = ( - ("r15", register_t), - ("r14", register_t), - ("r13", register_t), - ("r12", register_t), - ("r11", register_t), - ("r10", register_t), - ("r9", register_t), - ("r8", register_t), - ("rdi", register_t), - ("rsi", register_t), - ("rbp", register_t), - ("rbx", register_t), - ("rdx", register_t), - ("rcx", register_t), - ("rax", register_t), - ("trapno", c_uint32), - ("fs", c_uint16), - ("gs", c_uint16), - ("err", c_uint32), - ("es", c_uint16), - ("ds", c_uint16), - ("rip", register_t), - ("cs", register_t), - ("rflags", register_t), - ("rsp", register_t), - ("ss", register_t), + ("r15", register_t), + ("r14", register_t), + ("r13", register_t), + ("r12", register_t), + ("r11", register_t), + ("r10", register_t), + ("r9", register_t), + ("r8", register_t), + ("rdi", register_t), + ("rsi", register_t), + ("rbp", register_t), + ("rbx", register_t), + ("rdx", register_t), + ("rcx", register_t), + ("rax", register_t), + ("trapno", c_uint32), + ("fs", c_uint16), + ("gs", c_uint16), + ("err", c_uint32), + ("es", c_uint16), + ("ds", c_uint16), + ("rip", register_t), + ("cs", register_t), + ("rflags", register_t), + ("rsp", register_t), + ("ss", register_t), ) else: class reg(Structure): @@ -64,6 +65,7 @@ ("gs", c_uint), ) + class ptrace_io_desc(Structure): _fields_ = ( ("piod_op", c_int), @@ -71,4 +73,3 @@ ("piod_addr", c_void_p), ("piod_len", c_size_t), ) - diff -Nru python-ptrace-0.7/ptrace/binding/func.py python-ptrace-0.9.3/ptrace/binding/func.py --- python-ptrace-0.7/ptrace/binding/func.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/func.py 2017-02-10 11:41:08.000000000 +0000 @@ -1,7 +1,6 @@ from os import strerror -from ctypes import addressof, c_int +from ctypes import addressof, c_int, get_errno, set_errno from ptrace import PtraceError -from ptrace.ctypes_errno import get_errno from ptrace.ctypes_tools import formatAddress from ptrace.os_tools import RUNNING_LINUX, RUNNING_BSD, RUNNING_OPENBSD from ptrace.cpu_info import CPU_64BITS, CPU_WORD_SIZE, CPU_POWERPC @@ -23,7 +22,7 @@ from ptrace.binding.linux_struct import user_fpxregs_struct else: raise NotImplementedError("Unknown OS!") -REGISTER_NAMES = tuple( name for name, type in ptrace_registers_t._fields_ ) +REGISTER_NAMES = tuple(name for name, type in ptrace_registers_t._fields_) HAS_PTRACE_SINGLESTEP = True HAS_PTRACE_EVENTS = False @@ -31,6 +30,10 @@ HAS_PTRACE_SIGINFO = False HAS_PTRACE_GETREGS = False +# Special flags that are required to wait for cloned processes (threads) +# See wait(2) +THREAD_TRACE_FLAGS = 0x00000000 + pid_t = c_int # PTRACE_xxx constants from /usr/include/sys/ptrace.h @@ -59,10 +62,10 @@ HAS_PTRACE_IO = True PTRACE_IO = 11 HAS_PTRACE_SINGLESTEP = True - PTRACE_SINGLESTEP = 32 # PT_STEP - #HAS_PTRACE_EVENTS = True - #PTRACE_SETOPTIONS = 12 # PT_SET_EVENT_MASK - #PTRACE_GETEVENTMSG = 14 # PT_GET_PROCESS_STATE + PTRACE_SINGLESTEP = 32 # PT_STEP + # HAS_PTRACE_EVENTS = True + # PTRACE_SETOPTIONS = 12 # PT_SET_EVENT_MASK + # PTRACE_GETEVENTMSG = 14 # PT_GET_PROCESS_STATE elif RUNNING_BSD: # FreeBSD 7.0RC1 i386 PTRACE_ATTACH = 10 @@ -96,21 +99,24 @@ PTRACE_SETOPTIONS = 0x4200 PTRACE_GETEVENTMSG = 0x4201 -PTRACE_O_TRACESYSGOOD = 0x00000001 -PTRACE_O_TRACEFORK = 0x00000002 -PTRACE_O_TRACEVFORK = 0x00000004 -PTRACE_O_TRACECLONE = 0x00000008 -PTRACE_O_TRACEEXEC = 0x00000010 + # Linux introduces the __WALL flag for wait + THREAD_TRACE_FLAGS = 0x40000000 + +PTRACE_O_TRACESYSGOOD = 0x00000001 +PTRACE_O_TRACEFORK = 0x00000002 +PTRACE_O_TRACEVFORK = 0x00000004 +PTRACE_O_TRACECLONE = 0x00000008 +PTRACE_O_TRACEEXEC = 0x00000010 PTRACE_O_TRACEVFORKDONE = 0x00000020 -PTRACE_O_TRACEEXIT = 0x00000040 +PTRACE_O_TRACEEXIT = 0x00000040 # Wait extended result codes for the above trace options -PTRACE_EVENT_FORK = 1 -PTRACE_EVENT_VFORK = 2 -PTRACE_EVENT_CLONE = 3 -PTRACE_EVENT_EXEC = 4 +PTRACE_EVENT_FORK = 1 +PTRACE_EVENT_VFORK = 2 +PTRACE_EVENT_CLONE = 3 +PTRACE_EVENT_EXEC = 4 PTRACE_EVENT_VFORK_DONE = 5 -PTRACE_EVENT_EXIT = 6 +PTRACE_EVENT_EXIT = 6 try: from cptrace import ptrace as _ptrace @@ -125,10 +131,12 @@ _ptrace.argtypes = (c_ulong, c_ulong, c_ulong, c_ulong) _ptrace.restype = c_ulong + def ptrace(command, pid=0, arg1=0, arg2=0, check_errno=False): if HAS_CPTRACE: try: - result = _ptrace(command, pid, arg1, arg2) + set_errno(0) + result = _ptrace(command, pid, arg1, arg2, check_errno) except ValueError as errobj: message = str(errobj) errno = get_errno() @@ -148,14 +156,18 @@ raise PtraceError(message, errno=errno, pid=pid) return result + def ptrace_traceme(): ptrace(PTRACE_TRACEME) + def ptrace_attach(pid): ptrace(PTRACE_ATTACH, pid) + def ptrace_detach(pid, signal=0): - ptrace(PTRACE_DETACH, pid, 0, signal); + ptrace(PTRACE_DETACH, pid, 0, signal) + def _peek(command, pid, address): if address % CPU_WORD_SIZE: @@ -164,6 +176,7 @@ % formatAddress(address), pid=pid) return ptrace(command, pid, address, check_errno=True) + def _poke(command, pid, address, word): if address % CPU_WORD_SIZE: raise PtraceError( @@ -171,27 +184,35 @@ % formatAddress(address), pid=pid) ptrace(command, pid, address, word) + def ptrace_peektext(pid, address): return _peek(PTRACE_PEEKTEXT, pid, address) + def ptrace_peekdata(pid, address): return _peek(PTRACE_PEEKDATA, pid, address) + def ptrace_peekuser(pid, address): return _peek(PTRACE_PEEKUSER, pid, address) + def ptrace_poketext(pid, address, word): _poke(PTRACE_POKETEXT, pid, address, word) + def ptrace_pokedata(pid, address, word): _poke(PTRACE_POKEDATA, pid, address, word) + def ptrace_pokeuser(pid, address, word): _poke(PTRACE_POKEUSER, pid, address, word) + def ptrace_kill(pid): ptrace(PTRACE_KILL, pid) + if HAS_PTRACE_EVENTS: def WPTRACEEVENT(status): return status >> 16 @@ -272,4 +293,3 @@ if HAS_PTRACE_IO: def ptrace_io(pid, io_desc): ptrace(PTRACE_IO, pid, addressof(io_desc)) - diff -Nru python-ptrace-0.7/ptrace/binding/__init__.py python-ptrace-0.9.3/ptrace/binding/__init__.py --- python-ptrace-0.7/ptrace/binding/__init__.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/__init__.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,4 +1,4 @@ -from ptrace.binding.func import ( +from ptrace.binding.func import ( # noqa HAS_PTRACE_SINGLESTEP, HAS_PTRACE_EVENTS, HAS_PTRACE_IO, HAS_PTRACE_SIGINFO, HAS_PTRACE_GETREGS, REGISTER_NAMES, @@ -10,20 +10,19 @@ ptrace_peekuser, ptrace_registers_t) if HAS_PTRACE_EVENTS: - from ptrace.binding.func import (WPTRACEEVENT, - PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE, - PTRACE_EVENT_EXEC, - ptrace_setoptions, ptrace_geteventmsg) + from ptrace.binding.func import (WPTRACEEVENT, # noqa + PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE, + PTRACE_EVENT_EXEC, + ptrace_setoptions, ptrace_geteventmsg) if HAS_PTRACE_SINGLESTEP: - from ptrace.binding.func import ptrace_singlestep + from ptrace.binding.func import ptrace_singlestep # noqa if HAS_PTRACE_SIGINFO: - from ptrace.binding.func import ptrace_getsiginfo + from ptrace.binding.func import ptrace_getsiginfo # noqa if HAS_PTRACE_IO: - from ptrace.binding.func import ptrace_io - from ptrace.binding.freebsd_struct import ( + from ptrace.binding.func import ptrace_io # noqa + from ptrace.binding.freebsd_struct import ( # noqa ptrace_io_desc, PIOD_READ_D, PIOD_WRITE_D, - PIOD_READ_I,PIOD_WRITE_I) + PIOD_READ_I, PIOD_WRITE_I) if HAS_PTRACE_GETREGS: - from ptrace.binding.func import ptrace_getregs - + from ptrace.binding.func import ptrace_getregs # noqa diff -Nru python-ptrace-0.7/ptrace/binding/linux_struct.py python-ptrace-0.9.3/ptrace/binding/linux_struct.py --- python-ptrace-0.7/ptrace/binding/linux_struct.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/linux_struct.py 2017-02-10 11:41:08.000000000 +0000 @@ -1,6 +1,6 @@ from ctypes import (Structure, Union, sizeof, - c_char, c_ushort, c_int, c_uint, c_ulong, c_void_p, - c_uint16, c_uint32, c_uint64) + c_char, c_ushort, c_int, c_uint, c_ulong, c_void_p, + c_uint16, c_uint32, c_uint64) from ptrace.cpu_info import CPU_64BITS, CPU_PPC32, CPU_ARM pid_t = c_int @@ -8,6 +8,8 @@ clock_t = c_uint # From /usr/include/asm-i386/user.h + + class user_regs_struct(Structure): if CPU_PPC32: _fields_ = ( @@ -50,7 +52,7 @@ ("link", c_ulong), ("xer", c_ulong), ("ccr", c_ulong), - ("mq", c_ulong), # FIXME: ppc64 => softe + ("mq", c_ulong), # FIXME: ppc64 => softe ("trap", c_ulong), ("dar", c_ulong), ("dsisr", c_ulong), @@ -87,7 +89,7 @@ ("es", c_ulong), ("fs", c_ulong), ("gs", c_ulong) - ) + ) else: _fields_ = ( ("ebx", c_ulong), @@ -113,7 +115,8 @@ ("esp", c_ulong), ("ss", c_ushort), ("__ss", c_ushort), - ) + ) + class user_fpregs_struct(Structure): if CPU_64BITS: @@ -129,7 +132,7 @@ ("st_space", c_uint32 * 32), ("xmm_space", c_uint32 * 64), ("padding", c_uint32 * 24) - ) + ) else: _fields_ = ( ("cwd", c_ulong), @@ -140,7 +143,8 @@ ("foo", c_ulong), ("fos", c_ulong), ("st_space", c_ulong * 20) - ) + ) + if not CPU_64BITS: class user_fpxregs_struct(Structure): @@ -161,11 +165,14 @@ ) # From /usr/include/asm-generic/siginfo.h + + class _sifields_sigfault_t(Union): _fields_ = ( ("_addr", c_void_p), ) + class _sifields_sigchld_t(Structure): _fields_ = ( ("pid", pid_t), @@ -175,23 +182,24 @@ ("stime", clock_t), ) + class _sifields_t(Union): _fields_ = ( - ("pad", c_char * (128 - 3 * sizeof(c_int))), - ("_sigchld", _sifields_sigchld_t), - ("_sigfault", _sifields_sigfault_t), -# ("_kill", _sifields_kill_t), -# ("_timer", _sifields_timer_t), -# ("_rt", _sifields_rt_t), -# ("_sigpoll", _sifields_sigpoll_t), + ("pad", c_char * (128 - 3 * sizeof(c_int))), + ("_sigchld", _sifields_sigchld_t), + ("_sigfault", _sifields_sigfault_t), + # ("_kill", _sifields_kill_t), + # ("_timer", _sifields_timer_t), + # ("_rt", _sifields_rt_t), + # ("_sigpoll", _sifields_sigpoll_t), ) + class siginfo(Structure): _fields_ = ( ("si_signo", c_int), ("si_errno", c_int), ("si_code", c_int), ("_sifields", _sifields_t) - ) + ) _anonymous_ = ("_sifields",) - diff -Nru python-ptrace-0.7/ptrace/binding/openbsd_struct.py python-ptrace-0.9.3/ptrace/binding/openbsd_struct.py --- python-ptrace-0.7/ptrace/binding/openbsd_struct.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/binding/openbsd_struct.py 2017-02-10 11:38:49.000000000 +0000 @@ -9,6 +9,8 @@ pid_t = c_int # /usr/include/machine/reg.h + + class reg(Structure): _fields_ = ( ("eax", c_uint), @@ -29,11 +31,13 @@ ("gs", c_uint), ) + class fpreg(Structure): _fields_ = ( ("__data", c_char * 116), ) + class ptrace_io_desc(Structure): _fields_ = ( ("piod_op", c_int), @@ -41,4 +45,3 @@ ("piod_addr", c_void_p), ("piod_len", size_t), ) - diff -Nru python-ptrace-0.7/ptrace/cpu_info.py python-ptrace-0.9.3/ptrace/cpu_info.py --- python-ptrace-0.7/ptrace/cpu_info.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/cpu_info.py 2017-02-10 11:38:51.000000000 +0000 @@ -26,10 +26,10 @@ CPU_64BITS = (sizeof(c_void_p) == 8) if CPU_64BITS: - CPU_WORD_SIZE = 8 # bytes + CPU_WORD_SIZE = 8 # bytes CPU_MAX_UINT = 0xffffffffffffffff else: - CPU_WORD_SIZE = 4 # bytes + CPU_WORD_SIZE = 4 # bytes CPU_MAX_UINT = 0xffffffff if HAS_UNAME: @@ -59,4 +59,3 @@ CPU_INTEL = (CPU_I386 or CPU_X86_64) CPU_POWERPC = (CPU_PPC32 or CPU_PPC64) - diff -Nru python-ptrace-0.7/ptrace/ctypes_errno.py python-ptrace-0.9.3/ptrace/ctypes_errno.py --- python-ptrace-0.7/ptrace/ctypes_errno.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/ctypes_errno.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,71 +0,0 @@ -""" -Function get_errno(): get the current errno value. - -Try different implementations: - - ctypes_support.get_errno() function - - __errno_location_sym symbol from the C library - - PyErr_SetFromErrno() from the C Python API -""" - -get_errno = None -try: - from ctypes_support import get_errno -except ImportError: - pass - -if not get_errno: - from ctypes import POINTER, c_int - - def _errno_location(): - """ - Try to get errno integer from libc using __errno_location_sym function. - - This function is specific to OS with "libc.so.6" and may fails for - thread-safe libc. - """ - from ctypes import cdll - try: - libc = cdll.LoadLibrary("libc.so.6") - except OSError: - # Unable to open libc dynamic library - return None - try: - __errno_location = libc.__errno_location_sym - except AttributeError: - # libc doesn't have __errno_location - return None - __errno_location.restype = POINTER(c_int) - return __errno_location()[0] - - errno = _errno_location() - if errno is not None: - def get_errno(): - # pyflakes warn about "undefined name", - # but that's wrong: errno is defined! - return errno - else: - del errno - -if not get_errno: - from ctypes import pythonapi, py_object - - # Function from pypy project: - # File pypy/dist/pypy/rpython/rctypes/aerrno.py - def _pythonapi_geterrno(): - """ - Read errno using Python C API: raise an exception with PyErr_SetFromErrno - and then read error code 'errno'. - - This function may raise an RuntimeError. - """ - try: - pythonapi.PyErr_SetFromErrno(py_object(OSError)) - except OSError as err: - return err.errno - else: - raise RuntimeError("get_errno() is unable to get error code") - - get_errno = _pythonapi_geterrno - -__all__ = ["get_errno"] - diff -Nru python-ptrace-0.7/ptrace/ctypes_libc.py python-ptrace-0.9.3/ptrace/ctypes_libc.py --- python-ptrace-0.7/ptrace/ctypes_libc.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/ctypes_libc.py 2017-02-10 11:38:51.000000000 +0000 @@ -4,9 +4,8 @@ - libc: the loaded library """ -from ctypes import cdll +from ctypes import CDLL from ctypes.util import find_library LIBC_FILENAME = find_library('c') -libc = cdll.LoadLibrary(LIBC_FILENAME) - +libc = CDLL(LIBC_FILENAME, use_errno=True) diff -Nru python-ptrace-0.7/ptrace/ctypes_stdint.py python-ptrace-0.9.3/ptrace/ctypes_stdint.py --- python-ptrace-0.7/ptrace/ctypes_stdint.py 2013-12-16 22:55:31.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/ctypes_stdint.py 1970-01-01 00:00:00.000000000 +0000 @@ -1,41 +0,0 @@ -""" -Define standard (integers) types. - -Signed types: - - int8_t - - int16_t - - int32_t - - int64_t - - size_t - -Unsigned types: - - uint8_t - - uint16_t - - uint32_t - - uint64_t -""" - -import ctypes - -# 8-bit integers -int8_t = ctypes.c_int8 -uint8_t = ctypes.c_uint8 - -# 16-bit integers -int16_t = ctypes.c_int16 -uint16_t = ctypes.c_uint16 - -# 32-bit integers -int32_t = ctypes.c_int32 -uint32_t = ctypes.c_uint32 - -# 64-bit integers -int64_t = ctypes.c_int64 -uint64_t = ctypes.c_uint64 - -# size_t -size_t = ctypes.c_size_t - -__all__ = ( - "uint8_t", "int8_t", "int16_t", "uint16_t", - "int32_t", "uint32_t", "int64_t", "uint64_t", "size_t") diff -Nru python-ptrace-0.7/ptrace/ctypes_tools.py python-ptrace-0.9.3/ptrace/ctypes_tools.py --- python-ptrace-0.7/ptrace/ctypes_tools.py 2013-12-18 21:45:22.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/ctypes_tools.py 2017-02-10 11:41:08.000000000 +0000 @@ -2,71 +2,114 @@ from ptrace.cpu_info import CPU_64BITS from ctypes import cast, POINTER + def int2uint64(value): """ Convert a signed 64 bits integer into an unsigned 64 bits integer. + + >>> print(int2uint64(1)) + 1 + >>> print(int2uint64(2**64 + 1)) # ignore bits larger than 64 bits + 1 + >>> print(int2uint64(-1)) + 18446744073709551615 + >>> print(int2uint64(-2)) + 18446744073709551614 """ - if value < 0: - return 0x10000000000000000 + value - else: - return value + return (value & 0xffffffffffffffff) + def uint2int64(value): """ Convert an unsigned 64 bits integer into a signed 64 bits integer. + + >>> print(uint2int64(1)) + 1 + >>> print(uint2int64(2**64 + 1)) # ignore bits larger than 64 bits + 1 + >>> print(uint2int64(18446744073709551615)) + -1 + >>> print(uint2int64(18446744073709551614)) + -2 """ + value = value & 0xffffffffffffffff if value & 0x8000000000000000: return value - 0x10000000000000000 else: return value + def truncateWord32(value): """ Truncate an unsigned integer to 32 bits. """ return value & 0xFFFFFFFF + def truncateWord64(value): """ Truncate an unsigned integer to 64 bits. """ return value & 0xFFFFFFFFFFFFFFFF + def formatUintHex16(value): """ Format an 16 bits unsigned integer. """ return u"0x%04x" % value + def formatUintHex32(value): """ Format an 32 bits unsigned integer. """ return u"0x%08x" % value + def formatUintHex64(value): """ Format an 64 bits unsigned integer. """ return u"0x%016x" % value + def int2uint32(value): """ Convert a signed 32 bits integer into an unsigned 32 bits integer. + + >>> print(int2uint32(1)) + 1 + >>> print(int2uint32(2**32 + 1)) # ignore bits larger than 32 bits + 1 + >>> print(int2uint32(-1)) + 4294967295 """ - if value < 0: - return 0x100000000 + value - else: - return value + return value & 0xffffffff + def uint2int32(value): """ Convert an unsigned 32 bits integer into a signed 32 bits integer. + + >>> print(uint2int32(1)) + 1 + >>> print(uint2int32(2**32 + 1)) # ignore bits larger than 32 bits + 1 + >>> print(uint2int32(4294967295)) + -1 + >>> print(uint2int32(4294967294)) + -2 + >>> print(uint2int32(18446744073709551615)) + -1 """ + value = value & 0xffffffff if value & 0x80000000: - return value - 0x100000000 + v = value - 0x100000000 else: - return value + v = value + return v + uint2int = uint2int32 int2uint = int2uint32 @@ -81,6 +124,7 @@ formatWordHex = formatUintHex32 truncateWord = truncateWord32 + def formatAddress(address): """ Format an address to hexadecimal. @@ -91,46 +135,52 @@ else: return u"NULL" + def formatAddressRange(start, end): """ - Format an address range, eg. "0x80004000-0x8000ffff". + Format an address range, e.g. "0x80004000-0x8000ffff". """ return u"%s-%s" % (formatWordHex(start), formatWordHex(end)) + def ntoh_ushort(value): """ - Convert an unsigned short integer from network endiant to host endian. + Convert an unsigned short integer from network endian to host endian. """ return unpack("H", value))[0] + def ntoh_uint(value): """ - Convert an unsigned integer from network endiant to host endian. + Convert an unsigned integer from network endian to host endian. """ return unpack("I", value))[0] + def word2bytes(word): """ Convert an unsigned integer (a CPU word) to a bytes string. """ return pack("L", word) + def bytes2word(bytes): """ Convert a bytes string to an unsigned integer (a CPU word). """ return unpack("L", bytes)[0] + def bytes2type(bytes, type): """ - Cast a bytes string to an objet of the specified type. + Cast a bytes string to an object of the specified type. """ return cast(bytes, POINTER(type))[0] + def bytes2array(bytes, basetype, size): """ - Cast a bytes string to an array of objets of the specified type + Cast a bytes string to an array of objects of the specified type and size. """ return bytes2type(bytes, basetype * size) - diff -Nru python-ptrace-0.7/ptrace/debugger/application.py python-ptrace-0.9.3/ptrace/debugger/application.py --- python-ptrace-0.7/ptrace/debugger/application.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/application.py 2017-02-10 11:38:51.000000000 +0000 @@ -1,8 +1,7 @@ -from __future__ import print_function from optparse import OptionGroup from logging import (getLogger, StreamHandler, - DEBUG, INFO, WARNING, ERROR) -from sys import stderr, exit + DEBUG, INFO, WARNING, ERROR) +from sys import exit from ptrace import PtraceError from logging import error from ptrace.tools import locateProgram @@ -10,7 +9,9 @@ from errno import EPERM from ptrace.debugger.child import createChild + class Application(object): + def __init__(self): pass @@ -35,11 +36,11 @@ def createLogOptions(self, parser): log = OptionGroup(parser, "Logging") log.add_option("--quiet", "-q", help="Be quiet (set log level to ERROR)", - action="store_true", default=False) + action="store_true", default=False) log.add_option("--verbose", "-v", help="Debug mode (set log level to INFO)", - action="store_true", default=False) + action="store_true", default=False) log.add_option("--debug", help="Debug mode (set log level to DEBUG)", - action="store_true", default=False) + action="store_true", default=False) parser.add_option_group(log) def createChild(self, arguments, env=None): @@ -51,7 +52,7 @@ try: self.debugger.traceFork() except DebuggerError: - print("ERROR: --fork option is not supported by your OS, sorry!", file=stderr) + error("--fork option is not supported by your OS, sorry!") exit(1) if self.options.trace_exec: self.debugger.traceExec() @@ -68,19 +69,19 @@ return self.debugger.addProcess(pid, is_attached=is_attached) except (ProcessExit, PtraceError) as err: if isinstance(err, PtraceError) \ - and err.errno == EPERM: - error("ERROR: You are not allowed to trace process %s (permission denied or process already traced)" % pid) + and err.errno == EPERM: + error( + "ERROR: You are not allowed to trace process %s (permission denied or process already traced)" % pid) else: error("ERROR: Process can no be attached! %s" % err) return None def createCommonOptions(self, parser): parser.add_option("--pid", "-p", help="Attach running process specified by its identifier", - type="int", default=None) + type="int", default=None) parser.add_option("--fork", "-f", help="Trace fork and child process", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--trace-exec", help="Trace execve() event", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--no-stdout", help="Use /dev/null as stdout/stderr, or close stdout and stderr if /dev/null doesn't exist", - action="store_true", default=False) - + action="store_true", default=False) diff -Nru python-ptrace-0.7/ptrace/debugger/backtrace.py python-ptrace-0.9.3/ptrace/debugger/backtrace.py --- python-ptrace-0.7/ptrace/debugger/backtrace.py 2014-03-05 13:33:57.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/backtrace.py 2017-02-10 11:38:51.000000000 +0000 @@ -3,6 +3,7 @@ from ptrace import PtraceError from ptrace.six.moves import xrange + class BacktraceFrame(object): """ Backtrace frame. @@ -12,6 +13,7 @@ - name: name of the function - arguments: value of the arguments """ + def __init__(self, ip): self.ip = ip self.name = u"???" @@ -21,10 +23,12 @@ arguments = (formatWordHex(arg) for arg in self.arguments) return u"IP=%s: %s (%s)" % (formatAddress(self.ip), self.name, ", ".join(arguments)) + class Backtrace(object): """ Backtrace: all process frames since the start function. """ + def __init__(self): self.frames = [] self.truncated = False @@ -38,6 +42,7 @@ def __len__(self): return len(self.frames) + def getBacktrace(process, max_args=6, max_depth=20): """ Get the current backtrace of the specified process: @@ -80,7 +85,7 @@ break # Move to next instruction/frame pointer - ip = process.readWord(fp+CPU_WORD_SIZE) + ip = process.readWord(fp + CPU_WORD_SIZE) if ip == CPU_MAX_UINT: # Linux hack to detect end of the stack break @@ -88,6 +93,7 @@ depth += 1 return backtrace + def getBacktraceFrame(process, ip, fp, nargs): """ Get a backtrace frame: @@ -108,4 +114,3 @@ # Ignore argument read error pass return frame - diff -Nru python-ptrace-0.7/ptrace/debugger/breakpoint.py python-ptrace-0.9.3/ptrace/debugger/breakpoint.py --- python-ptrace-0.7/ptrace/debugger/breakpoint.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/breakpoint.py 2017-02-10 11:38:49.000000000 +0000 @@ -6,12 +6,14 @@ from ptrace.ctypes_tools import word2bytes from ptrace.six import b + class Breakpoint(object): """ Software breakpoint. Use desinstall() method to remove the breakpoint from the process. """ + def __init__(self, process, address, size=None): self._installed = False self.process = ref(process) @@ -63,4 +65,3 @@ self.desinstall(False) except PtraceError: pass - diff -Nru python-ptrace-0.7/ptrace/debugger/child.py python-ptrace-0.9.3/ptrace/debugger/child.py --- python-ptrace-0.7/ptrace/debugger/child.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/child.py 2017-02-10 11:38:51.000000000 +0000 @@ -2,13 +2,12 @@ Error pipe and serialization code comes from Python 2.5 subprocess module. """ from os import ( - fork, execv, execve, waitpid, + fork, execvp, execvpe, waitpid, close, dup2, pipe, - read, write, devnull) + read, write, devnull, sysconf) from sys import exc_info from traceback import format_exception from ptrace.os_tools import RUNNING_WINDOWS -from subprocess import MAXFD from ptrace.binding import ptrace_traceme from ptrace import PtraceError from sys import exit @@ -16,12 +15,20 @@ import fcntl import pickle +try: + MAXFD = sysconf("SC_OPEN_MAX") +except: + MAXFD = 256 + + class ChildError(RuntimeError): pass + class ChildPtraceError(ChildError): pass + def _set_cloexec_flag(fd): if RUNNING_WINDOWS: return @@ -33,6 +40,7 @@ old = fcntl.fcntl(fd, fcntl.F_GETFD) fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag) + def _waitpid_no_intr(pid, options): """Like os.waitpid, but retries on EINTR""" while True: @@ -44,6 +52,7 @@ else: raise + def _read_no_intr(fd, buffersize): """Like os.read, but retries on EINTR""" while True: @@ -55,6 +64,7 @@ else: raise + def _write_no_intr(fd, s): """Like os.write, but retries on EINTR""" while True: @@ -66,15 +76,17 @@ else: raise + def _createParent(pid, errpipe_read): # Wait for exec to fail or succeed; possibly raising exception - data = _read_no_intr(errpipe_read, 1048576) # Exceptions limited to 1 MB + data = _read_no_intr(errpipe_read, 1048576) # Exceptions limited to 1 MB close(errpipe_read) if data: _waitpid_no_intr(pid, 0) child_exception = pickle.loads(data) raise child_exception + def _createChild(arguments, no_stdout, env, errpipe_write): # Child code try: @@ -100,6 +112,7 @@ _write_no_intr(errpipe_write, pickle.dumps(exc_value)) exit(255) + def _execChild(arguments, no_stdout, env): if no_stdout: try: @@ -112,16 +125,17 @@ close(1) try: if env is not None: - execve(arguments[0], arguments, env) + execvpe(arguments[0], arguments, env) else: - execv(arguments[0], arguments) + execvp(arguments[0], arguments) except Exception as err: raise ChildError(str(err)) + def createChild(arguments, no_stdout, env=None): """ Create a child process: - - arguments: list of string where (eg. ['ls', '-la']) + - arguments: list of string where (e.g. ['ls', '-la']) - no_stdout: if True, use null device for stdout/stderr - env: environment variables dictionary @@ -141,4 +155,3 @@ else: close(errpipe_read) _createChild(arguments, no_stdout, env, errpipe_write) - diff -Nru python-ptrace-0.7/ptrace/debugger/debugger.py python-ptrace-0.9.3/ptrace/debugger/debugger.py --- python-ptrace-0.7/ptrace/debugger/debugger.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/debugger.py 2017-02-10 11:38:49.000000000 +0000 @@ -5,14 +5,18 @@ from errno import ECHILD from ptrace.debugger import PtraceProcess, ProcessSignal from ptrace.binding import HAS_PTRACE_EVENTS +from time import sleep if HAS_PTRACE_EVENTS: from ptrace.binding.func import ( PTRACE_O_TRACEFORK, PTRACE_O_TRACEVFORK, - PTRACE_O_TRACEEXEC, PTRACE_O_TRACESYSGOOD) + PTRACE_O_TRACEEXEC, PTRACE_O_TRACESYSGOOD, + PTRACE_O_TRACECLONE, THREAD_TRACE_FLAGS) + class DebuggerError(PtraceError): pass + class PtraceDebugger(object): """ Debugger managing one or multiple processes at the same time. @@ -40,7 +44,7 @@ Operations ========== - - iterarate on all processes: "for process in debugger: ..." + - iterate on all processes: "for process in debugger: ..." - get a process by its identifier: "process = debugger[pid]" - get the number of processes: len(debugger) @@ -54,16 +58,18 @@ - trace_exec (bool): exec() tracing is enabled? - use_sysgood (bool): sysgood option is enabled? """ + def __init__(self): self.dict = {} # pid -> PtraceProcess object self.list = [] self.options = 0 self.trace_fork = False self.trace_exec = False + self.trace_clone = False self.use_sysgood = False self.enableSysgood() - def addProcess(self, pid, is_attached, parent=None): + def addProcess(self, pid, is_attached, parent=None, is_thread=False): """ Add a new process using its identifier. Use is_attached=False to attach an existing (running) process, and is_attached=True to trace @@ -71,7 +77,8 @@ """ if pid in self.dict: raise KeyError("The process %s is already registered!" % pid) - process = PtraceProcess(self, pid, is_attached, parent=parent) + process = PtraceProcess(self, pid, is_attached, + parent=parent, is_thread=is_thread) info("Attach %s to debugger" % process) self.dict[pid] = process self.list.append(process) @@ -110,28 +117,33 @@ set) or any process (wanted_pid=None). The call is blocking is blocking option is True. Return the tuple (pid, status). - See os.waitpid() documentation for explainations about the result. + See os.waitpid() documentation for explanations about the result. """ flags = 0 if not blocking: flags |= WNOHANG if wanted_pid: if wanted_pid not in self.dict: - raise DebuggerError("Unknown PID: %r" % wanted_pid, pid=wanted_pid) + raise DebuggerError("Unknown PID: %r" % + wanted_pid, pid=wanted_pid) + + process = self.dict[wanted_pid] + if process.is_thread: + flags |= THREAD_TRACE_FLAGS pid, status = waitpid(wanted_pid, flags) else: pid, status = waitpid(-1, flags) if (blocking or pid) and wanted_pid and (pid != wanted_pid): raise DebuggerError("Unwanted PID: %r (instead of %s)" - % (pid, wanted_pid), pid=pid) + % (pid, wanted_pid), pid=pid) return pid, status - def _wait(self, wanted_pid, blocking=True): + def _wait_event_pid(self, wanted_pid, blocking=True): """ Wait for a process event from the specified process identifier. If blocking=False, return None if there is no new event, otherwise return - an objet based on ProcessEvent. + an object based on ProcessEvent. """ process = None while not process: @@ -151,13 +163,32 @@ warning("waitpid() warning: Unknown PID %r" % pid) return process.processStatus(status) + def _wait_event(self, wanted_pid, blocking=True): + if wanted_pid is not None: + return self._wait_event_pid(wanted_pid, blocking) + + pause = 0.001 + while True: + pids = tuple(self.dict) + if len(pids) > 1: + for pid in pids: + process = self._wait_event_pid(pid, False) + if process is not None: + return process + if not blocking: + return None + pause = min(pause * 2, 0.5) + sleep(pause) + else: + return self._wait_event_pid(pids[0], blocking) + def waitProcessEvent(self, pid=None, blocking=True): """ Wait for a process event from a specific process (if pid option is set) or any process (default). If blocking=False, return None if there - is no new event, otherwise return an objet based on ProcessEvent. + is no new event, otherwise return an object based on ProcessEvent. """ - return self._wait(pid, blocking) + return self._wait_event(pid, blocking) def waitSignals(self, *signals, **kw): """ @@ -167,7 +198,7 @@ """ pid = kw.get('pid', None) while True: - event = self._wait(pid) + event = self._wait_event(pid) if event.__class__ != ProcessSignal: raise event signum = event.signum @@ -212,7 +243,8 @@ Enable fork() tracing. Do nothing if it's not supported. """ if not HAS_PTRACE_EVENTS: - raise DebuggerError("Tracing fork events is not supported on this architecture or operating system") + raise DebuggerError( + "Tracing fork events is not supported on this architecture or operating system") self.options |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK self.trace_fork = True info("Debugger trace forks (options=%s)" % self.options) @@ -227,6 +259,16 @@ self.trace_exec = True self.options |= PTRACE_O_TRACEEXEC + def traceClone(self): + """ + Enable clone() tracing. Do nothing if it's not supported. + """ + if not HAS_PTRACE_EVENTS: + # no effect on OS without ptrace events + return + self.trace_clone = True + self.options |= PTRACE_O_TRACECLONE + def enableSysgood(self): """ Enable sysgood option: ask the kernel to set bit #7 of the signal @@ -247,4 +289,3 @@ def __len__(self): return len(self.list) - diff -Nru python-ptrace-0.7/ptrace/debugger/__init__.py python-ptrace-0.9.3/ptrace/debugger/__init__.py --- python-ptrace-0.7/ptrace/debugger/__init__.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/__init__.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,10 +1,9 @@ -from ptrace.debugger.breakpoint import Breakpoint -from ptrace.debugger.process_event import (ProcessEvent, - ProcessExit, NewProcessEvent, ProcessExecution) -from ptrace.debugger.ptrace_signal import ProcessSignal -from ptrace.debugger.process_error import ProcessError -from ptrace.debugger.child import ChildError -from ptrace.debugger.process import PtraceProcess -from ptrace.debugger.debugger import PtraceDebugger, DebuggerError -from ptrace.debugger.application import Application - +from ptrace.debugger.breakpoint import Breakpoint # noqa +from ptrace.debugger.process_event import (ProcessEvent, ProcessExit, # noqa + NewProcessEvent, ProcessExecution) +from ptrace.debugger.ptrace_signal import ProcessSignal # noqa +from ptrace.debugger.process_error import ProcessError # noqa +from ptrace.debugger.child import ChildError # noqa +from ptrace.debugger.process import PtraceProcess # noqa +from ptrace.debugger.debugger import PtraceDebugger, DebuggerError # noqa +from ptrace.debugger.application import Application # noqa diff -Nru python-ptrace-0.7/ptrace/debugger/memory_mapping.py python-ptrace-0.9.3/ptrace/debugger/memory_mapping.py --- python-ptrace-0.7/ptrace/debugger/memory_mapping.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/memory_mapping.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,11 +1,12 @@ from ptrace.os_tools import HAS_PROC -if HAS_PROC: - from ptrace.linux_proc import openProc, ProcError from ptrace.debugger.process_error import ProcessError from ptrace.ctypes_tools import formatAddress import re from weakref import ref +if HAS_PROC: + from ptrace.linux_proc import openProc, ProcError + PROC_MAP_REGEX = re.compile( # Address range: '08048000-080b0000 ' r'([0-9a-f]+)-([0-9a-f]+) ' @@ -20,6 +21,7 @@ # Filename: ' /usr/bin/synergyc' r'(?: +(.*))?') + class MemoryMapping(object): """ Process memory mapping (metadata about the mapping). @@ -41,6 +43,7 @@ - "repr(mapping)" create a string representation of the mapping, useful in list contexts """ + def __init__(self, process, start, end, permissions, offset, major_device, minor_device, inode, pathname): self._process = ref(process) self.start = start @@ -67,7 +70,7 @@ process = self._process() bytestr_len = len(bytestr) - buf_len = 64 * 1024 + buf_len = 64 * 1024 if buf_len < bytestr_len: buf_len = bytestr_len @@ -96,6 +99,7 @@ covered += skip remaining -= skip + def readProcessMappings(process): """ Read all memory mappings of the specified process. @@ -117,7 +121,8 @@ line = line.rstrip() match = PROC_MAP_REGEX.match(line) if not match: - raise ProcessError(process, "Unable to parse memoy mapping: %r" % line) + raise ProcessError( + process, "Unable to parse memory mapping: %r" % line) map = MemoryMapping( process, int(match.group(1), 16), @@ -132,4 +137,3 @@ finally: mapsfile.close() return maps - diff -Nru python-ptrace-0.7/ptrace/debugger/parse_expr.py python-ptrace-0.9.3/ptrace/debugger/parse_expr.py --- python-ptrace-0.7/ptrace/debugger/parse_expr.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/parse_expr.py 2017-02-10 11:38:50.000000000 +0000 @@ -3,7 +3,7 @@ # Match a register name: $eax, $gp0, $orig_eax REGISTER_REGEX = re.compile(r"([a-z]+[a-z0-9_]+)") -# Hexadacimel number (eg. 0xa) +# Hexadecimal number (e.g. 0xa) HEXADECIMAL_REGEX = re.compile(r"0x[0-9a-f]+") # Make sure that the expression does not contain invalid characters @@ -12,6 +12,7 @@ # 340&91 EXPR_REGEX = re.compile(r"^[()<>+*/&0-9-]+$") + def replaceHexadecimal(regs): """ Convert an hexadecimal number to decimal number (as string). @@ -25,6 +26,7 @@ value = int(text, 16) return str(value) + def parseExpression(process, text): """ Parse an expression. Syntax: @@ -72,4 +74,3 @@ except SyntaxError: raise ValueError("Invalid expression: %r" % orig_text) return value - diff -Nru python-ptrace-0.7/ptrace/debugger/process_error.py python-ptrace-0.9.3/ptrace/debugger/process_error.py --- python-ptrace-0.7/ptrace/debugger/process_error.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/process_error.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,7 +1,8 @@ from ptrace.error import PtraceError + class ProcessError(PtraceError): + def __init__(self, process, message): PtraceError.__init__(self, message, pid=process.pid) self.process = process - diff -Nru python-ptrace-0.7/ptrace/debugger/process_event.py python-ptrace-0.9.3/ptrace/debugger/process_event.py --- python-ptrace-0.7/ptrace/debugger/process_event.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/process_event.py 2017-02-10 11:38:51.000000000 +0000 @@ -1,5 +1,6 @@ from ptrace.signames import signalName + class ProcessEvent(Exception): """ A process event: program exit, program killed by a signal, program @@ -7,10 +8,12 @@ The attribute "process" contains the related process. """ + def __init__(self, process, message): Exception.__init__(self, message) self.process = process + class ProcessExit(ProcessEvent): """ Process exit event: @@ -18,6 +21,7 @@ - process exited with a code (if exitcode attribute is not None) - process terminated abnormally (otherwise) """ + def __init__(self, process, signum=None, exitcode=None): pid = process.pid if signum: @@ -34,13 +38,17 @@ self.signum = signum self.exitcode = exitcode + class ProcessExecution(ProcessEvent): """ Process execution: event send just after the process calls the exec() syscall if exec() tracing option is enabled. """ + def __init__(self, process): - ProcessEvent.__init__(self, process, "Process %s execution" % process.pid) + ProcessEvent.__init__( + self, process, "Process %s execution" % process.pid) + class NewProcessEvent(ProcessEvent): """ @@ -48,6 +56,6 @@ tracing option is enabled. The attribute process contains the new child process. """ + def __init__(self, process): ProcessEvent.__init__(self, process, "New process %s" % process.pid) - diff -Nru python-ptrace-0.7/ptrace/debugger/process.py python-ptrace-0.9.3/ptrace/debugger/process.py --- python-ptrace-0.7/ptrace/debugger/process.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/process.py 2017-02-21 10:57:46.000000000 +0000 @@ -6,6 +6,30 @@ ptrace_setregs, ptrace_peektext, ptrace_poketext, REGISTER_NAMES) +from ptrace.os_tools import HAS_PROC, RUNNING_BSD, RUNNING_PYTHON3 +from ptrace.tools import dumpRegs +from ptrace.cpu_info import CPU_WORD_SIZE +from ptrace.ctypes_tools import bytes2word, word2bytes, bytes2type, bytes2array +from signal import SIGTRAP, SIGSTOP, SIGKILL +from ptrace.ctypes_tools import formatAddress, formatWordHex +from ctypes import sizeof, c_char_p +from logging import info, warning, error +from ptrace.error import PtraceError +from errno import ESRCH, EACCES +from ptrace.debugger import (Breakpoint, + ProcessExit, ProcessSignal, NewProcessEvent, ProcessExecution) +from os import (kill, + WIFSTOPPED, WSTOPSIG, + WIFSIGNALED, WTERMSIG, + WIFEXITED, WEXITSTATUS) +from ptrace.disasm import HAS_DISASSEMBLER +from ptrace.debugger.backtrace import getBacktrace +from ptrace.debugger.process_error import ProcessError +from ptrace.debugger.memory_mapping import readProcessMappings +from ptrace.binding.cpu import CPU_INSTR_POINTER, CPU_STACK_POINTER, CPU_FRAME_POINTER, CPU_SUB_REGISTERS +from ptrace.debugger.syscall_state import SyscallState +from ptrace.six import b + if HAS_PTRACE_SINGLESTEP: from ptrace.binding import ptrace_singlestep if HAS_PTRACE_SIGINFO: @@ -20,36 +44,14 @@ ptrace_setoptions, ptrace_geteventmsg, WPTRACEEVENT, PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE, PTRACE_EVENT_EXEC) - NEW_PROCESS_EVENT = (PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE) + NEW_PROCESS_EVENT = ( + PTRACE_EVENT_FORK, PTRACE_EVENT_VFORK, PTRACE_EVENT_CLONE) if HAS_PTRACE_GETREGS: from ptrace.binding import ptrace_getregs else: from ptrace.binding import ptrace_peekuser, ptrace_registers_t -from ptrace.os_tools import HAS_PROC, RUNNING_BSD, RUNNING_PYTHON3 -from ptrace.tools import dumpRegs -from ptrace.cpu_info import CPU_WORD_SIZE -from ptrace.ctypes_tools import bytes2word, word2bytes, bytes2type, bytes2array -from signal import SIGTRAP, SIGSTOP, SIGKILL -from ptrace.ctypes_tools import formatAddress, formatWordHex -from ctypes import sizeof, c_char_p -from logging import info, warning, error -from ptrace.error import PtraceError -from errno import ESRCH, EACCES -from ptrace.debugger import (Breakpoint, - ProcessExit, ProcessSignal, NewProcessEvent, ProcessExecution) -from os import (kill, - WIFSTOPPED, WSTOPSIG, - WIFSIGNALED, WTERMSIG, - WIFEXITED, WEXITSTATUS) -from ptrace.disasm import HAS_DISASSEMBLER if HAS_DISASSEMBLER: from ptrace.disasm import disassemble, disassembleOne, MAX_INSTR_SIZE -from ptrace.debugger.backtrace import getBacktrace -from ptrace.debugger.process_error import ProcessError -from ptrace.debugger.memory_mapping import readProcessMappings -from ptrace.binding.cpu import CPU_INSTR_POINTER, CPU_STACK_POINTER, CPU_FRAME_POINTER, CPU_SUB_REGISTERS -from ptrace.debugger.syscall_state import SyscallState -from ptrace.six import b if HAS_PROC: from ptrace.linux_proc import readProcessStat @@ -58,6 +60,7 @@ DEFAULT_NB_INSTR = 10 DEFAULT_CODE_SIZE = 24 + class PtraceProcess(object): """ Process traced by a PtraceDebugger. @@ -85,7 +88,7 @@ - getInstrPointer(): get the instruction pointer - getStackPointer(): get the stack pointer - getFramePointer(): get the stack pointer - - getregs(): get all registers, eg. regs=getregs(); print regs.eax + - getregs(): get all registers, e.g. regs=getregs(); print regs.eax - disassemble(): assembler code of the next instructions - disassembleOne(): assembler code of the next instruction - findStack(): get stack memory mapping @@ -153,7 +156,8 @@ Sometimes, is_stopped value is wrong. You might use isTraced() to make sure that the process is stopped. """ - def __init__(self, debugger, pid, is_attached, parent=None): + + def __init__(self, debugger, pid, is_attached, parent=None, is_thread=False): self.debugger = debugger self.breakpoints = {} self.pid = pid @@ -163,6 +167,7 @@ self.was_attached = is_attached self.is_attached = False self.is_stopped = True + self.is_thread = is_thread if not is_attached: self.attach() else: @@ -215,9 +220,9 @@ size = MIN_CODE_SIZE code = self.readBytes(start, size) if RUNNING_PYTHON3: - text = " ".join( "%02x" % byte for byte in code ) + text = " ".join("%02x" % byte for byte in code) else: - text = " ".join( "%02x" % ord(byte) for byte in code ) + text = " ".join("%02x" % ord(byte) for byte in code) log("CODE: %s" % text) return @@ -231,18 +236,20 @@ bp = True else: instr = self.disassembleOne(address) - text = "%s| %s (%s)" % (formatAddress(instr.address), instr.text, instr.hexa) + text = "%s| %s (%s)" % (formatAddress( + instr.address), instr.text, instr.hexa) if instr.address == ip: text += " <==" if bp: text += " * BREAKPOINT *" log(text) - address = address+instr.size + address = address + instr.size if stop is not None and stop <= address: break else: for instr in self.disassemble(start, stop): - text = "%s| %s (%s)" % (formatAddress(instr.address), instr.text, instr.hexa) + text = "%s| %s (%s)" % (formatAddress( + instr.address), instr.text, instr.hexa) if instr.address == ip: text += " <==" log(text) @@ -263,7 +270,7 @@ code = self.readBytes(start, size) for index, instr in enumerate(disassemble(code, start)): yield instr - if nb_instr and nb_instr <= (index+1): + if nb_instr and nb_instr <= (index + 1): break def disassembleOne(self, address=None): @@ -271,7 +278,7 @@ self.notImplementedError() if address is None: address = self.getInstrPointer() - code = self.readBytes(address, MAX_INSTR_SIZE ) + code = self.readBytes(address, MAX_INSTR_SIZE) return disassembleOne(code, address) def findStack(self): @@ -399,7 +406,9 @@ self.notImplementedError() if event in NEW_PROCESS_EVENT: new_pid = ptrace_geteventmsg(self.pid) - new_process = self.debugger.addProcess(new_pid, is_attached=True, parent=self) + is_thread = (event == PTRACE_EVENT_CLONE) + new_process = self.debugger.addProcess( + new_pid, is_attached=True, parent=self, is_thread=is_thread) return NewProcessEvent(new_process) elif event == PTRACE_EVENT_EXEC: return ProcessExecution(self) @@ -473,13 +482,15 @@ if CPU_INSTR_POINTER: self.setreg(CPU_INSTR_POINTER, ip) else: - raise ProcessError(self, "Instruction pointer register is not defined") + raise ProcessError( + self, "Instruction pointer register is not defined") def getInstrPointer(self): if CPU_INSTR_POINTER: return self.getreg(CPU_INSTR_POINTER) else: - raise ProcessError(self, "Instruction pointer register is not defined") + raise ProcessError( + self, "Instruction pointer register is not defined") def getStackPointer(self): if CPU_STACK_POINTER: @@ -503,7 +514,7 @@ # Read some bytes from the word subsize = min(CPU_WORD_SIZE - offset, size) - data = bytes[offset:offset+subsize] # <-- FIXME: Big endian! + data = bytes[offset:offset + subsize] # <-- FIXME: Big endian! # Move cursor size -= subsize @@ -560,10 +571,21 @@ try: mem = self.read_mem_file mem.seek(address) - return mem.read(size) + data = mem.read(size) except (IOError, ValueError) as err: raise ProcessError(self, "readBytes(%s, %s) error: %s" % ( formatAddress(address), size, err)) + if len(data) == 0 and size: + # Issue #10: If the process was not created by the debugger + # (ex: fork), the kernel may deny reading private mappings of + # /proc/pid/mem to the debugger, depending on the kernel + # version and kernel config (ex: SELinux enabled or not). + # + # Fallback to PTRACE_PEEKTEXT. It is slower but a debugger + # tracing the process is always allowed to use it. + self.readBytes = self._readBytes + return self.readBytes(address, size) + return data else: readBytes = _readBytes @@ -591,9 +613,11 @@ word = self.readBytes(address, CPU_WORD_SIZE) if len(bytes) < size: size = len(bytes) - word = word[:offset] + bytes[:size] + word[offset + size:] # <-- FIXME: Big endian! + word = word[:offset] + bytes[:size] + \ + word[offset + size:] # <-- FIXME: Big endian! else: - word = word[:offset] + bytes[:size] # <-- FIXME: Big endian! + # <-- FIXME: Big endian! + word = word[:offset] + bytes[:size] self.writeWord(address, bytes2word(word)) bytes = bytes[size:] address += CPU_WORD_SIZE @@ -624,7 +648,7 @@ return bytes2type(bytes, struct) def readArray(self, address, basetype, count): - bytes = self.readBytes(address, sizeof(basetype)*count) + bytes = self.readBytes(address, sizeof(basetype) * count) bytes = c_char_p(bytes) return bytes2array(bytes, basetype, count) @@ -639,8 +663,8 @@ if pos != -1: done = True data = data[:pos] - if max_size <= size+chunk_length: - data = data[:(max_size-size)] + if max_size <= size + chunk_length: + data = data[:(max_size - size)] string.append(data) truncated = True break @@ -662,7 +686,7 @@ def _dumpStack(self, log): sp = self.getStackPointer() displayed = 0 - for index in range(-5, 5+1): + for index in range(-5, 5 + 1): delta = index * CPU_WORD_SIZE try: value = self.readWord(sp + delta) @@ -754,4 +778,3 @@ def notImplementedError(self): raise NotImplementedError() - diff -Nru python-ptrace-0.7/ptrace/debugger/ptrace_signal.py python-ptrace-0.9.3/ptrace/debugger/ptrace_signal.py --- python-ptrace-0.7/ptrace/debugger/ptrace_signal.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/ptrace_signal.py 2017-02-10 11:38:51.000000000 +0000 @@ -16,12 +16,12 @@ from ptrace import signalName from ptrace.debugger.signal_reason import ( DivisionByZero, Abort, StackOverflow, - InvalidMemoryAcces, InvalidRead, InvalidWrite, + InvalidMemoryAccess, InvalidRead, InvalidWrite, InstructionError, ChildExit) from ptrace.debugger.parse_expr import parseExpression import re -# Match a pointer dereference (eg. "DWORD [EDX+0x8]") +# Match a pointer dereference (e.g. "DWORD [EDX+0x8]") DEREF_REGEX = r'(?P(BYTE|WORD|DWORD|DQWORD) )?\[(?P[^]]+)\]' NAMED_WORD_SIZE = { @@ -31,9 +31,10 @@ 'DQWORD': 8, } -# Match any Intel instruction (eg. "ADD") +# Match any Intel instruction (e.g. "ADD") INSTR_REGEX = '(?:[A-Z]{3,10})' + def findDerefSize(match): name = match.group("deref_size") try: @@ -41,6 +42,7 @@ except KeyError: return None + def evalFaultAddress(process, match): expr = match.group('deref') if not expr: @@ -48,10 +50,12 @@ try: return parseExpression(process, expr) except ValueError as err: - print("err: %s" % err) + error("err: %s" % err) return None + class ProcessSignal(ProcessEvent): + def __init__(self, signum, process): # Initialize attributes self.name = signalName(signum) @@ -81,35 +85,36 @@ def memoryFaultInstr(self, instr, fault_address): asm = instr.text - # Invalid write (eg. "MOV [...], value") + # Invalid write (e.g. "MOV [...], value") match = re.search(r"^(?:MOV|TEST)[A-Z]* %s," % DEREF_REGEX, asm) if match: if fault_address is None: fault_address = evalFaultAddress(self.process, match) self.reason = InvalidWrite(fault_address, size=findDerefSize(match), - instr=instr, process=self.process) + instr=instr, process=self.process) return - # Invalid read (eg. "CMP BYTE [EAX+EDX-0x1], 0x0") + # Invalid read (e.g. "CMP BYTE [EAX+EDX-0x1], 0x0") match = re.search(r"^%s %s," % (INSTR_REGEX, DEREF_REGEX), asm) if match: if fault_address is None: fault_address = evalFaultAddress(self.process, match) self.reason = InvalidRead(fault_address, size=findDerefSize(match), - instr=instr, process=self.process) + instr=instr, process=self.process) return - # Invalid read (eg. "MOV reg, [...]") + # Invalid read (e.g. "MOV reg, [...]") match = re.match(r"%s [^,]+, %s" % (INSTR_REGEX, DEREF_REGEX), asm) if match: if fault_address is None: fault_address = evalFaultAddress(self.process, match) self.reason = InvalidRead(fault_address, size=findDerefSize(match), - instr=instr, process=self.process) + instr=instr, process=self.process) return - # MOVS* and SCAS* instructions (eg. "MOVSB" or "REP SCASD") - match = re.search(r"^(?:REP(?:NZ)? )?(?PMOVS|SCAS)(?P[BWD])?", asm) + # MOVS* and SCAS* instructions (e.g. "MOVSB" or "REP SCASD") + match = re.search( + r"^(?:REP(?:NZ)? )?(?PMOVS|SCAS)(?P[BWD])?", asm) if match: self.reason = self.movsInstr(fault_address, instr, match) return @@ -118,7 +123,7 @@ operator = match.group("operator") suffix = match.group("suffix") size = {'B': 1, 'W': 2, 'D': 4}.get(suffix) - error_cls = InvalidMemoryAcces + error_cls = InvalidMemoryAccess try: process = self.process if CPU_64BITS: @@ -147,7 +152,7 @@ except PtraceError: registers = {} return error_cls(fault_address, size=size, instr=instr, - registers=registers, process=self.process) + registers=registers, process=self.process) def getSignalInfo(self): if RUNNING_LINUX: @@ -161,9 +166,9 @@ if siginfo: fault_address = siginfo._sigfault._addr if not fault_address: - fault_address = 0 + fault_address = 0 else: - fault_address = None + fault_address = None # Get current instruction instr = self.getInstruction() @@ -183,7 +188,8 @@ if stack: sp = self.process.getStackPointer() if not (stack.start <= sp <= stack.end): - self.reason = StackOverflow(sp, stack, instr=instr, process=self.process) + self.reason = StackOverflow( + sp, stack, instr=instr, process=self.process) return # Guess error type using the assembler instruction @@ -193,7 +199,8 @@ return # Last chance: use generic invalid memory access error - self.reason = InvalidMemoryAcces(fault_address, instr=instr, process=self.process) + self.reason = InvalidMemoryAccess( + fault_address, instr=instr, process=self.process) def mathError(self): instr = self.getInstruction() @@ -222,4 +229,3 @@ if self.reason: self.reason.display(log) log("-" * 60) - diff -Nru python-ptrace-0.7/ptrace/debugger/signal_reason.py python-ptrace-0.9.3/ptrace/debugger/signal_reason.py --- python-ptrace-0.7/ptrace/debugger/signal_reason.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/signal_reason.py 2017-02-10 11:38:51.000000000 +0000 @@ -16,6 +16,7 @@ else: REGISTER_REGEX = None + def extractRegisters(process, instr): registers = {} if not process or not instr or not REGISTER_REGEX: @@ -30,10 +31,11 @@ try: value = process.getreg(name) registers[name] = value - except PtraceError as err: + except PtraceError: pass return registers + def findMappings(addresses, process, size): mappings = [] if addresses is None or not process: @@ -52,17 +54,19 @@ found = False for map in process_mappings: if (map.start <= address < map.end) \ - or (map.start <= (address + size - 1) < map.end): + or (map.start <= (address + size - 1) < map.end): found = True mappings.append("%s is part of %s" % (address_str, map)) if not found: mappings.append("%s is not mapped in memory" % address_str) return mappings + class SignalInfo(Exception): + def __init__(self, name, text, - address=None, size=None, instr=None, - process=None, registers=None): + address=None, size=None, instr=None, + process=None, registers=None): Exception.__init__(self, text) self.name = name self.text = text @@ -85,26 +89,34 @@ def displayExtra(self, log): pass + class DivisionByZero(SignalInfo): + def __init__(self, instr=None, process=None): SignalInfo.__init__(self, "div_by_zero", - "Division by zero", instr=instr, process=process) + "Division by zero", instr=instr, process=process) + class Abort(SignalInfo): + def __init__(self): SignalInfo.__init__(self, "abort", - "Program received signal SIGABRT, Aborted.") + "Program received signal SIGABRT, Aborted.") + class StackOverflow(SignalInfo): + def __init__(self, stack_ptr, stack_map, instr=None, process=None): text = "STACK OVERFLOW! Stack pointer is in %s" % stack_map SignalInfo.__init__(self, "stack_overflow", text, - address=stack_ptr, registers={'': stack_ptr}, - instr=instr, process=process) + address=stack_ptr, registers={ + '': stack_ptr}, + instr=instr, process=process) self.stack_ptr = stack_ptr self.stack_map = stack_map -class InvalidMemoryAcces(SignalInfo): + +class InvalidMemoryAccess(SignalInfo): NAME = "invalid_mem_access" PREFIX = "Invalid memory access" PREFIX_ADDR = "Invalid memory access to %s" @@ -115,7 +127,8 @@ """ if address is not None: if isinstance(address, (list, tuple)): - arguments = " or ".join( formatAddress(addr) for addr in address ) + arguments = " or ".join(formatAddress(addr) + for addr in address) else: arguments = formatAddress(address) message = self.PREFIX_ADDR % arguments @@ -127,28 +140,35 @@ if address is not None: name += "-" + formatAddress(address).lower() SignalInfo.__init__(self, name, message, - address=address, size=size, instr=instr, - process=process, registers=registers) + address=address, size=size, instr=instr, + process=process, registers=registers) + -class InvalidRead(InvalidMemoryAcces): +class InvalidRead(InvalidMemoryAccess): NAME = "invalid_read" PREFIX = "Invalid read" PREFIX_ADDR = "Invalid read from %s" -class InvalidWrite(InvalidMemoryAcces): + +class InvalidWrite(InvalidMemoryAccess): NAME = "invalid_write" PREFIX = "Invalid write" PREFIX_ADDR = "Invalid write to %s" + class InstructionError(SignalInfo): + def __init__(self, address, process=None): SignalInfo.__init__(self, "instr_error", - "UNABLE TO EXECUTE CODE AT %s (SEGMENTATION FAULT)" % formatAddress(address), - address=address, - process=process, - registers={'': address}) + "UNABLE TO EXECUTE CODE AT %s (SEGMENTATION FAULT)" % formatAddress( + address), + address=address, + process=process, + registers={'': address}) + class ChildExit(SignalInfo): + def __init__(self, pid=None, status=None, uid=None): if pid is not None and status is not None: message = formatProcessStatus(status, "Child process %s" % pid) @@ -162,4 +182,3 @@ def displayExtra(self, log): if self.uid is not None: log("Signal sent by user %s" % self.uid) - diff -Nru python-ptrace-0.7/ptrace/debugger/syscall_state.py python-ptrace-0.9.3/ptrace/debugger/syscall_state.py --- python-ptrace-0.7/ptrace/debugger/syscall_state.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/debugger/syscall_state.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,7 +1,9 @@ from ptrace.syscall import PtraceSyscall from signal import SIGTRAP + class SyscallState(object): + def __init__(self, process): self.process = process self.ignore_exec_trap = True @@ -20,7 +22,7 @@ self.syscall = PtraceSyscall(self.process, options, regs) self.name = self.syscall.name if (not self.ignore_callback) \ - or (not self.ignore_callback(self.syscall)): + or (not self.ignore_callback(self.syscall)): self.syscall.enter(regs) else: self.syscall = None @@ -31,8 +33,8 @@ if self.syscall: self.syscall.exit() if self.ignore_exec_trap \ - and self.name == "execve" \ - and not self.process.debugger.trace_exec: + and self.name == "execve" \ + and not self.process.debugger.trace_exec: # Ignore the SIGTRAP after exec() syscall exit self.process.syscall() self.process.waitSignals(SIGTRAP) @@ -44,4 +46,3 @@ self.syscall = None self.name = None self.next_event = "enter" - diff -Nru python-ptrace-0.7/ptrace/disasm.py python-ptrace-0.9.3/ptrace/disasm.py --- python-ptrace-0.7/ptrace/disasm.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/disasm.py 2017-02-10 11:38:49.000000000 +0000 @@ -40,6 +40,7 @@ - hexa (str): bytes of the instruction as an hexadecimal string - text (str): string representing the whole instruction """ + def __init__(self, instr): if DISTORM3: self.address, self.size, self.text, self.hexa = instr @@ -73,4 +74,3 @@ except (ImportError, OSError) as err: # OSError if libdistorm64.so doesn't exist HAS_DISASSEMBLER = False - diff -Nru python-ptrace-0.7/ptrace/error.py python-ptrace-0.9.3/ptrace/error.py --- python-ptrace-0.7/ptrace/error.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/error.py 2017-02-10 11:38:50.000000000 +0000 @@ -5,6 +5,7 @@ PTRACE_ERRORS = Exception + def writeBacktrace(logger, log_level=ERROR): """ Write a backtrace into the logger with the specified log level. @@ -22,6 +23,7 @@ pass log_func("Unable to get backtrace") + def formatError(error): """ Format an error as a string. Write the error type as prefix. @@ -29,12 +31,13 @@ """ return "[%s] %s" % (error.__class__.__name__, error) + def writeError(logger, error, title="ERROR", log_level=ERROR): """ Write an error into the logger: - logger: the logger (if None, use getLogger()) - - error: the exception objet - - title: error message prefix (eg. title="Initialization error") + - error: the exception object + - title: error message prefix (e.g. title="Initialization error") - log_level: log level of the error If the exception is a SystemExit or a KeyboardInterrupt, re-emit @@ -48,12 +51,13 @@ log_func("%s: %s" % (title, formatError(error))) writeBacktrace(logger, log_level=changeLogLevel(log_level, -1)) + class PtraceError(Exception): """ Ptrace error: have the optional attributes errno and pid. """ + def __init__(self, message, errno=None, pid=None): Exception.__init__(self, message) self.errno = errno self.pid = pid - diff -Nru python-ptrace-0.7/ptrace/func_arg.py python-ptrace-0.9.3/ptrace/func_arg.py --- python-ptrace-0.7/ptrace/func_arg.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/func_arg.py 2017-02-10 11:38:50.000000000 +0000 @@ -2,12 +2,13 @@ from logging import getLogger from ptrace.ctypes_tools import formatAddress + class FunctionArgument(object): """ Description of a function argument. Attributes: - - function: a Function objet + - function: a Function object - index (int): index of the argument (starting at zero) - - options: a FunctionCallOptions objet + - options: a FunctionCallOptions object - value (int) - type (str, optional) - text (str): string describing the argument @@ -15,8 +16,9 @@ Don't use text attribute directly, use getText() to format the argument instead. """ + def __init__(self, function, index, options, - value=None, type=None, name=None): + value=None, type=None, name=None): self.function = function self.index = index self.options = options @@ -37,8 +39,8 @@ self.text = repr(self.value) except PTRACE_ERRORS as err: writeError(getLogger(), err, - "Format argument %s of function %s() value error" - % (self.name, self.function.name)) + "Format argument %s of function %s() value error" + % (self.name, self.function.name)) self.text = repr(self.value) return self.text @@ -101,4 +103,3 @@ def __repr__(self): return "argument %s of %s()" % (self.name, self.function.name) - diff -Nru python-ptrace-0.7/ptrace/func_call.py python-ptrace-0.9.3/ptrace/func_call.py --- python-ptrace-0.7/ptrace/func_call.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/func_call.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,13 +1,15 @@ from ptrace.func_arg import FunctionArgument + class FunctionCallOptions(object): """ Options to format a function call and its arguments. """ + def __init__(self, - write_types=False, write_argname=False, - replace_socketcall=True, string_max_length=300, - write_address=False, max_array_count=20): + write_types=False, write_argname=False, + replace_socketcall=True, string_max_length=300, + write_address=False, max_array_count=20): self.write_address = write_address self.write_types = write_types self.write_argname = write_argname @@ -16,6 +18,7 @@ self.max_array_count = max_array_count self.instr_pointer = False + class FunctionCall(object): """ A function call. Attributes: @@ -30,6 +33,7 @@ - addArgument(): add a new argument - clearArguments(): remove all arguments """ + def __init__(self, name, options, argument_class=FunctionArgument): self.name = name self.options = options @@ -39,7 +43,8 @@ self.argument_class = argument_class def addArgument(self, value=None, name=None, type=None): - arg = self.argument_class(self, len(self.arguments), self.options, value, type, name) + arg = self.argument_class( + self, len(self.arguments), self.options, value, type, name) self.arguments.append(arg) def clearArguments(self): @@ -56,7 +61,7 @@ return self.arguments[key] def format(self): - arguments = [ arg.format() for arg in self.arguments ] + arguments = [arg.format() for arg in self.arguments] arguments = ", ".join(arguments) if self.restype and self.options.write_types: return "%s %s(%s)" % (self.restype, self.name, arguments) @@ -65,4 +70,3 @@ def __repr__(self): return "" % self.name - diff -Nru python-ptrace-0.7/ptrace/__init__.py python-ptrace-0.9.3/ptrace/__init__.py --- python-ptrace-0.7/ptrace/__init__.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/__init__.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,3 +1,2 @@ -from ptrace.signames import SIGNAMES, signalName -from ptrace.error import PtraceError - +from ptrace.signames import SIGNAMES, signalName # noqa +from ptrace.error import PtraceError # noqa diff -Nru python-ptrace-0.7/ptrace/linux_proc.py python-ptrace-0.9.3/ptrace/linux_proc.py --- python-ptrace-0.7/ptrace/linux_proc.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/linux_proc.py 2017-02-10 11:41:08.000000000 +0000 @@ -13,12 +13,14 @@ PAGE_SIZE = getpagesize() + class ProcError(Exception): """ Linux proc directory error. """ pass + def openProc(path): """ Open a proc entry in read only mode. @@ -29,6 +31,7 @@ except IOError as err: raise ProcError("Unable to open %r: %s" % (filename, err)) + def readProc(path): """ Read the content of a proc entry. @@ -37,6 +40,7 @@ with openProc(path) as procfile: return procfile.read() + def readProcessProc(pid, key): """ Read the content of a process entry in the proc directory. @@ -49,6 +53,7 @@ except IOError as err: raise ProcError("Process %s doesn't exist: %s" % (pid, err)) + class ProcessState(object): """ Processus state. Attributes: @@ -70,8 +75,9 @@ "D": "disk", "Z": "zombie", "T": "traced", - "W": "pagging", + "W": "paging", } + def __init__(self, stat): # pid (program) ... => "pid (program", "..." part, stat = stat.rsplit(')', 1) @@ -81,7 +87,7 @@ # "state ..." => state, "..." stat = stat.split() self.state = stat[0] - stat = [ int(item) for item in stat[1:] ] + stat = [int(item) for item in stat[1:]] # Read next numbers self.ppid = stat[0] @@ -93,6 +99,7 @@ self.stime = stat[11] self.starttime = stat[18] + def readProcessStat(pid): """ Read the process state ('stat') as a ProcessState object. @@ -100,15 +107,17 @@ stat = readProcessProc(pid, 'stat') return ProcessState(stat) + def readProcessStatm(pid): """ Read the process memory status ('statm') as a list of integers. Values are in bytes (and not in pages). """ statm = readProcessProc(pid, 'statm') - statm = [ int(item)*PAGE_SIZE for item in statm.split() ] + statm = [int(item) * PAGE_SIZE for item in statm.split()] return statm + def readProcessProcList(pid, key): """ Read a process entry as a list of strings. @@ -122,6 +131,7 @@ del data[-1] return data + def readProcessLink(pid, key): """ Read a process link. @@ -132,6 +142,7 @@ except OSError as err: raise ProcError("Unable to read proc link %r: %s" % (filename, err)) + def readProcesses(): """ Read all processes identifiers. The function is a generator, @@ -143,13 +154,14 @@ try: yield int(filename) except ValueError: - # Filename is not an integer (eg. "stat" from /proc/stat) + # Filename is not an integer (e.g. "stat" from /proc/stat) continue + def readProcessCmdline(pid, escape_stat=True): """ Read the process command line. If escape_stat is True, format program name - with "[%s]" if the process has no command line, eg. "[khelper]". + with "[%s]" if the process has no command line, e.g. "[khelper]". """ # Try /proc/42/cmdline try: @@ -169,6 +181,7 @@ except ProcError: return None + def searchProcessesByName(process_name): """ Find all processes matching the program name pattern. @@ -180,7 +193,7 @@ for pid in searchProcessByName(pattern): ... """ - suffix = '/'+process_name + suffix = '/' + process_name for pid in readProcesses(): cmdline = readProcessCmdline(pid) if not cmdline: @@ -189,6 +202,7 @@ if program == process_name or program.endswith(suffix): yield pid + def searchProcessByName(process_name): """ Function similar to searchProcessesByName() but only return the identifier @@ -199,6 +213,7 @@ return pid raise ProcError("Unable to find process: %r" % process_name) + def getUptime(): """ Get the system uptime as a datetime.timedelta object. @@ -208,6 +223,7 @@ uptime = float(uptime[0]) return timedelta(seconds=uptime) + def getSystemBoot(): """ Get the system boot date as a datetime.datetime object. @@ -225,5 +241,6 @@ if getSystemBoot.value is None: raise ProcError("Unable to read system boot time!") return getSystemBoot.value -getSystemBoot.value = None + +getSystemBoot.value = None diff -Nru python-ptrace-0.7/ptrace/logging_tools.py python-ptrace-0.9.3/ptrace/logging_tools.py --- python-ptrace-0.7/ptrace/logging_tools.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/logging_tools.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,6 +1,7 @@ from ptrace.tools import minmax from logging import ERROR, WARNING, INFO, DEBUG + def getLogFunc(logger, level): """ Get the logger function for the specified logging level. @@ -16,6 +17,7 @@ else: return logger.error + def changeLogLevel(level, delta): """ Compute log level and make sure that the result is in DEBUG..ERROR. @@ -25,5 +27,4 @@ >>> changeLogLevel(DEBUG, 1) == INFO True """ - return minmax(DEBUG, level + delta*10, ERROR) - + return minmax(DEBUG, level + delta * 10, ERROR) diff -Nru python-ptrace-0.7/ptrace/mockup.py python-ptrace-0.9.3/ptrace/mockup.py --- python-ptrace-0.7/ptrace/mockup.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/mockup.py 2017-02-10 11:38:49.000000000 +0000 @@ -2,7 +2,9 @@ Mockup classes used in unit tests. """ + class FakeProcess(object): + def __init__(self): self.regs = {} @@ -11,4 +13,3 @@ def getreg(self, name): return self.regs[name] - diff -Nru python-ptrace-0.7/ptrace/os_tools.py python-ptrace-0.9.3/ptrace/os_tools.py --- python-ptrace-0.7/ptrace/os_tools.py 2013-06-23 01:56:10.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/os_tools.py 2017-02-10 11:38:49.000000000 +0000 @@ -26,4 +26,3 @@ HAS_PROC = RUNNING_LINUX HAS_PTRACE = (RUNNING_BSD or RUNNING_LINUX) - diff -Nru python-ptrace-0.7/ptrace/process_tools.py python-ptrace-0.9.3/ptrace/process_tools.py --- python-ptrace-0.7/ptrace/process_tools.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/process_tools.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,8 +1,8 @@ from ptrace.os_tools import RUNNING_LINUX, RUNNING_WINDOWS if RUNNING_LINUX: from ptrace.linux_proc import (ProcError, openProc, - readProcessProcList, readProcessLink, readProcessStat) -from ptrace.signames import signalName + readProcessProcList, readProcessLink, readProcessStat) +from ptrace.signames import signalName # noqa if not RUNNING_WINDOWS: from os import ( WIFSTOPPED, WSTOPSIG, @@ -10,6 +10,7 @@ WIFEXITED, WEXITSTATUS, WCOREDUMP) + def dumpProcessInfo(log, pid, max_length=None): """ Dump all information about a process: @@ -50,13 +51,14 @@ index = 0 while index < len(env): var = env[index] - if max_length < length+len(var): + if max_length < length + len(var): del env[index] removed += 1 else: length += len(var) index += 1 - env = ', '.join( "%s=%r" % tuple(item.split("=", 1)) for item in env ) + env = ', '.join("%s=%r" % tuple(item.split("=", 1)) + for item in env) if removed: env += ', ... (skip %s vars)' % removed log("Process environment: %s" % env) @@ -75,9 +77,9 @@ status_file = openProc("%s/status" % pid) for line in status_file: if line.startswith("Uid:"): - user = [ int(id) for id in line[5:].split("\t") ] + user = [int(id) for id in line[5:].split("\t")] if line.startswith("Gid:"): - group = [ int(id) for id in line[5:].split("\t") ] + group = [int(id) for id in line[5:].split("\t")] status_file.close() if user: text = "User identifier: %s" % user[0] @@ -93,6 +95,7 @@ # Permission denied pass + def formatProcessStatus(status, title="Process"): """ Format a process status (integer) as a string. @@ -117,4 +120,3 @@ if WCOREDUMP(status): text += " (core dumped)" return text - diff -Nru python-ptrace-0.7/ptrace/profiler.py python-ptrace-0.9.3/ptrace/profiler.py --- python-ptrace-0.7/ptrace/profiler.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/profiler.py 2017-02-10 11:38:49.000000000 +0000 @@ -3,9 +3,10 @@ from os import unlink from io import StringIO + def runProfiler(logger, func, args=tuple(), kw={}, -verbose=True, nb_func=25, -sort_by=('time',)): + verbose=True, nb_func=25, + sort_by=('time',)): """ Run a function in a profiler and then display the functions sorted by time. """ @@ -30,4 +31,3 @@ return result finally: unlink(profile_filename) - diff -Nru python-ptrace-0.7/ptrace/pydistorm.py python-ptrace-0.9.3/ptrace/pydistorm.py --- python-ptrace-0.7/ptrace/pydistorm.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/pydistorm.py 2017-02-10 11:41:08.000000000 +0000 @@ -47,15 +47,18 @@ MAX_INSTRUCTIONS = 100 MAX_TEXT_SIZE = 60 + class _WString(Structure): _fields_ = ( ("pos", c_uint), ("p", c_char * MAX_TEXT_SIZE), ) + def __str__(self): # FIXME: Use pos? return self.p + class _DecodedInst(Structure): _fields_ = ( ("mnemonic", _WString), @@ -64,10 +67,14 @@ ("size", c_uint), ("offset", _OffsetType), ) + def __str__(self): return "%s %s" % (self.mnemonic, self.operands) -internal_decode.argtypes = (_OffsetType, c_void_p, c_int, c_int, c_void_p, c_uint, POINTER(c_uint)) + +internal_decode.argtypes = (_OffsetType, c_void_p, + c_int, c_int, c_void_p, c_uint, POINTER(c_uint)) + def Decode(codeOffset, code, dt=Decode32Bits): """ @@ -80,19 +87,21 @@ raise TypeError("code have to be a %s, not %s" % (binary_type.__name__, type(code).__name__)) if dt not in DECODERS: - raise IndexError("Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.") + raise IndexError( + "Decoding-type must be either Decode16Bits, Decode32Bits or Decode64Bits.") # Allocate memory for decoder code_buffer = create_string_buffer(code) decodedInstructionsCount = c_uint() - result = create_string_buffer(sizeof(_DecodedInst)*MAX_INSTRUCTIONS) + result = create_string_buffer(sizeof(_DecodedInst) * MAX_INSTRUCTIONS) # Prepare arguments codeLen = len(code) code = addressof(code_buffer) while codeLen: # Call internal decoder - res = internal_decode(codeOffset, code, codeLen, dt, result, MAX_INSTRUCTIONS, byref(decodedInstructionsCount)) + res = internal_decode(codeOffset, code, codeLen, dt, result, + MAX_INSTRUCTIONS, byref(decodedInstructionsCount)) # Check for errors if res == DECRES_INPUTERR: @@ -117,4 +126,3 @@ code += size codeOffset += size codeLen -= size - diff -Nru python-ptrace-0.7/ptrace/signames.py python-ptrace-0.9.3/ptrace/signames.py --- python-ptrace-0.7/ptrace/signames.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/signames.py 2017-02-10 11:41:08.000000000 +0000 @@ -8,18 +8,19 @@ PREFERRED_NAMES = ("SIGABRT", "SIGHUP", "SIGCHLD", "SIGPOLL") + def getSignalNames(): """ - Create signal names dictionay (eg. 9 => 'SIGKILL') using dir(signal). + Create signal names dictionary (e.g. 9 => 'SIGKILL') using dir(signal). If multiple signal names have the same number, use the first matching name - in PREFERRED_NAME to select preferred name (eg. SIGIOT=SIGABRT=17). + in PREFERRED_NAME to select preferred name (e.g. SIGIOT=SIGABRT=17). """ import signal allnames = {} for name in dir(signal): if not name.startswith("SIG"): continue - signum = getattr(signal,name) + signum = getattr(signal, name) try: allnames[signum].append(name) except KeyError: @@ -38,8 +39,11 @@ name = names[0] signames[signum] = name return signames + + SIGNAMES = getSignalNames() + def signalName(signum): """ Get the name of a signal @@ -54,4 +58,3 @@ return SIGNAMES[signum] except KeyError: return "signal<%s>" % signum - diff -Nru python-ptrace-0.7/ptrace/six.py python-ptrace-0.9.3/ptrace/six.py --- python-ptrace-0.7/ptrace/six.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/six.py 2017-02-10 11:38:49.000000000 +0000 @@ -53,6 +53,7 @@ else: # It's possible to have sizeof(long) != sizeof(Py_ssize_t). class X(object): + def __len__(self): return 1 << 31 try: @@ -130,7 +131,6 @@ return getattr(module, self.attr) - class _MovedItems(types.ModuleType): """Lazy loading of moved objects""" @@ -138,7 +138,8 @@ _moved_attributes = [ MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), + MovedAttribute("filterfalse", "itertools", "itertools", + "ifilterfalse", "filterfalse"), MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), MovedAttribute("map", "itertools", "builtins", "imap", "map"), MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), @@ -148,7 +149,8 @@ MovedAttribute("UserString", "UserString", "collections"), MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), + MovedAttribute("zip_longest", "itertools", "itertools", + "izip_longest", "zip_longest"), MovedModule("builtins", "__builtin__"), MovedModule("configparser", "ConfigParser"), @@ -158,7 +160,8 @@ MovedModule("html_entities", "htmlentitydefs", "html.entities"), MovedModule("html_parser", "HTMLParser", "html.parser"), MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), + MovedModule("email_mime_multipart", "email.MIMEMultipart", + "email.mime.multipart"), MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), @@ -171,8 +174,10 @@ MovedModule("tkinter", "Tkinter"), MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), + MovedModule("tkinter_scrolledtext", "ScrolledText", + "tkinter.scrolledtext"), + MovedModule("tkinter_simpledialog", "SimpleDialog", + "tkinter.simpledialog"), MovedModule("tkinter_tix", "Tix", "tkinter.tix"), MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), @@ -185,9 +190,12 @@ MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), + MovedModule("urllib_parse", __name__ + + ".moves.urllib_parse", "urllib.parse"), + MovedModule("urllib_error", __name__ + + ".moves.urllib_error", "urllib.error"), + MovedModule("urllib", __name__ + ".moves.urllib", + __name__ + ".moves.urllib"), MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), MovedModule("winreg", "_winreg"), ] @@ -198,7 +206,6 @@ moves = sys.modules[__name__ + ".moves"] = _MovedItems(__name__ + ".moves") - class Module_six_moves_urllib_parse(types.ModuleType): """Lazy loading of moved objects in six.moves.urllib_parse""" @@ -223,8 +230,10 @@ setattr(Module_six_moves_urllib_parse, attr.name, attr) del attr -sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse") -sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse(__name__ + ".moves.urllib.parse") +sys.modules[__name__ + ".moves.urllib_parse"] = Module_six_moves_urllib_parse( + __name__ + ".moves.urllib_parse") +sys.modules[__name__ + ".moves.urllib.parse"] = Module_six_moves_urllib_parse( + __name__ + ".moves.urllib.parse") class Module_six_moves_urllib_error(types.ModuleType): @@ -240,8 +249,10 @@ setattr(Module_six_moves_urllib_error, attr.name, attr) del attr -sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib_error") -sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error(__name__ + ".moves.urllib.error") +sys.modules[__name__ + ".moves.urllib_error"] = Module_six_moves_urllib_error( + __name__ + ".moves.urllib_error") +sys.modules[__name__ + ".moves.urllib.error"] = Module_six_moves_urllib_error( + __name__ + ".moves.urllib.error") class Module_six_moves_urllib_request(types.ModuleType): @@ -263,7 +274,8 @@ MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), MovedAttribute("BaseHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), + MovedAttribute("HTTPPasswordMgrWithDefaultRealm", + "urllib2", "urllib.request"), MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), @@ -286,8 +298,10 @@ setattr(Module_six_moves_urllib_request, attr.name, attr) del attr -sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib_request") -sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request(__name__ + ".moves.urllib.request") +sys.modules[__name__ + ".moves.urllib_request"] = Module_six_moves_urllib_request( + __name__ + ".moves.urllib_request") +sys.modules[__name__ + ".moves.urllib.request"] = Module_six_moves_urllib_request( + __name__ + ".moves.urllib.request") class Module_six_moves_urllib_response(types.ModuleType): @@ -304,8 +318,10 @@ setattr(Module_six_moves_urllib_response, attr.name, attr) del attr -sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib_response") -sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response(__name__ + ".moves.urllib.response") +sys.modules[__name__ + ".moves.urllib_response"] = Module_six_moves_urllib_response( + __name__ + ".moves.urllib_response") +sys.modules[__name__ + ".moves.urllib.response"] = Module_six_moves_urllib_response( + __name__ + ".moves.urllib.response") class Module_six_moves_urllib_robotparser(types.ModuleType): @@ -319,8 +335,10 @@ setattr(Module_six_moves_urllib_robotparser, attr.name, attr) del attr -sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib_robotparser") -sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser") +sys.modules[__name__ + ".moves.urllib_robotparser"] = Module_six_moves_urllib_robotparser( + __name__ + ".moves.urllib_robotparser") +sys.modules[__name__ + ".moves.urllib.robotparser"] = Module_six_moves_urllib_robotparser( + __name__ + ".moves.urllib.robotparser") class Module_six_moves_urllib(types.ModuleType): @@ -332,7 +350,8 @@ robotparser = sys.modules[__name__ + ".moves.urllib_robotparser"] -sys.modules[__name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") +sys.modules[ + __name__ + ".moves.urllib"] = Module_six_moves_urllib(__name__ + ".moves.urllib") def add_move(move): @@ -430,14 +449,17 @@ """Return an iterator over the keys of a dictionary.""" return iter(getattr(d, _iterkeys)(**kw)) + def itervalues(d, **kw): """Return an iterator over the values of a dictionary.""" return iter(getattr(d, _itervalues)(**kw)) + def iteritems(d, **kw): """Return an iterator over the (key, value) pairs of a dictionary.""" return iter(getattr(d, _iteritems)(**kw)) + def iterlists(d, **kw): """Return an iterator over the (key, [values]) pairs of a dictionary.""" return iter(getattr(d, _iterlists)(**kw)) @@ -446,6 +468,7 @@ if PY3: def b(s): return s.encode("latin-1") + def u(s): return s unichr = chr @@ -464,14 +487,18 @@ else: def b(s): return s + def u(s): return unicode(s, "unicode_escape") unichr = unichr int2byte = chr + def byte2int(bs): return ord(bs[0]) + def indexbytes(buf, i): return ord(buf[i]) + def iterbytes(buf): return (ord(byte) for byte in buf) import StringIO @@ -484,13 +511,11 @@ import builtins exec_ = getattr(builtins, "exec") - def reraise(tp, value, tb=None): if value.__traceback__ is not tb: raise value.with_traceback(tb) raise value - print_ = getattr(builtins, "print") del builtins @@ -507,17 +532,16 @@ _locs_ = _globs_ exec("""exec _code_ in _globs_, _locs_""") - exec_("""def reraise(tp, value, tb=None): raise tp, value, tb """) - def print_(*args, **kwargs): """The new-style print function.""" fp = kwargs.pop("file", sys.stdout) if fp is None: return + def write(data): if not isinstance(data, basestring): data = str(data) @@ -565,6 +589,7 @@ """Create a base class with a metaclass.""" return meta("NewBase", bases, {}) + def add_metaclass(metaclass): """Class decorator for creating a class with a metaclass.""" def wrapper(cls): diff -Nru python-ptrace-0.7/ptrace/syscall/freebsd_constants.py python-ptrace-0.9.3/ptrace/syscall/freebsd_constants.py --- python-ptrace-0.7/ptrace/syscall/freebsd_constants.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/freebsd_constants.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,20 +1,20 @@ from ptrace.syscall.posix_constants import SYSCALL_ARG_DICT RLIMIT_RESOURCE = { - 0: "RLIMIT_CPU", - 1: "RLIMIT_FSIZE", - 2: "RLIMIT_DATA", - 3: "RLIMIT_STACK", - 4: "RLIMIT_CORE", - 5: "RLIMIT_RSS", - 6: "RLIMIT_MEMLOCK", - 7: "RLIMIT_NPROC", - 8: "RLIMIT_NOFILE", - 9: "RLIMIT_SBSIZE", + 0: "RLIMIT_CPU", + 1: "RLIMIT_FSIZE", + 2: "RLIMIT_DATA", + 3: "RLIMIT_STACK", + 4: "RLIMIT_CORE", + 5: "RLIMIT_RSS", + 6: "RLIMIT_MEMLOCK", + 7: "RLIMIT_NPROC", + 8: "RLIMIT_NOFILE", + 9: "RLIMIT_SBSIZE", 10: "RLIMIT_VMEM", } -SIGPROCMASK_HOW = {1:" SIG_BLOCK", 2: "SIG_UNBLOCK", 3: "SIG_SETMASK"} +SIGPROCMASK_HOW = {1: " SIG_BLOCK", 2: "SIG_UNBLOCK", 3: "SIG_SETMASK"} SYSCALL_ARG_DICT.update({ "getrlimit": {"resource": RLIMIT_RESOURCE}, @@ -22,4 +22,3 @@ "sigprocmask": {"how": SIGPROCMASK_HOW}, "rt_sigprocmask": {"how": SIGPROCMASK_HOW}, }) - diff -Nru python-ptrace-0.7/ptrace/syscall/freebsd_syscall.py python-ptrace-0.9.3/ptrace/syscall/freebsd_syscall.py --- python-ptrace-0.7/ptrace/syscall/freebsd_syscall.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/freebsd_syscall.py 2017-02-10 11:38:51.000000000 +0000 @@ -11,10 +11,10 @@ 5: "open", 6: "close", 7: "wait4", -# 8: old creat + # 8: old creat 9: "link", 10: "unlink", -# 11: obsolete execv + # 11: obsolete execv 12: "chdir", 13: "fchdir", 14: "mknod", @@ -22,7 +22,7 @@ 16: "chown", 17: "break", 18: "freebsd4_getfsstat", -# 19: old lseek + # 19: old lseek 20: "getpid", 21: "mount", 22: "unmount", @@ -41,21 +41,21 @@ 35: "fchflags", 36: "sync", 37: "kill", -# 38: old stat + # 38: old stat 39: "getppid", -# 40: old lstat + # 40: old lstat 41: "dup", 42: "pipe", 43: "getegid", 44: "profil", 45: "ktrace", -# 46: old sigaction + # 46: old sigaction 47: "getgid", -# 48: old sigprocmask + # 48: old sigprocmask 49: "getlogin", 50: "setlogin", 51: "acct", -# 52: old sigpending + # 52: old sigpending 53: "sigaltstack", 54: "ioctl", 55: "reboot", @@ -65,33 +65,33 @@ 59: "execve", 60: "umask", 61: "chroot", -# 62: old fstat -# 63: old getkerninfo -# 64: old getpagesize + # 62: old fstat + # 63: old getkerninfo + # 64: old getpagesize 65: "msync", 66: "vfork", -# 67: obsolete vread -# 68: obsolete vwrite + # 67: obsolete vread + # 68: obsolete vwrite 69: "sbrk", 70: "sstk", -# 71: old mmap + # 71: old mmap 72: "vadvise", 73: "munmap", 74: "mprotect", 75: "madvise", -# 76: obsolete vhangup -# 77: obsolete vlimit + # 76: obsolete vhangup + # 77: obsolete vlimit 78: "mincore", 79: "getgroups", 80: "setgroups", 81: "getpgrp", 82: "setpgid", 83: "setitimer", -# 84: old wait + # 84: old wait 85: "swapon", 86: "getitimer", -# 87: old gethostname -# 88: old sethostname + # 87: old gethostname + # 88: old sethostname 89: "getdtablesize", 90: "dup2", 92: "fcntl", @@ -100,23 +100,23 @@ 96: "setpriority", 97: "socket", 98: "connect", -# 99: old accept + # 99: old accept 100: "getpriority", -# 101: old send -# 102: old recv -# 103: old sigreturn + # 101: old send + # 102: old recv + # 103: old sigreturn 104: "bind", 105: "setsockopt", 106: "listen", -# 107: obsolete vtimes -# 108: old sigvec -# 109: old sigblock -# 110: old sigsetmask -# 111: old sigsuspend -# 112: old sigstack -# 113: old recvmsg -# 114: old sendmsg -# 115: obsolete vtrace + # 107: obsolete vtimes + # 108: old sigvec + # 109: old sigblock + # 110: old sigsetmask + # 111: old sigsuspend + # 112: old sigstack + # 113: old recvmsg + # 114: old sendmsg + # 115: obsolete vtrace 116: "gettimeofday", 117: "getrusage", 118: "getsockopt", @@ -125,12 +125,12 @@ 122: "settimeofday", 123: "fchown", 124: "fchmod", -# 125: old recvfrom + # 125: old recvfrom 126: "setreuid", 127: "setregid", 128: "rename", -# 129: old truncate -# 130: old ftruncate + # 129: old truncate + # 130: old ftruncate 131: "flock", 132: "mkfifo", 133: "sendto", @@ -139,20 +139,20 @@ 136: "mkdir", 137: "rmdir", 138: "utimes", -# 139: obsolete 4.2 sigreturn + # 139: obsolete 4.2 sigreturn 140: "adjtime", -# 141: old getpeername -# 142: old gethostid -# 143: old sethostid -# 144: old getrlimit -# 145: old setrlimit -# 146: old killpg + # 141: old getpeername + # 142: old gethostid + # 143: old sethostid + # 144: old getrlimit + # 145: old setrlimit + # 146: old killpg 147: "setsid", 148: "quotactl", -# 149: old quota -# 150: old getsockname + # 149: old quota + # 150: old getsockname 155: "nfssvc", -# 156: old getdirentries + # 156: old getdirentries 157: "freebsd4_statfs", 158: "freebsd4_fstatfs", 160: "lgetfh", @@ -246,7 +246,7 @@ 310: "getsid", 311: "setresuid", 312: "setresgid", -# 313: obsolete signanosleep + # 313: obsolete signanosleep 314: "aio_return", 315: "aio_suspend", 316: "aio_cancel", @@ -255,8 +255,8 @@ 319: "oaio_write", 320: "olio_listio", 321: "yield", -# 322: obsolete thr_sleep -# 323: obsolete thr_wakeup + # 322: obsolete thr_sleep + # 323: obsolete thr_wakeup 324: "mlockall", 325: "munlockall", 326: "__getcwd", diff -Nru python-ptrace-0.7/ptrace/syscall/__init__.py python-ptrace-0.9.3/ptrace/syscall/__init__.py --- python-ptrace-0.7/ptrace/syscall/__init__.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/__init__.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,5 +1,4 @@ -from ptrace.syscall.names import SYSCALL_NAMES, SOCKET_SYSCALL_NAMES -from ptrace.syscall.prototypes import SYSCALL_PROTOTYPES, FILENAME_ARGUMENTS -from ptrace.syscall.syscall_argument import SyscallArgument -from ptrace.syscall.ptrace_syscall import PtraceSyscall - +from ptrace.syscall.names import SYSCALL_NAMES, SOCKET_SYSCALL_NAMES # noqa +from ptrace.syscall.prototypes import SYSCALL_PROTOTYPES, FILENAME_ARGUMENTS, DIRFD_ARGUMENTS # noqa +from ptrace.syscall.syscall_argument import SyscallArgument # noqa +from ptrace.syscall.ptrace_syscall import PtraceSyscall, SYSCALL_REGISTER, RETURN_VALUE_REGISTER # noqa diff -Nru python-ptrace-0.7/ptrace/syscall/linux_constants.py python-ptrace-0.9.3/ptrace/syscall/linux_constants.py --- python-ptrace-0.7/ptrace/syscall/linux_constants.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/linux_constants.py 2017-02-10 11:38:49.000000000 +0000 @@ -4,16 +4,16 @@ FD_SETSIZE = 1024 RLIMIT_RESOURCE = { - 0: "RLIMIT_CPU", - 1: "RLIMIT_FSIZE", - 2: "RLIMIT_DATA", - 3: "RLIMIT_STACK", - 4: "RLIMIT_CORE", - 5: "RLIMIT_RSS", - 6: "RLIMIT_NPROC", - 7: "RLIMIT_NOFILE", - 8: "RLIMIT_MEMLOCK", - 9: "RLIMIT_AS", + 0: "RLIMIT_CPU", + 1: "RLIMIT_FSIZE", + 2: "RLIMIT_DATA", + 3: "RLIMIT_STACK", + 4: "RLIMIT_CORE", + 5: "RLIMIT_RSS", + 6: "RLIMIT_NPROC", + 7: "RLIMIT_NOFILE", + 8: "RLIMIT_MEMLOCK", + 9: "RLIMIT_AS", 10: "RLIMIT_LOCKS", 11: "RLIMIT_SIGPENDING", 12: "RLIMIT_MSGQUEUE", @@ -30,4 +30,3 @@ "sigprocmask": {"how": SIGPROCMASK_HOW}, "rt_sigprocmask": {"how": SIGPROCMASK_HOW}, }) - diff -Nru python-ptrace-0.7/ptrace/syscall/linux_struct.py python-ptrace-0.9.3/ptrace/syscall/linux_struct.py --- python-ptrace-0.7/ptrace/syscall/linux_struct.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/linux_struct.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,22 +1,25 @@ from ctypes import (Structure, - c_char, c_short, c_int, c_uint, c_long, c_ulong) + c_char, c_short, c_int, c_uint, c_long, c_ulong) time_t = c_long suseconds_t = c_long rlim_t = c_long + class timeval(Structure): _fields_ = ( ("tv_sec", time_t), ("tv_usec", suseconds_t), ) + class timespec(Structure): _fields_ = ( ("tv_sec", time_t), ("tv_nsec", c_long), ) + class pollfd(Structure): _fields_ = ( ("fd", c_int), @@ -24,35 +27,37 @@ ("revents", c_short), ) + class rlimit(Structure): _fields_ = ( ("rlim_cur", rlim_t), ("rlim_max", rlim_t), ) + class new_utsname(Structure): _fields_ = ( - ("sysname", c_char*65), - ("nodename", c_char*65), - ("release", c_char*65), - ("version", c_char*65), - ("machine", c_char*65), - ("domainname", c_char*65), + ("sysname", c_char * 65), + ("nodename", c_char * 65), + ("release", c_char * 65), + ("version", c_char * 65), + ("machine", c_char * 65), + ("domainname", c_char * 65), ) # Arch depend + + class user_desc(Structure): _fields_ = ( ("entry_number", c_uint), ("base_addr", c_ulong), ("limit", c_uint), ("_bits_", c_char), -# unsigned int seg_32bit:1; -# unsigned int contents:2; -# unsigned int read_exec_only:1; -# unsigned int limit_in_pages:1; -# unsigned int seg_not_present:1; -# unsigned int useable:1; + # unsigned int seg_32bit:1; + # unsigned int contents:2; + # unsigned int read_exec_only:1; + # unsigned int limit_in_pages:1; + # unsigned int seg_not_present:1; + # unsigned int useable:1; ) - - diff -Nru python-ptrace-0.7/ptrace/syscall/linux_syscall32.py python-ptrace-0.9.3/ptrace/syscall/linux_syscall32.py --- python-ptrace-0.7/ptrace/syscall/linux_syscall32.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/linux_syscall32.py 2017-02-10 11:38:49.000000000 +0000 @@ -3,106 +3,106 @@ # List extracted from Linux kernel source code, see: # arch/i386/kernel/syscall_table.S SYSCALL_NAMES = { - 0: "restart_syscall", - 1: "exit", - 2: "fork", - 3: "read", - 4: "write", - 5: "open", - 6: "close", - 7: "waitpid", - 8: "creat", - 9: "link", - 10: "unlink", - 11: "execve", - 12: "chdir", - 13: "time", - 14: "mknod", - 15: "chmod", - 16: "lchown16", -# 17: - - 18: "stat", - 19: "lseek", - 20: "getpid", - 21: "mount", - 22: "oldumount", - 23: "setuid16", - 24: "getuid16", - 25: "stime", - 26: "ptrace", - 27: "alarm", - 28: "fstat", - 29: "pause", - 30: "utime", -# 31: - -# 32: - - 33: "access", - 34: "nice", -# 35: - - 36: "sync", - 37: "kill", - 38: "rename", - 39: "mkdir", - 40: "rmdir", - 41: "dup", - 42: "pipe", - 43: "times", -# 44: - - 45: "brk", - 46: "setgid16", - 47: "getgid16", - 48: "signal", - 49: "geteuid16", - 50: "getegid16", - 51: "acct", - 52: "umount", -# 53: - - 54: "ioctl", - 55: "fcntl", -# 56: - - 57: "setpgid", -# 58: - - 59: "oldolduname", - 60: "umask", - 61: "chroot", - 62: "ustat", - 63: "dup2", - 64: "getppid", - 65: "getpgrp", - 66: "setsid", - 67: "sigaction", - 68: "sgetmask", - 69: "ssetmask", - 70: "setreuid16", - 71: "setregid16", - 72: "sigsuspend", - 73: "sigpending", - 74: "sethostname", - 75: "setrlimit", - 76: "old_getrlimit", - 77: "getrusage", - 78: "gettimeofday", - 79: "settimeofday", - 80: "getgroups16", - 81: "setgroups16", - 82: "old_select", - 83: "symlink", - 84: "lstat", - 85: "readlink", - 86: "uselib", - 87: "swapon", - 88: "reboot", - 89: "old_readdir", - 90: "old_mmap", - 91: "munmap", - 92: "truncate", - 93: "ftruncate", - 94: "fchmod", - 95: "fchown16", - 96: "getpriority", - 97: "setpriority", -# 98: - - 99: "statfs", + 0: "restart_syscall", + 1: "exit", + 2: "fork", + 3: "read", + 4: "write", + 5: "open", + 6: "close", + 7: "waitpid", + 8: "creat", + 9: "link", + 10: "unlink", + 11: "execve", + 12: "chdir", + 13: "time", + 14: "mknod", + 15: "chmod", + 16: "lchown16", + # 17: - + 18: "stat", + 19: "lseek", + 20: "getpid", + 21: "mount", + 22: "oldumount", + 23: "setuid16", + 24: "getuid16", + 25: "stime", + 26: "ptrace", + 27: "alarm", + 28: "fstat", + 29: "pause", + 30: "utime", + # 31: - + # 32: - + 33: "access", + 34: "nice", + # 35: - + 36: "sync", + 37: "kill", + 38: "rename", + 39: "mkdir", + 40: "rmdir", + 41: "dup", + 42: "pipe", + 43: "times", + # 44: - + 45: "brk", + 46: "setgid16", + 47: "getgid16", + 48: "signal", + 49: "geteuid16", + 50: "getegid16", + 51: "acct", + 52: "umount", + # 53: - + 54: "ioctl", + 55: "fcntl", + # 56: - + 57: "setpgid", + # 58: - + 59: "oldolduname", + 60: "umask", + 61: "chroot", + 62: "ustat", + 63: "dup2", + 64: "getppid", + 65: "getpgrp", + 66: "setsid", + 67: "sigaction", + 68: "sgetmask", + 69: "ssetmask", + 70: "setreuid16", + 71: "setregid16", + 72: "sigsuspend", + 73: "sigpending", + 74: "sethostname", + 75: "setrlimit", + 76: "old_getrlimit", + 77: "getrusage", + 78: "gettimeofday", + 79: "settimeofday", + 80: "getgroups16", + 81: "setgroups16", + 82: "old_select", + 83: "symlink", + 84: "lstat", + 85: "readlink", + 86: "uselib", + 87: "swapon", + 88: "reboot", + 89: "old_readdir", + 90: "old_mmap", + 91: "munmap", + 92: "truncate", + 93: "ftruncate", + 94: "fchmod", + 95: "fchown16", + 96: "getpriority", + 97: "setpriority", + # 98: - + 99: "statfs", 100: "fstatfs", 101: "ioperm", 102: "socketcall", @@ -115,7 +115,7 @@ 109: "olduname", 110: "iopl", 111: "vhangup", -# 112: old "idle" + # 112: old "idle" 113: "vm86old", 114: "wait4", 115: "swapoff", @@ -130,17 +130,17 @@ 124: "adjtimex", 125: "mprotect", 126: "sigprocmask", -# 127: old "create_module" + # 127: old "create_module" 128: "init_module", 129: "delete_module", -# 130: old "get_kernel_syms" + # 130: old "get_kernel_syms" 131: "quotactl", 132: "getpgid", 133: "fchdir", 134: "bdflush", 135: "sysfs", 136: "personality", -# 137: reserved for afs_syscall + # 137: reserved for afs_syscall 138: "setfsuid16", 139: "setfsgid16", 140: "llseek", @@ -170,7 +170,7 @@ 164: "setresuid16", 165: "getresuid16", 166: "vm86", -# 167: old "query_module" + # 167: old "query_module" 168: "poll", 169: "nfsservctl", 170: "setresgid16", @@ -191,8 +191,8 @@ 185: "capset", 186: "sigaltstack", 187: "sendfile", -# 188: (reserved) -# 189: (reserved) + # 188: (reserved) + # 189: (reserved) 190: "vfork", 191: "getrlimit", 192: "mmap2", @@ -220,14 +220,14 @@ 214: "setgid", 215: "setfsuid", 216: "setfsgid", -# ------------------------------- + # ------------------------------- 217: "pivot_root", 218: "mincore", 219: "madvise", 220: "getdents64", 221: "fcntl64", -# 222: - -# 223: - + # 222: - + # 223: - 224: "gettid", 225: "readahead", 226: "setxattr", @@ -255,7 +255,7 @@ 248: "io_submit", 249: "io_cancel", 250: "fadvise64", -# 251: - + # 251: - 252: "exit_group", 253: "lookup_dcookie", 254: "epoll_create", @@ -277,7 +277,7 @@ 270: "tgkill", 271: "utimes", 272: "fadvise64_64", -# 273: - + # 273: - 274: "mbind", 275: "get_mempolicy", 276: "set_mempolicy", @@ -289,7 +289,7 @@ 282: "mq_getsetattr", 283: "kexec_load", 284: "waitid", -# 285: - + # 285: - 286: "add_key", 287: "request_key", 288: "keyctl", @@ -327,4 +327,3 @@ } SOCKET_SYSCALL_NAMES = set(("socketcall",)) - diff -Nru python-ptrace-0.7/ptrace/syscall/linux_syscall64.py python-ptrace-0.9.3/ptrace/syscall/linux_syscall64.py --- python-ptrace-0.7/ptrace/syscall/linux_syscall64.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/linux_syscall64.py 2017-02-10 11:38:50.000000000 +0000 @@ -1,15 +1,15 @@ # Linux kernel 2.6.23 on Intel Core2 Duo E6400 SYSCALL_NAMES = { - 0: "read", - 1: "write", - 2: "open", - 3: "close", - 4: "stat", - 5: "fstat", - 6: "lstat", - 7: "poll", - 8: "lseek", - 9: "mmap", + 0: "read", + 1: "write", + 2: "open", + 3: "close", + 4: "stat", + 5: "fstat", + 6: "lstat", + 7: "poll", + 8: "lseek", + 9: "mmap", 10: "mprotect", 11: "munmap", 12: "brk", @@ -100,192 +100,192 @@ 97: "getrlimit", 98: "getrusage", 99: "sysinfo", - 100: "times", - 101: "ptrace", - 102: "getuid", - 103: "syslog", - 104: "getgid", - 105: "setuid", - 106: "setgid", - 107: "geteuid", - 108: "getegid", - 109: "setpgid", - 110: "getppid", - 111: "getpgrp", - 112: "setsid", - 113: "setreuid", - 114: "setregid", - 115: "getgroups", - 116: "setgroups", - 117: "setresuid", - 118: "getresuid", - 119: "setresgid", - 120: "getresgid", - 121: "getpgid", - 122: "setfsuid", - 123: "setfsgid", - 124: "getsid", - 125: "capget", - 126: "capset", - 127: "rt_sigpending", - 128: "rt_sigtimedwait", - 129: "rt_sigqueueinfo", - 130: "rt_sigsuspend", - 131: "sigaltstack", - 132: "utime", - 133: "mknod", - 134: "uselib", - 135: "personality", - 136: "ustat", - 137: "statfs", - 138: "fstatfs", - 139: "sysfs", - 140: "getpriority", - 141: "setpriority", - 142: "sched_setparam", - 143: "sched_getparam", - 144: "sched_setscheduler", - 145: "sched_getscheduler", - 146: "sched_get_priority_max", - 147: "sched_get_priority_min", - 148: "sched_rr_get_interval", - 149: "mlock", - 150: "munlock", - 151: "mlockall", - 152: "munlockall", - 153: "vhangup", - 154: "modify_ldt", - 155: "pivot_root", - 156: "_sysctl", - 157: "prctl", - 158: "arch_prctl", - 159: "adjtimex", - 160: "setrlimit", - 161: "chroot", - 162: "sync", - 163: "acct", - 164: "settimeofday", - 165: "mount", - 166: "umount2", - 167: "swapon", - 168: "swapoff", - 169: "reboot", - 170: "sethostname", - 171: "setdomainname", - 172: "iopl", - 173: "ioperm", - 174: "create_module", - 175: "init_module", - 176: "delete_module", - 177: "get_kernel_syms", - 178: "query_module", - 179: "quotactl", - 180: "nfsservctl", - 181: "getpmsg", - 182: "putpmsg", - 183: "afs_syscall", - 184: "tuxcall", - 185: "security", - 186: "gettid", - 187: "readahead", - 188: "setxattr", - 189: "lsetxattr", - 190: "fsetxattr", - 191: "getxattr", - 192: "lgetxattr", - 193: "fgetxattr", - 194: "listxattr", - 195: "llistxattr", - 196: "flistxattr", - 197: "removexattr", - 198: "lremovexattr", - 199: "fremovexattr", - 200: "tkill", - 201: "time", - 202: "futex", - 203: "sched_setaffinity", - 204: "sched_getaffinity", - 205: "set_thread_area", - 206: "io_setup", - 207: "io_destroy", - 208: "io_getevents", - 209: "io_submit", - 210: "io_cancel", - 211: "get_thread_area", - 212: "lookup_dcookie", - 213: "epoll_create", - 214: "epoll_ctl_old", - 215: "epoll_wait_old", - 216: "remap_file_pages", - 217: "getdents64", - 218: "set_tid_address", - 219: "restart_syscall", - 220: "semtimedop", - 221: "fadvise64", - 222: "timer_create", - 223: "timer_settime", - 224: "timer_gettime", - 225: "timer_getoverrun", - 226: "timer_delete", - 227: "clock_settime", - 228: "clock_gettime", - 229: "clock_getres", - 230: "clock_nanosleep", - 231: "exit_group", - 232: "epoll_wait", - 233: "epoll_ctl", - 234: "tgkill", - 235: "utimes", - 236: "vserver", - 237: "mbind", - 238: "set_mempolicy", - 239: "get_mempolicy", - 240: "mq_open", - 241: "mq_unlink", - 242: "mq_timedsend", - 243: "mq_timedreceive", - 244: "mq_notify", - 245: "mq_getsetattr", - 246: "kexec_load", - 247: "waitid", - 248: "add_key", - 249: "request_key", - 250: "keyctl", - 251: "ioprio_set", - 252: "ioprio_get", - 253: "inotify_init", - 254: "inotify_add_watch", - 255: "inotify_rm_watch", - 256: "migrate_pages", - 257: "openat", - 258: "mkdirat", - 259: "mknodat", - 260: "fchownat", - 261: "futimesat", - 262: "newfstatat", - 263: "unlinkat", - 264: "renameat", - 265: "linkat", - 266: "symlinkat", - 267: "readlinkat", - 268: "fchmodat", - 269: "faccessat", - 270: "pselect6", - 271: "ppoll", - 272: "unshare", - 273: "set_robust_list", - 274: "get_robust_list", - 275: "splice", - 276: "tee", - 277: "sync_file_range", - 278: "vmsplice", - 279: "move_pages", - 280: "utimensat", - 281: "epoll_pwait", - 282: "signalfd", - 283: "timerfd", - 284: "eventfd", - 285: "fallocate", + 100: "times", + 101: "ptrace", + 102: "getuid", + 103: "syslog", + 104: "getgid", + 105: "setuid", + 106: "setgid", + 107: "geteuid", + 108: "getegid", + 109: "setpgid", + 110: "getppid", + 111: "getpgrp", + 112: "setsid", + 113: "setreuid", + 114: "setregid", + 115: "getgroups", + 116: "setgroups", + 117: "setresuid", + 118: "getresuid", + 119: "setresgid", + 120: "getresgid", + 121: "getpgid", + 122: "setfsuid", + 123: "setfsgid", + 124: "getsid", + 125: "capget", + 126: "capset", + 127: "rt_sigpending", + 128: "rt_sigtimedwait", + 129: "rt_sigqueueinfo", + 130: "rt_sigsuspend", + 131: "sigaltstack", + 132: "utime", + 133: "mknod", + 134: "uselib", + 135: "personality", + 136: "ustat", + 137: "statfs", + 138: "fstatfs", + 139: "sysfs", + 140: "getpriority", + 141: "setpriority", + 142: "sched_setparam", + 143: "sched_getparam", + 144: "sched_setscheduler", + 145: "sched_getscheduler", + 146: "sched_get_priority_max", + 147: "sched_get_priority_min", + 148: "sched_rr_get_interval", + 149: "mlock", + 150: "munlock", + 151: "mlockall", + 152: "munlockall", + 153: "vhangup", + 154: "modify_ldt", + 155: "pivot_root", + 156: "_sysctl", + 157: "prctl", + 158: "arch_prctl", + 159: "adjtimex", + 160: "setrlimit", + 161: "chroot", + 162: "sync", + 163: "acct", + 164: "settimeofday", + 165: "mount", + 166: "umount2", + 167: "swapon", + 168: "swapoff", + 169: "reboot", + 170: "sethostname", + 171: "setdomainname", + 172: "iopl", + 173: "ioperm", + 174: "create_module", + 175: "init_module", + 176: "delete_module", + 177: "get_kernel_syms", + 178: "query_module", + 179: "quotactl", + 180: "nfsservctl", + 181: "getpmsg", + 182: "putpmsg", + 183: "afs_syscall", + 184: "tuxcall", + 185: "security", + 186: "gettid", + 187: "readahead", + 188: "setxattr", + 189: "lsetxattr", + 190: "fsetxattr", + 191: "getxattr", + 192: "lgetxattr", + 193: "fgetxattr", + 194: "listxattr", + 195: "llistxattr", + 196: "flistxattr", + 197: "removexattr", + 198: "lremovexattr", + 199: "fremovexattr", + 200: "tkill", + 201: "time", + 202: "futex", + 203: "sched_setaffinity", + 204: "sched_getaffinity", + 205: "set_thread_area", + 206: "io_setup", + 207: "io_destroy", + 208: "io_getevents", + 209: "io_submit", + 210: "io_cancel", + 211: "get_thread_area", + 212: "lookup_dcookie", + 213: "epoll_create", + 214: "epoll_ctl_old", + 215: "epoll_wait_old", + 216: "remap_file_pages", + 217: "getdents64", + 218: "set_tid_address", + 219: "restart_syscall", + 220: "semtimedop", + 221: "fadvise64", + 222: "timer_create", + 223: "timer_settime", + 224: "timer_gettime", + 225: "timer_getoverrun", + 226: "timer_delete", + 227: "clock_settime", + 228: "clock_gettime", + 229: "clock_getres", + 230: "clock_nanosleep", + 231: "exit_group", + 232: "epoll_wait", + 233: "epoll_ctl", + 234: "tgkill", + 235: "utimes", + 236: "vserver", + 237: "mbind", + 238: "set_mempolicy", + 239: "get_mempolicy", + 240: "mq_open", + 241: "mq_unlink", + 242: "mq_timedsend", + 243: "mq_timedreceive", + 244: "mq_notify", + 245: "mq_getsetattr", + 246: "kexec_load", + 247: "waitid", + 248: "add_key", + 249: "request_key", + 250: "keyctl", + 251: "ioprio_set", + 252: "ioprio_get", + 253: "inotify_init", + 254: "inotify_add_watch", + 255: "inotify_rm_watch", + 256: "migrate_pages", + 257: "openat", + 258: "mkdirat", + 259: "mknodat", + 260: "fchownat", + 261: "futimesat", + 262: "newfstatat", + 263: "unlinkat", + 264: "renameat", + 265: "linkat", + 266: "symlinkat", + 267: "readlinkat", + 268: "fchmodat", + 269: "faccessat", + 270: "pselect6", + 271: "ppoll", + 272: "unshare", + 273: "set_robust_list", + 274: "get_robust_list", + 275: "splice", + 276: "tee", + 277: "sync_file_range", + 278: "vmsplice", + 279: "move_pages", + 280: "utimensat", + 281: "epoll_pwait", + 282: "signalfd", + 283: "timerfd", + 284: "eventfd", + 285: "fallocate", } SOCKET_SYSCALL_NAMES = set(( @@ -295,4 +295,3 @@ "getsockname", "getpeername", "getsockopt", "setsockopt", "shutdown", )) - diff -Nru python-ptrace-0.7/ptrace/syscall/names.py python-ptrace-0.9.3/ptrace/syscall/names.py --- python-ptrace-0.7/ptrace/syscall/names.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/names.py 2017-02-10 11:38:50.000000000 +0000 @@ -10,4 +10,3 @@ else: SYSCALL_NAMES = {} SOCKET_SYSCALL_NAMES = set() - diff -Nru python-ptrace-0.7/ptrace/syscall/posix_arg.py python-ptrace-0.9.3/ptrace/syscall/posix_arg.py --- python-ptrace-0.7/ptrace/syscall/posix_arg.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/posix_arg.py 2017-02-10 11:41:08.000000000 +0000 @@ -10,9 +10,11 @@ (0x02000000, "PROT_GROWSUP"), ) + def formatMmapProt(argument): return formatBits(argument.value, MMAP_PROT_BITMASK, "PROT_NONE") + # From /usr/include/bits/mman.h (Ubuntu Feisty, i386) ACCESS_MODE_BITMASK = ( (1, "X_OK"), @@ -20,11 +22,13 @@ (4, "R_OK"), ) + def formatAccessMode(argument): return formatBits(argument.value, ACCESS_MODE_BITMASK, "F_OK") + # From /usr/include/bits/fcntl.h (Ubuntu Feisty, i386) -OPEN_MODE_BITMASK = ( +OPEN_MODE_BITMASK = [ (0o1, "O_WRONLY"), (0o2, "O_RDWR"), (0o100, "O_CREAT"), @@ -40,10 +44,25 @@ (0o200000, "O_DIRECTORY"), (0o400000, "O_NOFOLLOW"), (0o1000000, "O_NOATIME"), -) + (0o2000000, "O_CLOEXEC"), + (0o10000000, "O_PATH"), # Linux 2.6.39 + (0o20200000, "O_TMPFILE"), # Linux 3.11 +] + def formatOpenMode(argument): - return formatBits(int(argument.value), OPEN_MODE_BITMASK, "O_RDONLY", oct) + value = argument.value + flags = readBits(int(value), OPEN_MODE_BITMASK) + + # Add default access mode if neither of the others are present. + if not flags or flags[0] not in ("O_WRONLY", "O_RDWR"): + flags.insert(0, "O_RDONLY") + + text = "|".join(flags) + if value: + text = "%s (%s)" % (text, oct(argument.value)) + return text + CLONE_FLAGS_BITMASK = ( (0x00000100, "CLONE_VM"), @@ -67,6 +86,7 @@ (0x08000000, "CLONE_NEWIPC"), ) + def formatCloneFlags(argument): flags = argument.value bits = readBits(flags, CLONE_FLAGS_BITMASK) @@ -79,3 +99,9 @@ else: return str(flags) + +AT_FDCWD = -100 + + +def formatDirFd(value): + return "AT_FDCWD" if value == AT_FDCWD else str(value) diff -Nru python-ptrace-0.7/ptrace/syscall/posix_constants.py python-ptrace-0.9.3/ptrace/syscall/posix_constants.py --- python-ptrace-0.7/ptrace/syscall/posix_constants.py 2013-06-06 20:54:57.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/posix_constants.py 2017-02-10 11:38:49.000000000 +0000 @@ -1,5 +1,5 @@ from ptrace.syscall.socketcall_constants import ( - SOCKET_FAMILY, SOCKET_TYPE, SOCKET_PROTOCOL, + SOCKET_FAMILY, SOCKET_PROTOCOL, SETSOCKOPT_LEVEL, SETSOCKOPT_OPTNAME) SYSCALL_ARG_DICT = { @@ -51,7 +51,6 @@ }, "socket": { "domain": SOCKET_FAMILY, - "type": SOCKET_TYPE, "protocol": SOCKET_PROTOCOL, }, "getsockopt": { @@ -61,4 +60,3 @@ } SYSCALL_ARG_DICT["setsockopt"] = SYSCALL_ARG_DICT["getsockopt"] - diff -Nru python-ptrace-0.7/ptrace/syscall/prototypes.py python-ptrace-0.9.3/ptrace/syscall/prototypes.py --- python-ptrace-0.7/ptrace/syscall/prototypes.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/prototypes.py 2017-02-10 11:38:50.000000000 +0000 @@ -5,471 +5,1763 @@ # arch/um/sys-i386/sys_call_table.S ALIASES = { - "mmap": ("mmap2",), - "break": ("brk",), - "exit": ("exit_group",), - "fcntl": ("fcntl64",), + "brk": ("break",), + "fadvise64": ("posix_fadvise",), + "fstatat64": ("fstatat",), "getcwd": ("__getcwd",), + "mmap_pgoff": ("mmap", "mmap2",), + "pread64": ("pread",), + "prlimit64": ("prlimit",), + "pselect6": ("pselect",), + "pwrite64": ("pwrite",), } # Name of arguments containing a filename or a path -FILENAME_ARGUMENTS = set(("filename", "pathname")) +FILENAME_ARGUMENTS = set( + ("filename", "pathname", "path", "oldname", "newname", "old", "new")) + +DIRFD_ARGUMENTS = set(("dirfd", "olddirfd", "newdirfd")) SYSCALL_PROTOTYPES = { - "read": ("ssize_t", ( - ("unsigned int", "fd"), - ("char*", "buf"), - ("size_t", "count"), - )), - "write": ("ssize_t", ( - ("int", "fd"), - ("const char*", "buf"), - ("size_t", "count"), - )), - "open": ("long", ( - ("const char*", "filename"), - ("int", "mode"), - )), - "readlink": ("long", ( - ("const char*", "pathname"), - ("char*", "buf"), - ("int", "bufsize"), - )), + "accept": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int *", "addrlen"), + )), + "accept4": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int *", "addrlen"), + ("int", "flags"), + )), + "access": ("long", ( + ("const char *", "filename"), + ("int", "mode"), + )), + "acct": ("long", ( + ("const char *", "name"), + )), + "add_key": ("long", ( + ("const char *", "_type"), + ("const char *", "_description"), + ("const void *", "_payload"), + ("size_t", "plen"), + ("key_serial_t", "destringid"), + )), + "adjtimex": ("long", ( + ("struct timex *", "txc_p"), + )), + "alarm": ("long", ( + ("unsigned int", "seconds"), + )), + "bdflush": ("long", ( + ("int", "func"), + ("long", "data"), + )), + "bind": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int", "addrlen"), + )), + "bpf": ("long", ( + ("int", "cmd"), + ("union bpf_attr *", "attr"), + ("unsigned int", "size"), + )), + "brk": ("long", ( + ("unsigned long", "brk"), + )), + "capget": ("long", ( + ("cap_user_header_t", "header"), + ("cap_user_data_t", "dataptr"), + )), + "capset": ("long", ( + ("cap_user_header_t", "header"), + ("const cap_user_data_t", "data"), + )), + "chdir": ("long", ( + ("const char *", "filename"), + )), + "chmod": ("long", ( + ("const char *", "filename"), + ("umode_t", "mode"), + )), + "chown": ("long", ( + ("const char *", "filename"), + ("uid_t", "user"), + ("gid_t", "group"), + )), + "chown16": ("long", ( + ("const char *", "filename"), + ("old_uid_t", "user"), + ("old_gid_t", "group"), + )), + "chroot": ("long", ( + ("const char *", "filename"), + )), + "clock_adjtime": ("long", ( + ("clockid_t", "which_clock"), + ("struct timex *", "tx"), + )), + "clock_getres": ("long", ( + ("clockid_t", "which_clock"), + ("struct timespec *", "tp"), + )), + "clock_gettime": ("long", ( + ("clockid_t", "which_clock"), + ("struct timespec *", "tp"), + )), + "clock_nanosleep": ("long", ( + ("clockid_t", "which_clock"), + ("int", "flags"), + ("const struct timespec *", "rqtp"), + ("struct timespec *", "rmtp"), + )), + "clock_settime": ("long", ( + ("clockid_t", "which_clock"), + ("const struct timespec *", "tp"), + )), + "clone": ("long", ( + ("unsigned long", "flags"), + ("unsigned long", "child_stack"), + ("int *", "ptid"), + ("int *", "ctid"), + ("unsigned long", "regs"), + )), "close": ("long", ( - ("unsigned int", "fd"), - )), - "set_tid_address": ("long", ( - ("int*", "tidptr"), - )), - "set_robust_list": ("long", ( - ("struct robust_list_head*", "head"), - ("size_t", "len_ptr"), - )), + ("unsigned int", "fd"), + )), + "connect": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int", "addrlen"), + )), + "copy_file_range": ("long", ( + ("int", "fd_in"), + ("loff_t *", "off_in"), + ("int", "fd_out"), + ("loff_t *", "off_out"), + ("size_t", "len"), + ("unsigned int", "flags"), + )), + "creat": ("long", ( + ("const char *", "pathname"), + ("umode_t", "mode"), + )), + "delete_module": ("long", ( + ("const char *", "name_user"), + ("unsigned int", "flags"), + )), + "dup": ("long", ( + ("unsigned int", "fildes"), + )), + "dup2": ("long", ( + ("unsigned int", "oldfd"), + ("unsigned int", "newfd"), + )), + "dup3": ("long", ( + ("unsigned int", "oldfd"), + ("unsigned int", "newfd"), + ("int", "flags"), + )), + "epoll_create": ("long", ( + ("int", "size"), + )), + "epoll_create1": ("long", ( + ("int", "flags"), + )), + "epoll_ctl": ("long", ( + ("int", "epfd"), + ("int", "op"), + ("int", "fd"), + ("struct epoll_event *", "event"), + )), + "epoll_pwait": ("long", ( + ("int", "epfd"), + ("struct epoll_event *", "events"), + ("int", "maxevents"), + ("int", "timeout"), + ("const sigset_t *", "sigmask"), + ("size_t", "sigsetsize"), + )), + "epoll_wait": ("long", ( + ("int", "epfd"), + ("struct epoll_event *", "events"), + ("int", "maxevents"), + ("int", "timeout"), + )), + "eventfd": ("long", ( + ("unsigned int", "count"), + )), + "eventfd2": ("long", ( + ("unsigned int", "count"), + ("int", "flags"), + )), + "execve": ("long", ( + ("const char *", "filename"), + ("const char *const *", "argv"), + ("const char *const *", "envp"), + )), + "execveat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("const char *const *", "argv"), + ("const char *const *", "envp"), + ("int", "flags"), + )), + "exit": ("long", ( + ("int", "error_code"), + )), + "exit_group": ("long", ( + ("int", "error_code"), + )), + "faccessat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("int", "mode"), + )), + "fadvise64": ("long", ( + ("int", "fd"), + ("loff_t", "offset"), + ("size_t", "len"), + ("int", "advice"), + )), + "fadvise64_64": ("long", ( + ("int", "fd"), + ("loff_t", "offset"), + ("loff_t", "len"), + ("int", "advice"), + )), + "fallocate": ("long", ( + ("int", "fd"), + ("int", "mode"), + ("loff_t", "offset"), + ("loff_t", "len"), + )), + "fanotify_init": ("long", ( + ("unsigned int", "flags"), + ("unsigned int", "event_f_flags"), + )), + "fanotify_mark": ("long", ( + ("int", "fanotify_fd"), + ("unsigned int", "flags"), + ("u64", "mask"), + ("int", "fd"), + ("const char *", "pathname"), + )), + "fchdir": ("long", ( + ("unsigned int", "fd"), + )), + "fchmod": ("long", ( + ("unsigned int", "fd"), + ("umode_t", "mode"), + )), + "fchmodat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("umode_t", "mode"), + )), + "fchown": ("long", ( + ("unsigned int", "fd"), + ("uid_t", "user"), + ("gid_t", "group"), + )), + "fchown16": ("long", ( + ("unsigned int", "fd"), + ("old_uid_t", "user"), + ("old_gid_t", "group"), + )), + "fchownat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("uid_t", "user"), + ("gid_t", "group"), + ("int", "flag"), + )), "fcntl": ("long", ( - ("unsigned int", "fd"), - ("unsigned int", "cmd"), - ("unsigned int", "arg"), - )), - "stat": ("long", ( - ("const char*", "filename"), - ("struct oldstat*", "statbuf"), - )), - "stat64": ("long", ( - ("const char*", "filename"), - ("struct stat64*", "statbuf"), - )), - "lstat": ("long", ( - ("const char*", "filename"), - ("struct oldstat*", "statbuf"), - )), - "lstat64": ("long", ( - ("const char*", "filename"), - ("struct stat64*", "statbuf"), - )), + ("unsigned int", "fd"), + ("unsigned int", "cmd"), + ("unsigned long", "arg"), + )), + "fcntl64": ("long", ( + ("unsigned int", "fd"), + ("unsigned int", "cmd"), + ("unsigned long", "arg"), + )), + "fdatasync": ("long", ( + ("unsigned int", "fd"), + )), + "fgetxattr": ("long", ( + ("int", "fd"), + ("const char *", "name"), + ("void *", "value"), + ("size_t", "size"), + )), + "finit_module": ("long", ( + ("int", "fd"), + ("const char *", "uargs"), + ("int", "flags"), + )), + "flistxattr": ("long", ( + ("int", "fd"), + ("char *", "list"), + ("size_t", "size"), + )), + "flock": ("long", ( + ("unsigned int", "fd"), + ("unsigned int", "cmd"), + )), + "fork": ("long", ( + )), + "fremovexattr": ("long", ( + ("int", "fd"), + ("const char *", "name"), + )), + "fsetxattr": ("long", ( + ("int", "fd"), + ("const char *", "name"), + ("const void *", "value"), + ("size_t", "size"), + ("int", "flags"), + )), "fstat": ("long", ( - ("unsigned int", "fd"), - ("struct oldstat*", "statbuf"), - )), + ("unsigned int", "fd"), + ("struct __old_kernel_stat *", "statbuf"), + )), "fstat64": ("long", ( - ("unsigned long", "fd"), - ("struct stat64*", "buf"), - )), + ("unsigned long", "fd"), + ("struct stat64 *", "statbuf"), + )), "fstatat64": ("long", ( - ("unsigned long", "dirfd"), - ("const char*", "filename"), - ("struct stat64*", "statbuf"), - ("int", "flags"), - )), - "statfs": ("long", ( - ("const char*", "pathname"), - ("struct statfs*", "buf"), - )), + ("int", "dfd"), + ("const char *", "filename"), + ("struct stat64 *", "statbuf"), + ("int", "flag"), + )), "fstatfs": ("long", ( - ("int", "fs"), - ("struct statfs*", "buf"), - )), - "access": ("long", ( - ("char*", "filename"), - ("int", "mode"), - )), - "lseek": ("long", ( - ("unsigned int", "fd"), - ("unsigned long", "offset"), - ("loff_t*", "result"), - ("unsigned int", "origin"), - )), + ("unsigned int", "fd"), + ("struct statfs *", "buf"), + )), + "fstatfs64": ("long", ( + ("unsigned int", "fd"), + ("size_t", "sz"), + ("struct statfs64 *", "buf"), + )), + "fsync": ("long", ( + ("unsigned int", "fd"), + )), + "ftruncate": ("long", ( + ("unsigned int", "fd"), + ("unsigned long", "length"), + )), + "ftruncate64": ("long", ( + ("unsigned int", "fd"), + ("loff_t", "length"), + )), + "futex": ("long", ( + ("u32 *", "uaddr"), + ("int", "op"), + ("u32", "val"), + ("struct timespec *", "utime"), + ("u32 *", "uaddr2"), + ("u32", "val3"), + )), + "futimesat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("struct timeval *", "utimes"), + )), + "get_mempolicy": ("long", ( + ("int *", "policy"), + ("unsigned long *", "nmask"), + ("unsigned long", "maxnode"), + ("unsigned long", "addr"), + ("unsigned long", "flags"), + )), + "get_robust_list": ("long", ( + ("int", "pid"), + ("struct robust_list_head * *", "head_ptr"), + ("size_t *", "len_ptr"), + )), + "getcpu": ("long", ( + ("unsigned *", "cpu"), + ("unsigned *", "node"), + ("struct getcpu_cache *", "cache"), + )), + "getcwd": ("long", ( + ("char *", "pathname"), + ("unsigned long", "size"), + )), + "getdents": ("long", ( + ("unsigned int", "fd"), + ("struct linux_dirent *", "dirent"), + ("unsigned int", "count"), + )), + "getdents64": ("long", ( + ("unsigned int", "fd"), + ("struct linux_dirent64 *", "dirent"), + ("unsigned int", "count"), + )), + "getegid": ("long", ( + )), + "getegid16": ("long", ( + )), + "geteuid": ("long", ( + )), + "geteuid16": ("long", ( + )), + "getgid": ("long", ( + )), + "getgid16": ("long", ( + )), + "getgroups": ("long", ( + ("int", "gidsetsize"), + ("gid_t *", "grouplist"), + )), + "getgroups16": ("long", ( + ("int", "gidsetsize"), + ("old_gid_t *", "grouplist"), + )), + "gethostname": ("long", ( + ("char *", "name"), + ("int", "len"), + )), + "getitimer": ("long", ( + ("int", "which"), + ("struct itimerval *", "value"), + )), + "getpeername": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int *", "addrlen"), + )), + "getpgid": ("long", ( + ("pid_t", "pid"), + )), + "getpgrp": ("long", ( + )), + "getpid": ("long", ( + )), + "getppid": ("long", ( + )), + "getpriority": ("long", ( + ("int", "which"), + ("int", "who"), + )), + "getrandom": ("long", ( + ("char *", "buf"), + ("size_t", "count"), + ("unsigned int", "flags"), + )), + "getresgid": ("long", ( + ("gid_t *", "rgid"), + ("gid_t *", "egid"), + ("gid_t *", "sgid"), + )), + "getresgid16": ("long", ( + ("old_gid_t *", "rgid"), + ("old_gid_t *", "egid"), + ("old_gid_t *", "sgid"), + )), + "getresuid": ("long", ( + ("uid_t *", "ruid"), + ("uid_t *", "euid"), + ("uid_t *", "suid"), + )), + "getresuid16": ("long", ( + ("old_uid_t *", "ruid"), + ("old_uid_t *", "euid"), + ("old_uid_t *", "suid"), + )), + "getrlimit": ("long", ( + ("unsigned int", "resource"), + ("struct rlimit *", "rlim"), + )), + "getrusage": ("long", ( + ("int", "who"), + ("struct rusage *", "ru"), + )), + "getsid": ("long", ( + ("pid_t", "pid"), + )), + "getsockname": ("long", ( + ("int", "sockfd"), + ("struct sockaddr *", "addr"), + ("int *", "addrlen"), + )), + "getsockopt": ("long", ( + ("int", "fd"), + ("int", "level"), + ("int", "optname"), + ("char *", "optval"), + ("int *", "optlen"), + )), + "gettid": ("long", ( + )), + "gettimeofday": ("long", ( + ("struct timeval *", "tv"), + ("struct timezone *", "tz"), + )), + "getuid": ("long", ( + )), + "getuid16": ("long", ( + )), + "getxattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + ("void *", "value"), + ("size_t", "size"), + )), + "init_module": ("long", ( + ("void *", "umod"), + ("unsigned long", "len"), + ("const char *", "uargs"), + )), + "inotify_add_watch": ("long", ( + ("int", "fd"), + ("const char *", "path"), + ("u32", "mask"), + )), + "inotify_init": ("long", ( + )), + "inotify_init1": ("long", ( + ("int", "flags"), + )), + "inotify_rm_watch": ("long", ( + ("int", "fd"), + ("__s32", "wd"), + )), + "io_cancel": ("long", ( + ("aio_context_t", "ctx_id"), + ("struct iocb *", "iocb"), + ("struct io_event *", "result"), + )), + "io_destroy": ("long", ( + ("aio_context_t", "ctx"), + )), + "io_getevents": ("long", ( + ("aio_context_t", "ctx_id"), + ("long", "min_nr"), + ("long", "nr"), + ("struct io_event *", "events"), + ("struct timespec *", "timeout"), + )), + "io_setup": ("long", ( + ("unsigned", "nr_reqs"), + ("aio_context_t *", "ctx"), + )), + "io_submit": ("long", ( + ("aio_context_t", "ctx_id"), + ("long", "nr"), + ("struct iocb * *", "iocbpp"), + )), + "ioctl": ("long", ( + ("unsigned int", "fd"), + ("unsigned int", "cmd"), + ("unsigned long", "arg"), + )), + "ioperm": ("long", ( + ("unsigned long", "from"), + ("unsigned long", "num"), + ("int", "on"), + )), + "ioprio_get": ("long", ( + ("int", "which"), + ("int", "who"), + )), + "ioprio_set": ("long", ( + ("int", "which"), + ("int", "who"), + ("int", "ioprio"), + )), + "ipc": ("long", ( + ("unsigned int", "call"), + ("int", "first"), + ("unsigned long", "second"), + ("unsigned long", "third"), + ("void *", "ptr"), + ("long", "fifth"), + )), + "kcmp": ("long", ( + ("pid_t", "pid1"), + ("pid_t", "pid2"), + ("int", "type"), + ("unsigned long", "idx1"), + ("unsigned long", "idx2"), + )), + "kexec_file_load": ("long", ( + ("int", "kernel_fd"), + ("int", "initrd_fd"), + ("unsigned long", "cmdline_len"), + ("const char *", "cmdline_ptr"), + ("unsigned long", "flags"), + )), + "kexec_load": ("long", ( + ("unsigned long", "entry"), + ("unsigned long", "nr_segments"), + ("struct kexec_segment *", "segments"), + ("unsigned long", "flags"), + )), + "keyctl": ("long", ( + ("int", "cmd"), + ("unsigned long", "arg2"), + ("unsigned long", "arg3"), + ("unsigned long", "arg4"), + ("unsigned long", "arg5"), + )), + "kill": ("long", ( + ("int", "pid"), + ("int", "sig"), + )), + "lchown": ("long", ( + ("const char *", "filename"), + ("uid_t", "user"), + ("gid_t", "group"), + )), + "lchown16": ("long", ( + ("const char *", "filename"), + ("old_uid_t", "user"), + ("old_gid_t", "group"), + )), + "lgetxattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + ("void *", "value"), + ("size_t", "size"), + )), + "link": ("long", ( + ("const char *", "oldname"), + ("const char *", "newname"), + )), + "linkat": ("long", ( + ("int", "olddfd"), + ("const char *", "oldname"), + ("int", "newdfd"), + ("const char *", "newname"), + ("int", "flags"), + )), + "listen": ("long", ( + ("int", "sockfd"), + ("int", "backlog"), + )), + "listxattr": ("long", ( + ("const char *", "path"), + ("char *", "list"), + ("size_t", "size"), + )), + "llistxattr": ("long", ( + ("const char *", "path"), + ("char *", "list"), + ("size_t", "size"), + )), "llseek": ("long", ( - ("unsigned int", "fd"), - ("unsigned long", "offset_high"), - ("unsigned long", "offset_low"), - ("loff_t*", "result"), - ("unsigned int", "origin"), - )), - "break": ("void*", ( - ("void*", "brk"), - )), - "sigprocmask": ("int", ( - ("int", "how"), - ("const old_sigset_t*", "set"), - ("old_sigset_t*", "ofset"), - )), - "rt_sigprocmask": ("int", ( - ("int", "how"), - ("const sigset_t*", "set"), - ("sigset_t*", "ofset"), - ("size_t", "sigsetsize"), - )), - "sigaction": ("long", ( - ("int", "signum"), - ("const struct oldsigaction*", "act"), - ("struct oldsigaction*", "oldact"), - )), + ("unsigned int", "fd"), + ("unsigned long", "offset_high"), + ("unsigned long", "offset_low"), + ("loff_t *", "result"), + ("unsigned int", "whence"), + )), + "lookup_dcookie": ("long", ( + ("u64", "cookie64"), + ("char *", "buf"), + ("size_t", "len"), + )), + "lremovexattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + )), + "lseek": ("long", ( + ("unsigned int", "fd"), + ("off_t", "offset"), + ("unsigned int", "whence"), + )), + "lsetxattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + ("const void *", "value"), + ("size_t", "size"), + ("int", "flags"), + )), + "lstat": ("long", ( + ("const char *", "filename"), + ("struct __old_kernel_stat *", "statbuf"), + )), + "lstat64": ("long", ( + ("const char *", "filename"), + ("struct stat64 *", "statbuf"), + )), + "madvise": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + ("int", "behavior"), + )), + "mbind": ("long", ( + ("unsigned long", "start"), + ("unsigned long", "len"), + ("unsigned long", "mode"), + ("const unsigned long *", "nmask"), + ("unsigned long", "maxnode"), + ("unsigned", "flags"), + )), + "membarrier": ("long", ( + ("int", "cmd"), + ("int", "flags"), + )), + "memfd_create": ("long", ( + ("const char *", "uname_ptr"), + ("unsigned int", "flags"), + )), + "migrate_pages": ("long", ( + ("pid_t", "pid"), + ("unsigned long", "maxnode"), + ("const unsigned long *", "from"), + ("const unsigned long *", "to"), + )), + "mincore": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + ("unsigned char *", "vec"), + )), + "mkdir": ("long", ( + ("const char *", "pathname"), + ("umode_t", "mode"), + )), + "mkdirat": ("long", ( + ("int", "dfd"), + ("const char *", "pathname"), + ("umode_t", "mode"), + )), + "mknod": ("long", ( + ("const char *", "filename"), + ("umode_t", "mode"), + ("unsigned", "dev"), + )), + "mknodat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("umode_t", "mode"), + ("unsigned", "dev"), + )), + "mlock": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + )), + "mlock2": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + ("int", "flags"), + )), + "mlockall": ("long", ( + ("int", "flags"), + )), + "mmap_pgoff": ("long", ( + ("unsigned long", "addr"), + ("unsigned long", "len"), + ("unsigned long", "prot"), + ("unsigned long", "flags"), + ("unsigned long", "fd"), + ("unsigned long", "pgoff"), + )), + "mount": ("long", ( + ("char *", "dev_name"), + ("char *", "dir_name"), + ("char *", "type"), + ("unsigned long", "flags"), + ("void *", "data"), + )), + "move_pages": ("long", ( + ("pid_t", "pid"), + ("unsigned long", "nr_pages"), + ("const void * *", "pages"), + ("const int *", "nodes"), + ("int *", "status"), + ("int", "flags"), + )), + "mprotect": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + ("unsigned long", "prot"), + )), + "mq_getsetattr": ("long", ( + ("mqd_t", "mqdes"), + ("const struct mq_attr *", "mqstat"), + ("struct mq_attr *", "omqstat"), + )), + "mq_notify": ("long", ( + ("mqd_t", "mqdes"), + ("const struct sigevent *", "notification"), + )), + "mq_open": ("long", ( + ("const char *", "name"), + ("int", "oflag"), + ("umode_t", "mode"), + ("struct mq_attr *", "attr"), + )), + "mq_timedreceive": ("long", ( + ("mqd_t", "mqdes"), + ("char *", "msg_ptr"), + ("size_t", "msg_len"), + ("unsigned int *", "msg_prio"), + ("const struct timespec *", "abs_timeout"), + )), + "mq_timedsend": ("long", ( + ("mqd_t", "mqdes"), + ("const char *", "msg_ptr"), + ("size_t", "msg_len"), + ("unsigned int", "msg_prio"), + ("const struct timespec *", "abs_timeout"), + )), + "mq_unlink": ("long", ( + ("const char *", "name"), + )), + "mremap": ("long", ( + ("unsigned long", "addr"), + ("unsigned long", "old_len"), + ("unsigned long", "new_len"), + ("unsigned long", "flags"), + ("unsigned long", "new_addr"), + )), + "msgctl": ("long", ( + ("int", "msqid"), + ("int", "cmd"), + ("struct msqid_ds *", "buf"), + )), + "msgget": ("long", ( + ("key_t", "key"), + ("int", "msgflg"), + )), + "msgrcv": ("long", ( + ("int", "msqid"), + ("struct msgbuf *", "msgp"), + ("size_t", "msgsz"), + ("long", "msgtyp"), + ("int", "msgflg"), + )), + "msgsnd": ("long", ( + ("int", "msqid"), + ("struct msgbuf *", "msgp"), + ("size_t", "msgsz"), + ("int", "msgflg"), + )), + "msync": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + ("int", "flags"), + )), + "munlock": ("long", ( + ("unsigned long", "start"), + ("size_t", "len"), + )), + "munlockall": ("long", ( + )), + "munmap": ("long", ( + ("unsigned long", "addr"), + ("size_t", "len"), + )), + "name_to_handle_at": ("long", ( + ("int", "dfd"), + ("const char *", "name"), + ("struct file_handle *", "handle"), + ("int *", "mnt_id"), + ("int", "flag"), + )), + "nanosleep": ("long", ( + ("struct timespec *", "rqtp"), + ("struct timespec *", "rmtp"), + )), + "newfstat": ("long", ( + ("unsigned int", "fd"), + ("struct stat *", "statbuf"), + )), + "newfstatat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("struct stat *", "statbuf"), + ("int", "flag"), + )), + "newlstat": ("long", ( + ("const char *", "filename"), + ("struct stat *", "statbuf"), + )), + "newstat": ("long", ( + ("const char *", "filename"), + ("struct stat *", "statbuf"), + )), + "newuname": ("long", ( + ("struct new_utsname *", "name"), + )), + "ni_syscall": ("long", ( + )), + "nice": ("long", ( + ("int", "increment"), + )), + "old_getrlimit": ("long", ( + ("unsigned int", "resource"), + ("struct rlimit *", "rlim"), + )), + "old_mmap": ("long", ( + ("struct mmap_arg_struct *", "arg"), + )), + "old_readdir": ("long", ( + ("unsigned int", "fd"), + ("struct old_linux_dirent *", "dirp"), + ("unsigned int", "count"), + )), + "old_select": ("long", ( + ("struct sel_arg_struct *", "arg"), + )), + "oldumount": ("long", ( + ("char *", "name"), + )), + "olduname": ("long", ( + ("struct oldold_utsname *", "buf"), + )), + "open": ("long", ( + ("const char *", "filename"), + ("int", "flags"), + ("umode_t", "mode"), + )), + "open_by_handle_at": ("long", ( + ("int", "mountdirfd"), + ("struct file_handle *", "handle"), + ("int", "flags"), + )), + "openat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("int", "flags"), + ("umode_t", "mode"), + )), + "pause": ("long", ( + )), + "pciconfig_iobase": ("long", ( + ("long", "which"), + ("unsigned long", "bus"), + ("unsigned long", "devfn"), + )), + "pciconfig_read": ("long", ( + ("unsigned long", "bus"), + ("unsigned long", "dfn"), + ("unsigned long", "off"), + ("unsigned long", "len"), + ("void *", "buf"), + )), + "pciconfig_write": ("long", ( + ("unsigned long", "bus"), + ("unsigned long", "dfn"), + ("unsigned long", "off"), + ("unsigned long", "len"), + ("void *", "buf"), + )), + "perf_event_open": ("long", ( + ("struct perf_event_attr *", "attr_uptr"), + ("pid_t", "pid"), + ("int", "cpu"), + ("int", "group_fd"), + ("unsigned long", "flags"), + )), + "personality": ("long", ( + ("unsigned int", "personality"), + )), + "pipe": ("long", ( + ("int *", "fildes"), + )), + "pipe2": ("long", ( + ("int *", "fildes"), + ("int", "flags"), + )), + "pivot_root": ("long", ( + ("const char *", "new_root"), + ("const char *", "put_old"), + )), + "poll": ("long", ( + ("struct pollfd *", "ufds"), + ("unsigned int", "nfds"), + ("int", "timeout"), + )), + "ppoll": ("long", ( + ("struct pollfd *", "fds"), + ("unsigned int", "nfds"), + ("struct timespec *", "tmo_p"), + ("const sigset_t *", "sigmask"), + ("size_t", ""), + )), + "prctl": ("long", ( + ("int", "option"), + ("unsigned long", "arg2"), + ("unsigned long", "arg3"), + ("unsigned long", "arg4"), + ("unsigned long", "arg5"), + )), + "pread64": ("long", ( + ("unsigned int", "fd"), + ("char *", "buf"), + ("size_t", "count"), + ("loff_t", "pos"), + )), + "preadv": ("long", ( + ("unsigned long", "fd"), + ("const struct iovec *", "vec"), + ("unsigned long", "vlen"), + ("unsigned long", "pos_l"), + ("unsigned long", "pos_h"), + )), + "prlimit64": ("long", ( + ("pid_t", "pid"), + ("unsigned int", "resource"), + ("const struct rlimit64 *", "new_rlim"), + ("struct rlimit64 *", "old_rlim"), + )), + "process_vm_readv": ("long", ( + ("pid_t", "pid"), + ("const struct iovec *", "lvec"), + ("unsigned long", "liovcnt"), + ("const struct iovec *", "rvec"), + ("unsigned long", "riovcnt"), + ("unsigned long", "flags"), + )), + "process_vm_writev": ("long", ( + ("pid_t", "pid"), + ("const struct iovec *", "lvec"), + ("unsigned long", "liovcnt"), + ("const struct iovec *", "rvec"), + ("unsigned long", "riovcnt"), + ("unsigned long", "flags"), + )), + "pselect6": ("long", ( + ("int", "nfds"), + ("fd_set *", "readfds"), + ("fd_set *", "writefds"), + ("fd_set *", "exceptfds"), + ("struct timespec *", "timeout"), + ("void *", "sigmask"), + )), + "ptrace": ("long", ( + ("long", "request"), + ("long", "pid"), + ("unsigned long", "addr"), + ("unsigned long", "data"), + )), + "pwrite64": ("long", ( + ("unsigned int", "fd"), + ("const char *", "buf"), + ("size_t", "count"), + ("loff_t", "pos"), + )), + "pwritev": ("long", ( + ("unsigned long", "fd"), + ("const struct iovec *", "vec"), + ("unsigned long", "vlen"), + ("unsigned long", "pos_l"), + ("unsigned long", "pos_h"), + )), + "quotactl": ("long", ( + ("unsigned int", "cmd"), + ("const char *", "special"), + ("qid_t", "id"), + ("void *", "addr"), + )), + "read": ("long", ( + ("unsigned int", "fd"), + ("char *", "buf"), + ("size_t", "count"), + )), + "readahead": ("long", ( + ("int", "fd"), + ("loff_t", "offset"), + ("size_t", "count"), + )), + "readlink": ("long", ( + ("const char *", "path"), + ("char *", "buf"), + ("int", "bufsiz"), + )), + "readlinkat": ("long", ( + ("int", "dfd"), + ("const char *", "path"), + ("char *", "buf"), + ("int", "bufsiz"), + )), + "readv": ("long", ( + ("unsigned long", "fd"), + ("const struct iovec *", "vec"), + ("unsigned long", "vlen"), + )), + "reboot": ("long", ( + ("int", "magic1"), + ("int", "magic2"), + ("unsigned int", "cmd"), + ("void *", "arg"), + )), + "recv": ("long", ( + ("int", "sockfd"), + ("void *", "buf"), + ("size_t", "len"), + ("unsigned", "flags"), + )), + "recvfrom": ("long", ( + ("int", "sockfd"), + ("void *", "buf"), + ("size_t", "len"), + ("unsigned", "flags"), + ("struct sockaddr *", "src_addr"), + ("int *", "addrlen"), + )), + "recvmmsg": ("long", ( + ("int", "fd"), + ("struct mmsghdr *", "msg"), + ("unsigned int", "vlen"), + ("unsigned", "flags"), + ("struct timespec *", "timeout"), + )), + "recvmsg": ("long", ( + ("int", "fd"), + ("struct user_msghdr *", "msg"), + ("unsigned", "flags"), + )), + "remap_file_pages": ("long", ( + ("unsigned long", "start"), + ("unsigned long", "size"), + ("unsigned long", "prot"), + ("unsigned long", "pgoff"), + ("unsigned long", "flags"), + )), + "removexattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + )), + "rename": ("long", ( + ("const char *", "oldname"), + ("const char *", "newname"), + )), + "renameat": ("long", ( + ("int", "olddfd"), + ("const char *", "oldname"), + ("int", "newdfd"), + ("const char *", "newname"), + )), + "renameat2": ("long", ( + ("int", "olddfd"), + ("const char *", "oldname"), + ("int", "newdfd"), + ("const char *", "newname"), + ("unsigned int", "flags"), + )), + "request_key": ("long", ( + ("const char *", "_type"), + ("const char *", "_description"), + ("const char *", "_callout_info"), + ("key_serial_t", "destringid"), + )), + "restart_syscall": ("long", ( + )), + "rmdir": ("long", ( + ("const char *", "pathname"), + )), "rt_sigaction": ("long", ( - # FIXME: Check parameters! - ("int", "signum"), - ("const struct sigaction*", "act"), - ("struct sigaction*", "oldact"), - ("int", "sigsetsize"), - )), + ("int", "signum"), + ("const struct sigaction *", "act"), + ("struct sigaction *", "oldact"), + ("size_t", ""), + )), + "rt_sigpending": ("long", ( + ("sigset_t *", "set"), + ("size_t", "sigsetsize"), + )), + "rt_sigprocmask": ("long", ( + ("int", "how"), + ("sigset_t *", "set"), + ("sigset_t *", "oset"), + ("size_t", "sigsetsize"), + )), + "rt_sigqueueinfo": ("long", ( + ("int", "pid"), + ("int", "sig"), + ("siginfo_t *", "uinfo"), + )), + "rt_sigsuspend": ("long", ( + ("sigset_t *", "unewset"), + ("size_t", "sigsetsize"), + )), + "rt_sigtimedwait": ("long", ( + ("const sigset_t *", "uthese"), + ("siginfo_t *", "uinfo"), + ("const struct timespec *", "uts"), + ("size_t", "sigsetsize"), + )), + "rt_tgsigqueueinfo": ("long", ( + ("pid_t", "tgid"), + ("pid_t", "pid"), + ("int", "sig"), + ("siginfo_t *", "uinfo"), + )), + "sched_get_priority_max": ("long", ( + ("int", "policy"), + )), + "sched_get_priority_min": ("long", ( + ("int", "policy"), + )), + "sched_getaffinity": ("long", ( + ("pid_t", "pid"), + ("unsigned int", "len"), + ("unsigned long *", "user_mask_ptr"), + )), + "sched_getattr": ("long", ( + ("pid_t", "pid"), + ("struct sched_attr *", "attr"), + ("unsigned int", "size"), + ("unsigned int", "flags"), + )), + "sched_getparam": ("long", ( + ("pid_t", "pid"), + ("struct sched_param *", "param"), + )), + "sched_getscheduler": ("long", ( + ("pid_t", "pid"), + )), + "sched_rr_get_interval": ("long", ( + ("pid_t", "pid"), + ("struct timespec *", "interval"), + )), + "sched_setaffinity": ("long", ( + ("pid_t", "pid"), + ("unsigned int", "len"), + ("unsigned long *", "user_mask_ptr"), + )), + "sched_setattr": ("long", ( + ("pid_t", "pid"), + ("struct sched_attr *", "attr"), + ("unsigned int", "flags"), + )), + "sched_setparam": ("long", ( + ("pid_t", "pid"), + ("struct sched_param *", "param"), + )), + "sched_setscheduler": ("long", ( + ("pid_t", "pid"), + ("int", "policy"), + ("struct sched_param *", "param"), + )), + "sched_yield": ("long", ( + )), + "seccomp": ("long", ( + ("unsigned int", "op"), + ("unsigned int", "flags"), + ("const char *", "uargs"), + )), "select": ("long", ( - ("int", "n"), - ("fd_set*", "inp"), - ("fd_set*", "outp"), - ("fd_set*", "exp"), - ("struct timeval*", "timeout"), - )), - "poll": ("long", ( - ("struct pollfd*", "ufds"), - ("int", "nfds"), - ("long", "timeout"), - )), - "gettimeofday": ("long", ( - ("struct timeval*", "tv"), - ("struct timezone*", "tz"), - )), + ("int", "n"), + ("fd_set *", "inp"), + ("fd_set *", "outp"), + ("fd_set *", "exp"), + ("struct timeval *", "tvp"), + )), + "semctl": ("long", ( + ("int", "semid"), + ("int", "semnum"), + ("int", "cmd"), + ("unsigned long", "arg"), + )), + "semget": ("long", ( + ("key_t", "key"), + ("int", "nsems"), + ("int", "semflg"), + )), + "semop": ("long", ( + ("int", "semid"), + ("struct sembuf *", "sops"), + ("unsigned", "nsops"), + )), + "semtimedop": ("long", ( + ("int", "semid"), + ("struct sembuf *", "sops"), + ("unsigned", "nsops"), + ("const struct timespec *", "timeout"), + )), + "send": ("long", ( + ("int", "sockfd"), + ("void *", "buf"), + ("size_t", "len"), + ("unsigned", "flags"), + )), + "sendfile": ("long", ( + ("int", "out_fd"), + ("int", "in_fd"), + ("off_t *", "offset"), + ("size_t", "count"), + )), + "sendfile64": ("long", ( + ("int", "out_fd"), + ("int", "in_fd"), + ("loff_t *", "offset"), + ("size_t", "count"), + )), + "sendmmsg": ("long", ( + ("int", "fd"), + ("struct mmsghdr *", "msg"), + ("unsigned int", "vlen"), + ("unsigned", "flags"), + )), + "sendmsg": ("long", ( + ("int", "fd"), + ("struct user_msghdr *", "msg"), + ("unsigned", "flags"), + )), + "sendto": ("long", ( + ("int", "sockfd"), + ("void *", "buf"), + ("size_t", "len"), + ("unsigned", "flags"), + ("struct sockaddr *", "dest_addr"), + ("int", "addrlen"), + )), + "set_mempolicy": ("long", ( + ("int", "mode"), + ("const unsigned long *", "nmask"), + ("unsigned long", "maxnode"), + )), + "set_robust_list": ("long", ( + ("struct robust_list_head *", "head"), + ("size_t", "len"), + )), + "set_tid_address": ("long", ( + ("int *", "tidptr"), + )), + "setdomainname": ("long", ( + ("char *", "name"), + ("int", "len"), + )), + "setfsgid": ("long", ( + ("gid_t", "gid"), + )), + "setfsgid16": ("long", ( + ("old_gid_t", "gid"), + )), + "setfsuid": ("long", ( + ("uid_t", "uid"), + )), + "setfsuid16": ("long", ( + ("old_uid_t", "uid"), + )), + "setgid": ("long", ( + ("gid_t", "gid"), + )), + "setgid16": ("long", ( + ("old_gid_t", "gid"), + )), + "setgroups": ("long", ( + ("int", "gidsetsize"), + ("gid_t *", "grouplist"), + )), + "setgroups16": ("long", ( + ("int", "gidsetsize"), + ("old_gid_t *", "grouplist"), + )), + "sethostname": ("long", ( + ("char *", "name"), + ("int", "len"), + )), + "setitimer": ("long", ( + ("int", "which"), + ("struct itimerval *", "value"), + ("struct itimerval *", "ovalue"), + )), + "setns": ("long", ( + ("int", "fd"), + ("int", "nstype"), + )), + "setpgid": ("long", ( + ("pid_t", "pid"), + ("pid_t", "pgid"), + )), + "setpriority": ("long", ( + ("int", "which"), + ("int", "who"), + ("int", "niceval"), + )), + "setregid": ("long", ( + ("gid_t", "rgid"), + ("gid_t", "egid"), + )), + "setregid16": ("long", ( + ("old_gid_t", "rgid"), + ("old_gid_t", "egid"), + )), + "setresgid": ("long", ( + ("gid_t", "rgid"), + ("gid_t", "egid"), + ("gid_t", "sgid"), + )), + "setresgid16": ("long", ( + ("old_gid_t", "rgid"), + ("old_gid_t", "egid"), + ("old_gid_t", "sgid"), + )), + "setresuid": ("long", ( + ("uid_t", "ruid"), + ("uid_t", "euid"), + ("uid_t", "suid"), + )), + "setresuid16": ("long", ( + ("old_uid_t", "ruid"), + ("old_uid_t", "euid"), + ("old_uid_t", "suid"), + )), + "setreuid": ("long", ( + ("uid_t", "ruid"), + ("uid_t", "euid"), + )), + "setreuid16": ("long", ( + ("old_uid_t", "ruid"), + ("old_uid_t", "euid"), + )), + "setrlimit": ("long", ( + ("unsigned int", "resource"), + ("struct rlimit *", "rlim"), + )), + "setsid": ("long", ( + )), + "setsockopt": ("long", ( + ("int", "fd"), + ("int", "level"), + ("int", "optname"), + ("char *", "optval"), + ("int", "optlen"), + )), "settimeofday": ("long", ( - ("struct timeval*", "tv"), - ("struct timezone*", "tz"), - )), + ("struct timeval *", "tv"), + ("struct timezone *", "tz"), + )), + "setuid": ("long", ( + ("uid_t", "uid"), + )), + "setuid16": ("long", ( + ("old_uid_t", "uid"), + )), + "setxattr": ("long", ( + ("const char *", "path"), + ("const char *", "name"), + ("const void *", "value"), + ("size_t", "size"), + ("int", "flags"), + )), + "sgetmask": ("long", ( + )), + "shmat": ("long", ( + ("int", "shmid"), + ("char *", "shmaddr"), + ("int", "shmflg"), + )), + "shmctl": ("long", ( + ("int", "shmid"), + ("int", "cmd"), + ("struct shmid_ds *", "buf"), + )), + "shmdt": ("long", ( + ("char *", "shmaddr"), + )), + "shmget": ("long", ( + ("key_t", "key"), + ("size_t", "size"), + ("int", "flag"), + )), + "shutdown": ("long", ( + ("int", "sockfd"), + ("int", "how"), + )), + "sigaction": ("long", ( + ("int", "signum"), + ("const struct old_sigaction *", "act"), + ("struct old_sigaction *", "oldact"), + )), + "sigaltstack": ("long", ( + ("const struct sigaltstack *", "uss"), + ("struct sigaltstack *", "uoss"), + )), + "signal": ("long", ( + ("int", "sig"), + ("__sighandler_t", "handler"), + )), + "signalfd": ("long", ( + ("int", "ufd"), + ("sigset_t *", "user_mask"), + ("size_t", "sizemask"), + )), + "signalfd4": ("long", ( + ("int", "ufd"), + ("sigset_t *", "user_mask"), + ("size_t", "sizemask"), + ("int", "flags"), + )), + "sigpending": ("long", ( + ("old_sigset_t *", "set"), + )), + "sigprocmask": ("long", ( + ("int", "how"), + ("old_sigset_t *", "set"), + ("old_sigset_t *", "oset"), + )), + "sigsuspend": ("long", ( + ("int", "unused1"), + ("int", "unused2"), + ("old_sigset_t", "mask"), + )), + "socket": ("long", ( + ("int", "domain"), + ("int", "type"), + ("int", "protocol"), + )), "socketcall": ("long", ( - ("int", "call"), - ("unsigned long*", "args"), - )), - "clock_gettime": ("long", ( - ("clockid_t", "which_clock"), - ("struct timespec*", "tp"), - )), - "clock_getres": ("long", ( - ("clockid_t", "which_clock"), - ("struct timespec*", "tp"), - )), - "time": ("time_t", ( - ("time_t*", "tloc"), - )), + ("int", "call"), + ("unsigned long *", "args"), + )), + "socketpair": ("long", ( + ("int", "domain"), + ("int", "type"), + ("int", "protocol"), + ("int *", "sv"), + )), + "splice": ("long", ( + ("int", "fd_in"), + ("loff_t *", "off_in"), + ("int", "fd_out"), + ("loff_t *", "off_out"), + ("size_t", "len"), + ("unsigned int", "flags"), + )), + "spu_create": ("long", ( + ("const char *", "name"), + ("unsigned int", "flags"), + ("umode_t", "mode"), + ("int", "fd"), + )), + "spu_run": ("long", ( + ("int", "fd"), + ("__u32 *", "unpc"), + ("__u32 *", "ustatus"), + )), + "ssetmask": ("long", ( + ("int", "newmask"), + )), + "stat": ("long", ( + ("const char *", "filename"), + ("struct __old_kernel_stat *", "statbuf"), + )), + "stat64": ("long", ( + ("const char *", "filename"), + ("struct stat64 *", "statbuf"), + )), + "statfs": ("long", ( + ("const char *", "path"), + ("struct statfs *", "buf"), + )), + "statfs64": ("long", ( + ("const char *", "path"), + ("size_t", "sz"), + ("struct statfs64 *", "buf"), + )), "stime": ("long", ( - ("time_t*", "tptr"), - )), - "munmap": ("long", ( - ("void*", "addr"), - ("size_t", "length"), - )), - "mmap": ("void*", ( - ("void*", "start"), - ("unsigned long", "length"), - ("unsigned long", "prot"), - ("long", "flags"), - ("long", "fd"), - ("unsigned long", "offset"), - )), - "madvise": ("long", ( - ("unsigned long", "start"), - ("size_t", "length"), - ("int", "behaviour"), - )), - "exit": ("void", ( - ("int", "error_code"), - )), - "futex": ("long", ( - ("u32*", "uaddr"), - ("int", "op"), - ("u32", "val"), - ("struct timespec*", "utime"), - ("u32*", "uaddr2"), - ("u32", "val3"), - )), - "ioctl": ("long", ( - ("unsigned int", "fd"), - ("unsigend int", "cmd"), - ("void*", "arg"), - )), - "getrusage": ("long", ( - ("int", "who"), - ("struct rusage*", "usage"), - )), - "times": ("clock_t", ( - ("struct tms*", "tbuf"), - )), - "mprotect": ("long", ( - ("void*", "start"), - ("size_t", "len"), - ("unsigned long", "prot"), - )), - "getrlimit": ("int", ( - ("unsigned int", "resource"), - ("struct rlimit*", "rlim"), - )), - "setrlimit": ("int", ( - ("unsigned int", "resource"), - ("struct rlimit*", "rlim"), - )), - - "getuid": ("uid_t", tuple()), - "geteuid": ("uid_t", tuple()), - "getuid16": ("uid16_t", tuple()), - "geteuid16": ("uid16_t", tuple()), - "issetugid": ("long", tuple()), - - "getgid": ("gid_t", tuple()), - "getegid": ("gid_t", tuple()), - "getgid16": ("gid16_t", tuple()), - "getegid16": ("gid16_t", tuple()), - - "getpid": ("pid_t", tuple()), - "getppid": ("pid_t", tuple()), - - "setuid": ("long", (("uid_t", "uid"),)), - "setreuid": ("long", (("uid_t", "uid"),)), - "setfsuid": ("long", (("uid_t", "uid"),)), - - "setgid": ("long", (("gid_t", "gid"),)), - "setregid": ("long", (("gid_t", "gid"),)), - "setfsgid": ("long", (("gid_t", "gid"),)), - - "getsid": ("long", (("pid_t", "pid"),)), - "setsid": ("long", tuple()), - - "pipe": ("int", ( - ("int[2]", "filedes"), - )), - "wait4": ("pid_t", ( - ("pid_t", "pid"), - ("int*", "status"), - ("int", "options"), - ("struct rusage*", "rusage"), - )), - "waitpid": ("pid_t", ( - ("pid_t", "pid"), - ("int*", "status"), - ("int", "options"), - )), - "set_thread_area": ("long", ( - ("struct user_desc*", "u_info"), - )), - "oldolduname": ("long", ( - ("struct oldold_utsname*", "name"), - )), - "olduname": ("long", ( - ("struct old_utsname*", "name"), - )), + ("time_t *", "tptr"), + )), + "swapoff": ("long", ( + ("const char *", "specialfile"), + )), + "swapon": ("long", ( + ("const char *", "specialfile"), + ("int", "swap_flags"), + )), + "symlink": ("long", ( + ("const char *", "old"), + ("const char *", "new"), + )), + "symlinkat": ("long", ( + ("const char *", "oldname"), + ("int", "newdfd"), + ("const char *", "newname"), + )), + "sync": ("long", ( + )), + "sync_file_range": ("long", ( + ("int", "fd"), + ("loff_t", "offset"), + ("loff_t", "nbytes"), + ("unsigned int", "flags"), + )), + "sync_file_range2": ("long", ( + ("int", "fd"), + ("unsigned int", "flags"), + ("loff_t", "offset"), + ("loff_t", "nbytes"), + )), + "syncfs": ("long", ( + ("int", "fd"), + )), + "sysctl": ("long", ( + ("struct __sysctl_args *", "args"), + )), + "sysfs": ("long", ( + ("int", "option"), + ("unsigned long", "arg1"), + ("unsigned long", "arg2"), + )), + "sysinfo": ("long", ( + ("struct sysinfo *", "info"), + )), + "syslog": ("long", ( + ("int", "type"), + ("char *", "buf"), + ("int", "len"), + )), + "tee": ("long", ( + ("int", "fdin"), + ("int", "fdout"), + ("size_t", "len"), + ("unsigned int", "flags"), + )), + "tgkill": ("long", ( + ("int", "tgid"), + ("int", "pid"), + ("int", "sig"), + )), + "time": ("long", ( + ("time_t *", "tloc"), + )), + "timer_create": ("long", ( + ("clockid_t", "which_clock"), + ("struct sigevent *", "timer_event_spec"), + ("timer_t *", "created_timer_id"), + )), + "timer_delete": ("long", ( + ("timer_t", "timer_id"), + )), + "timer_getoverrun": ("long", ( + ("timer_t", "timer_id"), + )), + "timer_gettime": ("long", ( + ("timer_t", "timer_id"), + ("struct itimerspec *", "setting"), + )), + "timer_settime": ("long", ( + ("timer_t", "timer_id"), + ("int", "flags"), + ("const struct itimerspec *", "new_setting"), + ("struct itimerspec *", "old_setting"), + )), + "timerfd_create": ("long", ( + ("int", "clockid"), + ("int", "flags"), + )), + "timerfd_gettime": ("long", ( + ("int", "ufd"), + ("struct itimerspec *", "otmr"), + )), + "timerfd_settime": ("long", ( + ("int", "ufd"), + ("int", "flags"), + ("const struct itimerspec *", "utmr"), + ("struct itimerspec *", "otmr"), + )), + "times": ("long", ( + ("struct tms *", "tbuf"), + )), + "tkill": ("long", ( + ("int", "pid"), + ("int", "sig"), + )), + "truncate": ("long", ( + ("const char *", "path"), + ("long", "length"), + )), + "truncate64": ("long", ( + ("const char *", "path"), + ("loff_t", "length"), + )), + "umask": ("long", ( + ("int", "mask"), + )), + "umount": ("long", ( + ("char *", "name"), + ("int", "flags"), + )), "uname": ("long", ( - ("struct new_utsname*", "name"), - )), - "clone": ("long", ( - ("int", "flags"), - ("void*", "child_stack"), - ("void*", "parent_tidptr"), - ("struct user_desc*", "newtls"), - ("void*", "child_tidptr"), - )), - "getcwd": ("long", ( - ("char*", "pathname"), - ("size_t", "size"), - )), - "dup2": ("long", ( - ("int", "fd"), - ("int", "fd2"), - )), - "fork": ("uid_t", tuple()), - "execve": ("long", ( - ("const char*", "filename"), - ("const char**", "argv"), - ("const char**", "envp"), - )), - "readv": ("ssize_t", ( - ("int", "fd"), - ("const iovec*", "vector"), - ("int", "count"), - )), - "writev": ("ssize_t", ( - ("int", "fd"), - ("const iovec*", "vector"), - ("int", "count"), - )), - "openat": ("long", ( - ("int", "dirfd"), - ("const char*", "pathname"), - ("int", "flags"), - ("int", "mode"), - )), - "getdents": ("long", ( - ("int", "fd"), - ("struct dirent*", "dirp"), - ("unsigned int", "count"), - )), - "getdents64": ("long", ( - ("int", "fd"), - ("struct dirent64*", "dirp"), - ("unsigned int", "count"), - )), - "dup": ("long", ( - ("int", "fd"), - )), - "dup2": ("long", ( - ("int", "oldfd"), - ("int", "newfd"), - )), - "fchdir": ("long", ( - ("int", "fd"), - )), - "getdirentries": ("long", ( - ("int", "fd"), - ("void*", "buf"), - ("int", "nbytes"), - ("long*", "basep"), - )), + ("struct old_utsname *", "buf"), + )), "unlink": ("long", ( - ("const char*", "pathname"), - )), - "unlinkat":("long", ( - ("int", "dirfd"), - ("const char*", "pathname"), - ("int", "flags"), - )), - "kill" : ("long", ( - ("int", "pid"), - ("int", "signum"), - )), - "modify_ldt" : ("long", ( - ("int", "func"), - ("void*", "ptr"), - ("unsigned long", "bytecount"), - )), - "ipc" : ("long", ( - ("unsigned int", "call"), - ("int", "first"), - ("unsigned long", "second"), - ("long", "third"), - ("void*", "ptr"), - ("long", "fifth"), - )), - "nanosleep" : ("long", ( - ("struct timespec*", "rqtp"), - ("struct timespec*", "rmtp"), - )), - "restart_syscall" : ("long", tuple()), - "getsockname" : ("long", ( - ("int", "fd"), - ("struct sockaddr*", "name"), - ("socklen_t*", "namelen"), - )), - "getpeername" : ("long", ( - ("int", "fd"), - ("struct sockaddr*", "name"), - ("socklen_t*", "namelen"), - )), - "getsockopt" : ("long", ( - ("int", "fd"), - ("int", "level"), - ("int", "optname"), - ("void*", "optval"), - ("socklen_t*", "optlen"), - )), - "setsockopt" : ("long", ( - ("int", "fd"), - ("int", "level"), - ("int", "optname"), - ("void*", "optval"), - ("socklen_t*", "optlen"), - )), - "bind" : ("long", ( - ("int", "fd"), - ("const struct sockaddr*", "addr"), - ("socklen_t", "addrlen"), - )), - "connect" : ("long", ( - ("int", "fd"), - ("const struct sockaddr*", "addr"), - ("socklen_t", "addrlen"), - )), - "socket" : ("long", ( - ("int", "domain"), - ("int", "type"), - ("int", "protocol"), - )), - "alarm" : ("long", ( - ("unsigned int", "seconds"), - )), - "recv": ("ssize_t", ( - ("int", "sockfd"), - ("void*", "buf"), - ("size_t", "len"), - ("int", "flags"), - )), - "recvfrom": ("ssize_t", ( - ("int", "sockfd"), - ("void*", "buf"), - ("size_t", "len"), - ("int", "flags"), - ("struct sockaddr*", "src_addr"), - ("socklen_t", "addrlen"), - )), - "recvmsg": ("ssize_t", ( - ("int", "sockfd"), - ("struct msghdr*", "msg"), - ("int", "flags"), - )), - "send": ("ssize_t", ( - ("int", "sockfd"), - ("const void*", "buf"), - ("size_t", "len"), - ("int", "flags"), - )), - "sendto": ("ssize_t", ( - ("int", "sockfd"), - ("const void*", "buf"), - ("size_t", "len"), - ("int", "flags"), - ("const struct sockaddr*", "dest_addr"), - ("socklen_t", "addrlen"), - )), - "sendmsg": ("ssize_t", ( - ("int", "sockfd"), - ("const struct msghdr*", "buf"), - ("int", "flags"), - )), - "listen": ("int", ( - ("int", "fd"), - ("int", "backlog"), - )), - "accept": ("int", ( - ("int", "fd"), - ("struct sockaddr*", "addr"), - ("socklen_t*", "addrlen"), - )), - "socketpair": ("int", ( - ("int", "domain"), - ("int", "type"), - ("int", "protocol"), - ("int*", "sockvec"), - )), - "shutdown": ("int", ( - ("int", "fd"), - ("int", "how"), - )), + ("const char *", "pathname"), + )), + "unlinkat": ("long", ( + ("int", "dfd"), + ("const char *", "pathname"), + ("int", "flag"), + )), + "unshare": ("long", ( + ("unsigned long", "unshare_flags"), + )), + "uselib": ("long", ( + ("const char *", "library"), + )), + "userfaultfd": ("long", ( + ("int", "flags"), + )), + "ustat": ("long", ( + ("unsigned", "dev"), + ("struct ustat *", "ubuf"), + )), + "utime": ("long", ( + ("char *", "filename"), + ("struct utimbuf *", "times"), + )), + "utimensat": ("long", ( + ("int", "dfd"), + ("const char *", "filename"), + ("struct timespec *", "utimes"), + ("int", "flags"), + )), + "utimes": ("long", ( + ("char *", "filename"), + ("struct timeval *", "utimes"), + )), + "vfork": ("long", ( + )), + "vhangup": ("long", ( + )), + "vmsplice": ("long", ( + ("int", "fd"), + ("const struct iovec *", "iov"), + ("unsigned long", "nr_segs"), + ("unsigned int", "flags"), + )), + "wait4": ("long", ( + ("pid_t", "pid"), + ("int *", "stat_addr"), + ("int", "options"), + ("struct rusage *", "ru"), + )), + "waitid": ("long", ( + ("int", "which"), + ("pid_t", "pid"), + ("struct siginfo *", "infop"), + ("int", "options"), + ("struct rusage *", "ru"), + )), + "waitpid": ("long", ( + ("pid_t", "pid"), + ("int *", "stat_addr"), + ("int", "options"), + )), + "write": ("long", ( + ("unsigned int", "fd"), + ("const char *", "buf"), + ("size_t", "count"), + )), + "writev": ("long", ( + ("unsigned long", "fd"), + ("const struct iovec *", "vec"), + ("unsigned long", "vlen"), + )), } for orig, copies in ALIASES.items(): orig = SYSCALL_PROTOTYPES[orig] for copy in copies: SYSCALL_PROTOTYPES[copy] = orig - diff -Nru python-ptrace-0.7/ptrace/syscall/ptrace_syscall.py python-ptrace-0.9.3/ptrace/syscall/ptrace_syscall.py --- python-ptrace-0.7/ptrace/syscall/ptrace_syscall.py 2014-03-05 13:43:43.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/ptrace_syscall.py 2017-02-10 11:38:51.000000000 +0000 @@ -1,4 +1,5 @@ from os import strerror +from errno import errorcode from ptrace.cpu_info import CPU_X86_64, CPU_POWERPC, CPU_I386, CPU_ARM from ptrace.ctypes_tools import ulong2long, formatAddress, formatWordHex @@ -9,13 +10,41 @@ from ptrace.cpu_info import CPU_WORD_SIZE from ptrace.binding.cpu import CPU_INSTR_POINTER +if CPU_POWERPC: + SYSCALL_REGISTER = "gpr0" +elif CPU_ARM: + SYSCALL_REGISTER = "r7" +elif RUNNING_LINUX: + if CPU_X86_64: + SYSCALL_REGISTER = "orig_rax" + else: + SYSCALL_REGISTER = "orig_eax" +else: + if CPU_X86_64: + SYSCALL_REGISTER = "rax" + else: + SYSCALL_REGISTER = "eax" + +if CPU_ARM: + RETURN_VALUE_REGISTER = "r0" +elif CPU_I386: + RETURN_VALUE_REGISTER = "eax" +elif CPU_X86_64: + RETURN_VALUE_REGISTER = "rax" +elif CPU_POWERPC: + RETURN_VALUE_REGISTER = "result" +else: + raise NotImplementedError("Unsupported CPU architecture") + PREFORMAT_ARGUMENTS = { "select": (2, 3, 4), "execve": (0, 1, 2), "clone": (0, 1), } + class PtraceSyscall(FunctionCall): + def __init__(self, process, options, regs=None): FunctionCall.__init__(self, "syscall", options, SyscallArgument) self.process = process @@ -47,23 +76,10 @@ def readSyscall(self, regs): # Read syscall number - if CPU_POWERPC: - self.syscall = regs.gpr0 - elif CPU_ARM: - self.syscall = regs.r7 - elif RUNNING_LINUX: - if CPU_X86_64: - self.syscall = regs.orig_rax - else: - self.syscall = regs.orig_eax - else: - if CPU_X86_64: - self.syscall = regs.rax - else: - self.syscall = regs.eax - + self.syscall = getattr(regs, SYSCALL_REGISTER) # Get syscall variables - self.name = SYSCALL_NAMES.get(self.syscall, "syscall<%s>" % self.syscall) + self.name = SYSCALL_NAMES.get( + self.syscall, "syscall<%s>" % self.syscall) def readArgumentValues(self, regs): if CPU_X86_64: @@ -72,8 +88,8 @@ return (regs.r0, regs.r1, regs.r2, regs.r3, regs.r4, regs.r5, regs.r6) if RUNNING_BSD: sp = self.process.getStackPointer() - return [ self.process.readWord(sp + index*CPU_WORD_SIZE) - for index in range(1, 6+1) ] + return [self.process.readWord(sp + index * CPU_WORD_SIZE) + for index in range(1, 6 + 1)] if CPU_I386: return (regs.ebx, regs.ecx, regs.edx, regs.esi, regs.edi, regs.ebp) if CPU_POWERPC: @@ -97,7 +113,7 @@ preformat = set() # Data pointed by arguments may have changed during the syscall - # eg. uname() syscall + # e.g. uname() syscall for index, argument in enumerate(self.arguments): if index in preformat: # Don't lose preformatted arguments @@ -106,26 +122,17 @@ continue argument.text = None - if CPU_ARM: - regname = "r0" - elif CPU_I386: - regname = "eax" - elif CPU_X86_64: - regname = "rax" - elif CPU_POWERPC: - regname = "result" - else: - raise NotImplementedError() - self.result = self.process.getreg(regname) + self.result = self.process.getreg(RETURN_VALUE_REGISTER) if self.restype.endswith("*"): text = formatAddress(self.result) else: uresult = self.result self.result = ulong2long(self.result) - if self.result < 0: - text = "%s (%s)" % ( - self.result, strerror(-self.result)) + if self.result < 0 and (-self.result) in errorcode: + errcode = -self.result + text = "%s %s (%s)" % ( + self.result, errorcode[errcode], strerror(errcode)) elif not(0 <= self.result <= 9): text = "%s (%s)" % (self.result, formatWordHex(uresult)) else: @@ -135,4 +142,3 @@ def __str__(self): return "" % self.name - diff -Nru python-ptrace-0.7/ptrace/syscall/socketcall_constants.py python-ptrace-0.9.3/ptrace/syscall/socketcall_constants.py --- python-ptrace-0.7/ptrace/syscall/socketcall_constants.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/socketcall_constants.py 2017-02-10 11:41:08.000000000 +0000 @@ -1,3 +1,5 @@ +import socket + SOCKETCALL = { 1: "socket", 2: "bind", @@ -19,16 +21,16 @@ } SOCKET_FAMILY = { - 0: "AF_UNSPEC", - 1: "AF_FILE", - 2: "AF_INET", - 3: "AF_AX25", - 4: "AF_IPX", - 5: "AF_APPLETALK", - 6: "AF_NETROM", - 7: "AF_BRIDGE", - 8: "AF_ATMPVC", - 9: "AF_X25", + 0: "AF_UNSPEC", + 1: "AF_FILE", + 2: "AF_INET", + 3: "AF_AX25", + 4: "AF_IPX", + 5: "AF_APPLETALK", + 6: "AF_NETROM", + 7: "AF_BRIDGE", + 8: "AF_ATMPVC", + 9: "AF_X25", 10: "AF_INET6", 11: "AF_ROSE", 12: "AF_DECnet", @@ -48,16 +50,31 @@ } SOCKET_TYPE = { - 1: "SOCK_STREAM", - 2: "SOCK_DGRAM", - 3: "SOCK_RAW", - 4: "SOCK_RDM", - 5: "SOCK_SEQPACKET", + 1: "SOCK_STREAM", + 2: "SOCK_DGRAM", + 3: "SOCK_RAW", + 4: "SOCK_RDM", + 5: "SOCK_SEQPACKET", 10: "SOCK_PACKET", } + +def formatSocketType(argument): + value = argument.value + text = [] + if hasattr(socket, 'SOCK_CLOEXEC'): + cloexec = value & socket.SOCK_CLOEXEC + value &= ~socket.SOCK_CLOEXEC + else: + cloexec = False + text = SOCKET_TYPE.get(value, str(value)) + if cloexec: + text += '|SOCK_CLOEXEC' + return text + + SOCKET_PROTOCOL = { - 1: "IPPROTO_ICMP", + 1: "IPPROTO_ICMP", 58: "IPPROTO_ICMPV6", } @@ -67,12 +84,11 @@ } SETSOCKOPT_OPTNAME = { - # level 0 (SOL_IP) - 1: "IP_TOS", - # level 1 (SOL_SOCKET) - 2: "SO_REUSEADDR", - 9: "SO_KEEPALIVE", + # level 0 (SOL_IP) + 1: "IP_TOS", + # level 1 (SOL_SOCKET) + 2: "SO_REUSEADDR", + 9: "SO_KEEPALIVE", 20: "SO_RCVTIMEO", 21: "SO_SNDTIMEO", } - diff -Nru python-ptrace-0.7/ptrace/syscall/socketcall.py python-ptrace-0.9.3/ptrace/syscall/socketcall.py --- python-ptrace-0.7/ptrace/syscall/socketcall.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/socketcall.py 2017-02-10 11:38:51.000000000 +0000 @@ -1,18 +1,18 @@ from ptrace.cpu_info import CPU_WORD_SIZE -from ptrace.ctypes_tools import ntoh_ushort, ntoh_uint +from ptrace.ctypes_tools import ntoh_ushort, ntoh_uint # noqa from ptrace.syscall import SYSCALL_PROTOTYPES -from ptrace.syscall.socketcall_constants import SOCKETCALL, SOCKET_FAMILY +from ptrace.syscall.socketcall_constants import SOCKETCALL, SOCKET_FAMILY # noqa from ptrace.syscall.socketcall_struct import sockaddr, sockaddr_in, sockaddr_in6, sockaddr_un from ctypes import c_int from ptrace.os_tools import RUNNING_LINUX -from socket import AF_INET, AF_INET6, inet_ntoa -from struct import pack +from socket import AF_INET, AF_INET6, inet_ntoa # noqa if RUNNING_LINUX: from socket import AF_NETLINK from ptrace.syscall.socketcall_struct import sockaddr_nl AF_FILE = 1 + def formatOptVal(argument): function = argument.function optlen = function["optlen"].value @@ -23,6 +23,7 @@ else: return None + def formatSockaddr(argument, argtype): address = argument.value value = argument.function.process.readStruct(address, sockaddr) @@ -39,6 +40,7 @@ family = SOCKET_FAMILY.get(family, family) return argument.formatPointer("" % family, address) + def setupSocketCall(function, process, socketcall, address): # Reset function call function.clearArguments() @@ -55,15 +57,16 @@ function.addArgument(value, argname, argtype) address += CPU_WORD_SIZE + def formatSockaddrInStruct(argument, name, value): if name == "sin_port": return ntoh_ushort(value) return None + def formatSockaddrIn6Struct(argument, name, value): if name == "sin6_port": return ntoh_ushort(value) - #if name == "sin6_addr": + # if name == "sin6_addr": # FIXME: ... return None - diff -Nru python-ptrace-0.7/ptrace/syscall/socketcall_struct.py python-ptrace-0.9.3/ptrace/syscall/socketcall_struct.py --- python-ptrace-0.7/ptrace/syscall/socketcall_struct.py 2013-06-06 20:54:57.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/socketcall_struct.py 2017-02-10 11:41:08.000000000 +0000 @@ -4,9 +4,10 @@ from struct import pack from ptrace.ctypes_tools import ntoh_uint, ntoh_ushort + def ip_int2str(ip): """ - Convert an IP address (as an interger) to a string. + Convert an IP address (as an integer) to a string. >>> ip_int2str(0x7f000001) '127.0.0.1' @@ -14,11 +15,13 @@ ip_bytes = pack("!I", ip) return inet_ntoa(ip_bytes) + if RUNNING_BSD: sa_family_t = c_ubyte else: sa_family_t = c_ushort + class sockaddr(Structure): if RUNNING_BSD: _fields_ = ( @@ -30,6 +33,7 @@ ("family", sa_family_t), ) + class in_addr(Structure): _fields_ = ( ("s_addr", c_uint32), @@ -39,6 +43,7 @@ ip = ntoh_uint(self.s_addr) return ip_int2str(ip) + class in6_addr(Union): _fields_ = ( ("addr8", c_ubyte * 16), @@ -51,6 +56,8 @@ return "" % text # INET socket + + class sockaddr_in(Structure): if RUNNING_BSD: _fields_ = ( @@ -66,6 +73,7 @@ ("sin_addr", in_addr), ) + class sockaddr_in6(Structure): if RUNNING_BSD: _fields_ = ( @@ -85,12 +93,15 @@ ) # UNIX socket + + class sockaddr_un(Structure): _fields_ = ( ("sun_family", sa_family_t), - ("sun_path", c_char*108), + ("sun_path", c_char * 108), ) + # Netlink socket if RUNNING_LINUX: class sockaddr_nl(Structure): @@ -100,4 +111,3 @@ ("nl_pid", c_uint32), ("nl_groups", c_uint32), ) - diff -Nru python-ptrace-0.7/ptrace/syscall/syscall_argument.py python-ptrace-0.9.3/ptrace/syscall/syscall_argument.py --- python-ptrace-0.7/ptrace/syscall/syscall_argument.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/syscall/syscall_argument.py 2017-02-10 11:38:49.000000000 +0000 @@ -6,14 +6,17 @@ from logging import getLogger, INFO from ptrace.func_arg import FunctionArgument from ptrace.syscall.posix_arg import ( - formatMmapProt, formatAccessMode, formatOpenMode, formatCloneFlags) + formatMmapProt, formatAccessMode, formatOpenMode, formatCloneFlags, formatDirFd) from ptrace.func_call import FunctionCall from ptrace.syscall.socketcall import (setupSocketCall, - formatOptVal, formatSockaddr, formatSockaddrInStruct, formatSockaddrIn6Struct) + formatOptVal, formatSockaddr, formatSockaddrInStruct, formatSockaddrIn6Struct) from ptrace.syscall.socketcall_constants import SOCKETCALL +import os import re +from ptrace import six from ptrace.os_tools import RUNNING_LINUX, RUNNING_FREEBSD -from ptrace.syscall import FILENAME_ARGUMENTS +from ptrace.syscall import FILENAME_ARGUMENTS, DIRFD_ARGUMENTS +from ptrace.syscall.socketcall_constants import formatSocketType if RUNNING_LINUX: from ptrace.syscall.linux_struct import ( timeval, timespec, pollfd, rlimit, new_utsname, user_desc) @@ -25,16 +28,19 @@ KNOWN_STRUCTS = [] if RUNNING_LINUX: - KNOWN_STRUCTS.extend((timeval, timespec, pollfd, rlimit, new_utsname, user_desc)) -KNOWN_STRUCTS = dict( (struct.__name__, struct) for struct in KNOWN_STRUCTS ) + KNOWN_STRUCTS.extend( + (timeval, timespec, pollfd, rlimit, new_utsname, user_desc)) +KNOWN_STRUCTS = dict((struct.__name__, struct) for struct in KNOWN_STRUCTS) ARGUMENT_CALLBACK = { # Prototype: callback(argument) -> str "access": {"mode": formatAccessMode}, - "open": {"mode": formatOpenMode}, + "open": {"flags": formatOpenMode, "mode": formatOpenMode}, + "openat": {"flags": formatOpenMode, "mode": formatOpenMode}, "mmap": {"prot": formatMmapProt}, "mmap2": {"prot": formatMmapProt}, "clone": {"flags": formatCloneFlags}, + "socket": {"type": formatSocketType}, "setsockopt": {"optval": formatOptVal}, } @@ -54,13 +60,16 @@ "socklen_t", "pid_t", "uid_t", "gid_t", )) + def iterBits(data): for char in data: byte = ord(char) for index in range(8): yield ((byte >> index) & 1) == 1 + class SyscallArgument(FunctionArgument): + def createText(self): value = self.value argtype = self.type @@ -92,7 +101,8 @@ return str(value) if name == "args": func_call = FunctionCall("socketcall", self.options) - setupSocketCall(func_call, self.function.process, self.function[0], self.value) + setupSocketCall(func_call, self.function.process, + self.function[0], self.value) text = "<%s>" % func_call.format() return self.formatPointer(text, self.value) if syscall == "write" and name == "buf": @@ -102,13 +112,16 @@ return self.readString(value, length) if name == "signum": return signalName(value) - if name in FILENAME_ARGUMENTS: - return self.readCString(value) + if name in DIRFD_ARGUMENTS and argtype == "int": + return formatDirFd(uint2int(value)) # Remove "const " prefix if argtype.startswith("const "): argtype = argtype[6:] + if name in FILENAME_ARGUMENTS and argtype == "char *": + return self.readCString(value) + # Format depending on the type if argtype.endswith("*"): try: @@ -116,7 +129,8 @@ if text: return text except PTRACE_ERRORS as err: - writeError(getLogger(), err, "Warning: Format %r value error" % self, log_level=INFO) + writeError( + getLogger(), err, "Warning: Format %r value error" % self, log_level=INFO) return formatAddress(self.value) # Array like "int[2]" @@ -165,6 +179,7 @@ syscall = self.function.name if syscall == "rt_sigprocmask" and argtype == "sigset_t": size = self.function["sigsetsize"].value * 8 + def formatter(key): key += 1 return signalName(key) @@ -173,33 +188,43 @@ return None def readBits(self, address, count, format=str): - bytes = self.function.process.readBytes(address, count//8) - fd_set = [ format(index) for index, bit in enumerate(iterBits(bytes)) if bit ] + bytes = self.function.process.readBytes(address, count // 8) + fd_set = [format(index) + for index, bit in enumerate(iterBits(bytes)) if bit] return ", ".join(fd_set) def readCString(self, address): if address: max_size = self.options.string_max_length - char, truncated = self.function.process.readCString(address, max_size) - char = repr(char) + data, truncated = self.function.process.readCString( + address, max_size) + if six.PY3: + text = os.fsdecode(data) + else: + text = data + text = repr(text) if truncated: - char += "..." + text += "..." else: - char = "NULL" - return self.formatPointer(char, address) + text = "NULL" + return self.formatPointer(text, address) def readString(self, address, size): if address: max_len = self.options.string_max_length truncated = (max_len < size) size = min(size, max_len) - bytes = self.function.process.readBytes(address, size) - bytes = repr(bytes) + data = self.function.process.readBytes(address, size) + if six.PY3: + text = os.fsdecode(data) + else: + text = data + text = repr(text) if truncated: - bytes += "..." + text += "..." else: - bytes = "NULL" - return self.formatPointer(bytes, address) + text = "NULL" + return self.formatPointer(text, address) def readCStringArray(self, address): if not address: @@ -224,4 +249,3 @@ callback = STRUCT_CALLBACK[struct] return callback(self, name, value) return None - diff -Nru python-ptrace-0.7/ptrace/terminal.py python-ptrace-0.9.3/ptrace/terminal.py --- python-ptrace-0.7/ptrace/terminal.py 2014-03-05 13:18:36.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/terminal.py 2017-02-10 11:38:51.000000000 +0000 @@ -10,18 +10,21 @@ TERMIO_LFLAGS = 3 + def _terminalSize(): fd = stdout.fileno() size = ioctl(fd, TIOCGWINSZ, '1234') height, width = unpack('hh', size) return (width, height) + def terminalWidth(): """ Get the terminal width in characters. """ return _terminalSize()[0] + def enableEchoMode(): """ Enable echo mode in the terminal. Return True if the echo mode is set @@ -36,5 +39,3 @@ state[TERMIO_LFLAGS] = state[TERMIO_LFLAGS] | ECHO tcsetattr(fd, TCSADRAIN, state) return True - - diff -Nru python-ptrace-0.7/ptrace/tools.py python-ptrace-0.9.3/ptrace/tools.py --- python-ptrace-0.7/ptrace/tools.py 2014-03-05 13:37:26.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/tools.py 2017-02-10 11:41:08.000000000 +0000 @@ -4,11 +4,12 @@ from os import getenv, access, X_OK, pathsep, getcwd from os.path import join as path_join, isabs, dirname, normpath + def dumpRegs(log, regs): """ Dump all registers using log callback (write one line). """ - width = max( len(name) for name, type in regs._fields_ ) + width = max(len(name) for name, type in regs._fields_) name_format = "%% %us" % width for name, type in regs._fields_: value = getattr(regs, name) @@ -21,6 +22,7 @@ value = formatWordHex(value) log("%s = %s" % (name, value)) + def readBits(value, bitmasks): """ Extract bits from the integer value using a list of bit masks. @@ -33,6 +35,8 @@ ... >>> readBits(5, bitmask) ['exec', 'read'] + >>> readBits(12, bitmask) + ['read', '8'] """ bitset = [] for mask, item in bitmasks: @@ -40,8 +44,11 @@ continue bitset.append(item) value = value & ~mask + if value: + bitset.append(str(value)) return bitset + def formatBits(value, bitmasks, empty_text=None, format_value=str): """ Format a value using a bitmask: see readBits() functions. @@ -70,11 +77,14 @@ else: return str(value) -LOCAL_TIMEZONE_OFFSET = datetime.fromtimestamp(0) - datetime.utcfromtimestamp(0) + +LOCAL_TIMEZONE_OFFSET = datetime.fromtimestamp( + 0) - datetime.utcfromtimestamp(0) # Start of UNIX timestamp (Epoch): 1st January 1970 at 00:00 UNIX_TIMESTAMP_T0 = datetime(1970, 1, 1) + def timestampUNIX(value, is_local): """ Convert an UNIX (32-bit) timestamp to datetime object. Timestamp value @@ -93,6 +103,7 @@ timestamp += LOCAL_TIMEZONE_OFFSET return timestamp + def locateProgram(program): """ Locate a program using the PATH environment variable. Return the @@ -116,6 +127,7 @@ return filename return program + def minmax(min_value, value, max_value): """ Restrict value to [min_value; max_value] @@ -129,6 +141,7 @@ """ return min(max(min_value, value), max_value) + def inverseDict(data): """ Inverse a dictionary. @@ -140,4 +153,3 @@ for key, value in data.items(): result[value] = key return result - diff -Nru python-ptrace-0.7/ptrace/version.py python-ptrace-0.9.3/ptrace/version.py --- python-ptrace-0.7/ptrace/version.py 2014-01-03 00:56:18.000000000 +0000 +++ python-ptrace-0.9.3/ptrace/version.py 2017-02-12 18:08:34.000000000 +0000 @@ -1,4 +1,4 @@ PACKAGE = "python-ptrace" -VERSION = "0.7" -WEBSITE = "http://bitbucket.org/haypo/python-ptrace/wiki/Home" +VERSION = "0.9.3" +WEBSITE = "http://python-ptrace.readthedocs.io/" LICENSE = "GNU GPL v2" diff -Nru python-ptrace-0.7/python_ptrace.egg-info/PKG-INFO python-ptrace-0.9.3/python_ptrace.egg-info/PKG-INFO --- python-ptrace-0.7/python_ptrace.egg-info/PKG-INFO 2014-03-05 13:46:11.000000000 +0000 +++ python-ptrace-0.9.3/python_ptrace.egg-info/PKG-INFO 2017-09-19 09:03:19.000000000 +0000 @@ -1,202 +1,37 @@ Metadata-Version: 1.1 Name: python-ptrace -Version: 0.7 +Version: 0.9.3 Summary: python binding of ptrace -Home-page: http://bitbucket.org/haypo/python-ptrace/wiki/Home +Home-page: http://python-ptrace.readthedocs.io/ Author: Victor Stinner Author-email: UNKNOWN License: GNU GPL v2 -Download-URL: http://bitbucket.org/haypo/python-ptrace/wiki/Home -Description: python-ptrace is a Python binding of ptrace library. - - The binding works on: - - * Linux version 2.6.20 on i386, x86_64, PPC (may works on Linux 2.4.x - and 2.6.x) - * Linux version 2.4 on PPC - * FreeBSD version 7.0RC1 on i386 (may works on FreeBSD 5.x/6.x) - * OpenBSD version 4.2 on i386 - - Features: - - * High level Python object API : !PtraceDebugger and !PtraceProcess - * Able to control multiple processes: catch fork events on Linux - * Read/write bytes to arbitrary address: take care of memory alignment and - split bytes to cpu word - * Execution step by step using ptrace_singlestep() or hardware interruption 3 - * Can use distorm (http://www.ragestorm.net/distorm/) disassembler - * Dump registers, memory mappings, stack, etc. - * Syscall tracer and parser (strace command) - - Website: http://bitbucket.org/haypo/python-ptrace/wiki/Home - - - Installation - ============ - - Read INSTALL documentation file. - - Documentation +Download-URL: http://python-ptrace.readthedocs.io/ +Description-Content-Type: UNKNOWN +Description: ============= + python-ptrace ============= - Browse doc/ and examples/ directories. - - Changelog - ========= - - python-ptrace 0.7 (2013-03-05) - ------------------------------ - - * Experimental support of Python 3.3 in the same code base - * Drop support of Python 2.5 - * Remove the ptrace.compatibility module - * Fix Process.readStruct() and Process.readArray() on x86_64 - * Experimental support of ARM architecture (Linux EAPI), - strace.py has been tested on Raspberry Pi (armv6l) - - python-ptrace 0.6.6 (2013-12-16) - -------------------------------- - - * Fix os_tools.RUNNING_LINUX for Python 2.x compiled on Linux kernel 3.x - * Support FreeBSD on x86_64 - * Add missing prototype of the unlinkat() system call. Patch written by - Matthew Fernandez. - - python-ptrace 0.6.5 (2013-06-06) - -------------------------------- - - * syscall: fix parsing socketcall on Linux x86 - * syscall: fix protoype of socket() - - python-ptrace 0.6.4 (2012-02-26) - -------------------------------- - - * Convert all classes to new-style classes, patch written by teythoon - * Fix compilation on Apple, patch written by Anthony Gelibert - * Support GNU/kFreeBSD, patch written by Jakub Wilk - * Support sockaddr_in6 (IPv6 address) - - python-ptrace 0.6.3 (2011-02-16) - -------------------------------- - - * Support distrom3 - * Support Python 3 - * Rename strace.py option --socketcall to --socket, and fix this option for - FreeBSD and Linux/64 bits - * Add MANIFEST.in: include all files in source distribution (tests, cptrace - module, ...) - - python-ptrace 0.6.2 (2009-11-09) - -------------------------------- - - * Fix 64 bits sub registers (set mask for eax, ebx, ecx, edx) - - python-ptrace 0.6.1 (2009-11-07) - -------------------------------- - - * Create follow, showfollow, resetfollow, xray commands in gdb.py. Patch - written by Dimitris Glynos - * Project website moved to http://bitbucket.org/haypo/python-ptrace/ - * Replace types (u)intXX_t by c_(u)intXX - * Create MemoryMapping.search() method and MemoryMapping now keeps a weak - reference to the process - - python-ptrace 0.6 (2009-02-13) - ------------------------------ - - User visible changes: - - * python-ptrace now depends on Python 2.5 - * Invalid memory access: add fault address in the name - * Update Python 3.0 conversion patch - * Create -i (--show-ip) option to strace.py: show instruction pointer - * Add a new example (itrace.py) written by Mark Seaborn and based - on strace.py - - API changes: - - * PtraceSyscall: store the instruction pointer at syscall enter (if the - option instr_pointer=True, disabled by default) - * Remove PROC_DIRNAME and procFilename() from ptrace.linux_proc - - Bugfixes: - - * Fix locateProgram() for relative path - * Fix interpretation of memory fault on MOSVW instruction (source is ESI and - destination is EDI, and not the inverse!) - - python-ptrace 0.5 (2008-09-13) - ------------------------------ - - Visible changes: - - * Write an example (the most simple debugger) and begin to document the code - * gdb.py: create "dbginfo" command - * Parse socket syscalls on FreeBSD - * On invalid memory access (SIGSEGV), eval the dereference expression to get - the fault address on OS without siginfo (eg. FreeBSD) - * Fixes to get minimal Windows support: fix imports, fix locateProgram() - - Other changes: - - * Break the API: - - Rename PtraceDebugger.traceSysgood() to PtraceDebugger.enableSysgood() - - Rename PtraceDebugger.trace_sysgood to PtraceDebugger.use_sysgood - - Remove PtraceProcess.readCode() - * Create createChild() function which close all files except stdin, - stdout and stderr - * On FreeBSD, on process exit recalls waitpid(pid) to avoid zombi process - - - python-ptrace 0.4.2 (2008-08-28) - -------------------------------- - - * BUGFIX: Fix typo in gdb.py (commands => command_str), it wasn't possible to - write more than one command... - * BUGIFX: Fix typo in SignalInfo class (remove "self."). When a process - received a signal SIGCHLD (because of a fork), the debugger exited because - of this bug. - * BUGFIX: Debugger._wait() return abnormal process exit as a normal event, - the event is not raised as an exception - * PtraceSignal: don't clear preformatted arguments (eg. arguments of execve) - - python-ptrace 0.4.1 (2008-08-23) - -------------------------------- - - * The project has a new dedicated website: http://python-ptrace.hachoir.org/ - * Create cptrace: optional Python binding of ptrace written in C (faster - than ptrace, the Python binding written in Python with ctypes) - * Add name attribute to SignalInfo classes - * Fixes to help Python 3.0 compatibility: don't use sys.exc_clear() - (was useless) in writeBacktrace() - * ProcessState: create utime, stime, starttime attributes - - python-ptrace 0.4.0 (2008-08-19) - -------------------------------- - - Visible changes: - - * Rename the project to "python-ptrace" (old name was "Ptrace) - * strace.py: create --ignore-regex option - * PtraceSignal: support SIGBUS, display the related registers and - the instruction - * Support execve() syscall tracing - - Developer changes: - - * New API is incompatible with 0.3.2 - * PtraceProcess.waitProcessEvent() accepts optional blocking=False argument - * PtraceProcess.getreg()/setreg() are able to read/write i386 and x86-64 - "sub-registers" like al or bx - * Remove iterProc() function, replaced by openProc() with explicit - call to .close() to make sure that files are closed - * Create searchProcessesByName() - * Replace CPU_PPC constant by CPU_POWERPC and create CPU_PPC32 and CPU_PPC64 - * Create MemoryMapping object, used by readMappings() and findStack() methods - of PtraceProcess - * Always define all PtraceProcess methods but raise an error if the function - is not implemented + .. image:: https://img.shields.io/pypi/v/python-ptrace.svg + :alt: Latest release on the Python Cheeseshop (PyPI) + :target: https://pypi.python.org/pypi/python-ptrace + + .. image:: https://travis-ci.org/haypo/python-ptrace.svg?branch=master + :alt: Build status of python-ptrace on Travis CI + :target: https://travis-ci.org/haypo/python-ptrace + + python-ptrace is a debugger using ptrace (Linux, BSD and Darwin system call to + trace processes) written in Python. + + * `python-ptrace documentation + `_ + * `python-ptrace at GitHub + `_ + * `python-ptrace at the Python Cheeseshop (PyPI) + `_ + python-ptrace is an opensource project written in Python under GNU GPLv2 + license. Platform: UNKNOWN Classifier: Intended Audience :: Developers diff -Nru python-ptrace-0.7/python_ptrace.egg-info/SOURCES.txt python-ptrace-0.9.3/python_ptrace.egg-info/SOURCES.txt --- python-ptrace-0.7/python_ptrace.egg-info/SOURCES.txt 2014-03-05 13:46:11.000000000 +0000 +++ python-ptrace-0.9.3/python_ptrace.egg-info/SOURCES.txt 2017-09-19 09:03:19.000000000 +0000 @@ -1,29 +1,36 @@ -AUTHORS COPYING -ChangeLog -INSTALL MANIFEST.in -README -README.cptrace -TODO +README.rst gdb.py pyflakes.sh +runtests.py setup.py setup_cptrace.py strace.py test_doc.py +tox.ini cptrace/Makefile cptrace/cptrace.c cptrace/version.py +doc/Makefile +doc/authors.rst +doc/changelog.rst +doc/conf.py +doc/cptrace.rst +doc/gdb.rst +doc/index.rst +doc/install.rst +doc/make.bat doc/process_events.rst doc/ptrace_signal.rst +doc/syscall.rst +doc/todo.rst +doc/usage.rst examples/itrace.py examples/simple_dbg.py ptrace/__init__.py ptrace/cpu_info.py -ptrace/ctypes_errno.py ptrace/ctypes_libc.py -ptrace/ctypes_stdint.py ptrace/ctypes_tools.py ptrace/disasm.py ptrace/error.py @@ -81,6 +88,10 @@ python_ptrace.egg-info/SOURCES.txt python_ptrace.egg-info/dependency_links.txt python_ptrace.egg-info/top_level.txt +tests/test_gdb.py +tests/test_strace.py +tests/crash/BSDmakefile +tests/crash/Makefile tests/crash/abort.c tests/crash/call_null.c tests/crash/div_zero.c diff -Nru python-ptrace-0.7/README python-ptrace-0.9.3/README --- python-ptrace-0.7/README 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,34 +0,0 @@ -python-ptrace is a Python binding of ptrace library. - -The binding works on: - - * Linux version 2.6.20 on i386, x86_64, PPC (may works on Linux 2.4.x - and 2.6.x) - * Linux version 2.4 on PPC - * FreeBSD version 7.0RC1 on i386 (may works on FreeBSD 5.x/6.x) - * OpenBSD version 4.2 on i386 - -Features: - - * High level Python object API : !PtraceDebugger and !PtraceProcess - * Able to control multiple processes: catch fork events on Linux - * Read/write bytes to arbitrary address: take care of memory alignment and - split bytes to cpu word - * Execution step by step using ptrace_singlestep() or hardware interruption 3 - * Can use distorm (http://www.ragestorm.net/distorm/) disassembler - * Dump registers, memory mappings, stack, etc. - * Syscall tracer and parser (strace command) - -Website: http://bitbucket.org/haypo/python-ptrace/wiki/Home - - -Installation -============ - -Read INSTALL documentation file. - -Documentation -============= - -Browse doc/ and examples/ directories. - diff -Nru python-ptrace-0.7/README.cptrace python-ptrace-0.9.3/README.cptrace --- python-ptrace-0.7/README.cptrace 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/README.cptrace 1970-01-01 00:00:00.000000000 +0000 @@ -1,18 +0,0 @@ -+++++++++++++++++++++ -cptrace Python module -+++++++++++++++++++++ - -Python binding for ptrace written in C. - -Example -======= - -Dummy example: :: - - >>> import cptrace - >>> cptrace.ptrace(1, 1) - Traceback (most recent call last): - File "", line 1, in - ValueError: ptrace(request=1, pid=1, 0x(nil), 0x(nil)) error #1: Operation not permitted - - diff -Nru python-ptrace-0.7/README.rst python-ptrace-0.9.3/README.rst --- python-ptrace-0.7/README.rst 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/README.rst 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,24 @@ +============= +python-ptrace +============= + +.. image:: https://img.shields.io/pypi/v/python-ptrace.svg + :alt: Latest release on the Python Cheeseshop (PyPI) + :target: https://pypi.python.org/pypi/python-ptrace + +.. image:: https://travis-ci.org/haypo/python-ptrace.svg?branch=master + :alt: Build status of python-ptrace on Travis CI + :target: https://travis-ci.org/haypo/python-ptrace + +python-ptrace is a debugger using ptrace (Linux, BSD and Darwin system call to +trace processes) written in Python. + +* `python-ptrace documentation + `_ +* `python-ptrace at GitHub + `_ +* `python-ptrace at the Python Cheeseshop (PyPI) + `_ + +python-ptrace is an opensource project written in Python under GNU GPLv2 +license. diff -Nru python-ptrace-0.7/runtests.py python-ptrace-0.9.3/runtests.py --- python-ptrace-0.7/runtests.py 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/runtests.py 2017-02-10 11:38:49.000000000 +0000 @@ -0,0 +1,291 @@ +#!/usr/bin/env python +"""Run Tulip unittests. + +Usage: + python3 runtests.py [flags] [pattern] ... + +Patterns are matched against the fully qualified name of the test, +including package, module, class and method, +e.g. 'tests.test_events.PolicyTests.testPolicy'. + +For full help, try --help. + +runtests.py --coverage is equivalent of: + + $(COVERAGE) run --branch runtests.py -v + $(COVERAGE) html $(list of files) + $(COVERAGE) report -m $(list of files) + +""" + +# Originally written by Beech Horn (for NDB). + +from __future__ import print_function +import optparse +import gc +import logging +import os +import re +import sys +import textwrap +try: + import coverage +except ImportError: + coverage = None +if sys.version_info < (3,): + sys.exc_clear() + +try: + import unittest + from unittest.signals import installHandler +except ImportError: + import unittest2 as unittest + from unittest2.signals import installHandler + +ARGS = optparse.OptionParser(description="Run all unittests.", usage="%prog") +ARGS.add_option( + '-v', '--verbose', action="store_true", dest='verbose', + default=0, help='verbose') +ARGS.add_option( + '-x', action="store_true", dest='exclude', help='exclude tests') +ARGS.add_option( + '-f', '--failfast', action="store_true", default=False, + dest='failfast', help='Stop on first fail or error') +ARGS.add_option( + '-c', '--catch', action="store_true", default=False, + dest='catchbreak', help='Catch control-C and display results') +ARGS.add_option( + '--forever', action="store_true", dest='forever', default=False, + help='run tests forever to catch sporadic errors') +ARGS.add_option( + '--findleaks', action='store_true', dest='findleaks', + help='detect tests that leak memory') +ARGS.add_option( + '-q', action="store_true", dest='quiet', help='quiet') +ARGS.add_option( + '--tests', action="store", dest='testsdir', default='tests', + help='tests directory') +ARGS.add_option( + '--coverage', action="store_true", dest='coverage', + help='enable html coverage report') +ARGS.add_option( + '--pattern', action="append", + help='optional regex patterns to match test ids (default all tests)') + + +if sys.version_info >= (3, 3): + import importlib.machinery + + def load_module(modname, sourcefile): + loader = importlib.machinery.SourceFileLoader(modname, sourcefile) + return loader.load_module() +else: + import imp + + def load_module(modname, sourcefile): + return imp.load_source(modname, sourcefile) + + +def load_modules(basedir, suffix='.py'): + def list_dir(prefix, dir): + files = [] + + modpath = os.path.join(dir, '__init__.py') + if os.path.isfile(modpath): + mod = os.path.split(dir)[-1] + files.append(('{0}{1}'.format(prefix, mod), modpath)) + + prefix = '{0}{1}.'.format(prefix, mod) + + for name in os.listdir(dir): + path = os.path.join(dir, name) + + if os.path.isdir(path): + files.extend(list_dir('{0}{1}.'.format(prefix, name), path)) + else: + if (name != '__init__.py' and + name.endswith(suffix) and + not name.startswith(('.', '_'))): + files.append(('{0}{1}'.format(prefix, name[:-3]), path)) + + return files + + mods = [] + for modname, sourcefile in list_dir('', basedir): + if modname == 'runtests': + continue + try: + mod = load_module(modname, sourcefile) + mods.append((mod, sourcefile)) + except SyntaxError: + raise + except Exception as err: + print("Skipping '{0}': {1}".format(modname, err), file=sys.stderr) + + return mods + + +class TestsFinder: + + def __init__(self, testsdir, includes=(), excludes=()): + self._testsdir = testsdir + self._includes = includes + self._excludes = excludes + self.find_available_tests() + + def find_available_tests(self): + """ + Find available test classes without instantiating them. + """ + self._test_factories = [] + mods = [mod for mod, _ in load_modules(self._testsdir)] + for mod in mods: + for name in set(dir(mod)): + if 'Test' in name: + self._test_factories.append(getattr(mod, name)) + + def load_tests(self): + """ + Load test cases from the available test classes and apply + optional include / exclude filters. + """ + loader = unittest.TestLoader() + suite = unittest.TestSuite() + for test_factory in self._test_factories: + tests = loader.loadTestsFromTestCase(test_factory) + if self._includes: + tests = [test + for test in tests + if any(re.search(pat, test.id()) + for pat in self._includes)] + if self._excludes: + tests = [test + for test in tests + if not any(re.search(pat, test.id()) + for pat in self._excludes)] + suite.addTests(tests) + return suite + + +class TestResult(unittest.TextTestResult): + + def __init__(self, stream, descriptions, verbosity): + super().__init__(stream, descriptions, verbosity) + self.leaks = [] + + def startTest(self, test): + super().startTest(test) + gc.collect() + + def addSuccess(self, test): + super().addSuccess(test) + gc.collect() + if gc.garbage: + if self.showAll: + self.stream.writeln( + " Warning: test created {} uncollectable " + "object(s).".format(len(gc.garbage))) + # move the uncollectable objects somewhere so we don't see + # them again + self.leaks.append((self.getDescription(test), gc.garbage[:])) + del gc.garbage[:] + + +class TestRunner(unittest.TextTestRunner): + resultclass = TestResult + + def run(self, test): + result = super().run(test) + if result.leaks: + self.stream.writeln("{0} tests leaks:".format(len(result.leaks))) + for name, leaks in result.leaks: + self.stream.writeln(' ' * 4 + name + ':') + for leak in leaks: + self.stream.writeln(' ' * 8 + repr(leak)) + return result + + +def runtests(): + args, commands = ARGS.parse_args() + + if args.coverage and coverage is None: + URL = "bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py" + print(textwrap.dedent(""" + coverage package is not installed. + + To install coverage3 for Python 3, you need: + - Setuptools (https://pypi.python.org/pypi/setuptools) + + What worked for me: + - download {0} + * curl -O https://{0} + - python3 ez_setup.py + - python3 -m easy_install coverage + """.format(URL)).strip()) + sys.exit(1) + + testsdir = os.path.abspath(args.testsdir) + if not os.path.isdir(testsdir): + print("Tests directory is not found: {0}\n".format(testsdir)) + ARGS.print_help() + return + + excludes = includes = [] + if args.exclude: + excludes = args.pattern + else: + includes = args.pattern + + v = 0 if args.quiet else args.verbose + 1 + failfast = args.failfast + catchbreak = args.catchbreak + findleaks = args.findleaks + runner_factory = TestRunner if findleaks else unittest.TextTestRunner + + if args.coverage: + cov = coverage.coverage(branch=True, + source=['asyncio'], + ) + cov.start() + + finder = TestsFinder(args.testsdir, includes, excludes) + logger = logging.getLogger() + if v == 0: + logger.setLevel(logging.CRITICAL) + elif v == 1: + logger.setLevel(logging.ERROR) + elif v == 2: + logger.setLevel(logging.WARNING) + elif v == 3: + logger.setLevel(logging.INFO) + elif v >= 4: + logger.setLevel(logging.DEBUG) + if catchbreak: + installHandler() + try: + if args.forever: + while True: + tests = finder.load_tests() + result = runner_factory(verbosity=v, + failfast=failfast).run(tests) + if not result.wasSuccessful(): + sys.exit(1) + else: + tests = finder.load_tests() + result = runner_factory(verbosity=v, + failfast=failfast).run(tests) + sys.exit(not result.wasSuccessful()) + finally: + if args.coverage: + cov.stop() + cov.save() + cov.html_report(directory='htmlcov') + print("\nCoverage report:") + cov.report(show_missing=False) + here = os.path.dirname(os.path.abspath(__file__)) + print("\nFor html report:") + print("open file://{0}/htmlcov/index.html".format(here)) + + +if __name__ == '__main__': + runtests() diff -Nru python-ptrace-0.7/setup.cfg python-ptrace-0.9.3/setup.cfg --- python-ptrace-0.7/setup.cfg 2014-03-05 13:46:11.000000000 +0000 +++ python-ptrace-0.9.3/setup.cfg 2017-09-19 09:03:19.000000000 +0000 @@ -1,5 +1,4 @@ [egg_info] tag_build = tag_date = 0 -tag_svn_revision = 0 diff -Nru python-ptrace-0.7/setup_cptrace.py python-ptrace-0.9.3/setup_cptrace.py --- python-ptrace-0.7/setup_cptrace.py 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/setup_cptrace.py 2017-02-10 11:41:08.000000000 +0000 @@ -13,7 +13,8 @@ 'Programming Language :: Python', ] -LONG_DESCRIPTION = open('README.cptrace').read() +LONG_DESCRIPTION = open('doc/cptrace.rst').read() + def main(): from imp import load_source @@ -44,6 +45,6 @@ } setup(**install_options) + if __name__ == "__main__": main() - diff -Nru python-ptrace-0.7/setup.py python-ptrace-0.9.3/setup.py --- python-ptrace-0.7/setup.py 2014-03-05 13:45:37.000000000 +0000 +++ python-ptrace-0.9.3/setup.py 2017-09-19 09:03:08.000000000 +0000 @@ -1,23 +1,43 @@ #!/usr/bin/env python -# Produce to release a new version: -# - hg in # check that there is no incoming changesets -# - ./test_doc.py -# - run tests (test_gdb.py and test_strace.py) with Python 2 and Python 3 -# - check version in ptrace/version.py -# - set release date in the ChangeLog -# - hg ci -# - hg tag python-ptrace-x.y -# - hg push -# - ./setup.py sdist register bdist_wheel upload -# - update the website home page (url, md5 and news) -# https://bitbucket.org/haypo/python-ptrace/wiki/Home -# - set version to n+1 (ptrace/version.py) -# - hg ci -# - hg push +# Prepare a release: +# +# - git pull --rebase # check that there is no incoming changesets +# - check version in ptrace/version.py and doc/conf.py +# - set release date in doc/changelog.rst +# - check that "python setup.py sdist" contains all files tracked by +# the SCM (Git): update MANIFEST.in if needed +# - git commit -a -m "prepare release VERSION" +# - run tests, type: tox +# - git push +# - check Travis status: +# https://travis-ci.org/haypo/python-ptrace +# +# Release a new version: +# +# - git tag python-ptrace-VERSION +# - git push --tags +# - git clean -fdx # WARNING: Remove all untracked files! +# - python3 setup.py sdist bdist_wheel +# - twine upload dist/* +# +# After the release: +# +# - increment version in ptrace/version.py and doc/conf.py +# - git commit -a -m "post-release" +# - git push from __future__ import with_statement +from imp import load_source +from os import path +try: + # setuptools supports bdist_wheel + from setuptools import setup +except ImportError: + from distutils.core import setup + + MODULES = ["ptrace", "ptrace.binding", "ptrace.syscall", "ptrace.debugger"] SCRIPTS = ("strace.py", "gdb.py") @@ -33,19 +53,8 @@ 'Programming Language :: Python :: 3', ] -with open('README') as fp: +with open('README.rst') as fp: LONG_DESCRIPTION = fp.read() -with open('ChangeLog') as fp: - LONG_DESCRIPTION += fp.read() - -from imp import load_source -from os import path -from sys import argv -try: - # setuptools supports bdist_wheel - from setuptools import setup, Extension -except ImportError: - from distutils.core import setup ptrace = load_source("version", path.join("ptrace", "version.py")) PACKAGES = {} diff -Nru python-ptrace-0.7/strace.py python-ptrace-0.9.3/strace.py --- python-ptrace-0.7/strace.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/strace.py 2017-02-10 11:41:08.000000000 +0000 @@ -2,19 +2,20 @@ from __future__ import print_function from ptrace import PtraceError from ptrace.debugger import (PtraceDebugger, Application, - ProcessExit, ProcessSignal, NewProcessEvent, ProcessExecution) + ProcessExit, ProcessSignal, NewProcessEvent, ProcessExecution) from ptrace.syscall import (SYSCALL_NAMES, SYSCALL_PROTOTYPES, - FILENAME_ARGUMENTS, SOCKET_SYSCALL_NAMES) + FILENAME_ARGUMENTS, SOCKET_SYSCALL_NAMES) from ptrace.func_call import FunctionCallOptions from sys import stderr, exit from optparse import OptionParser from logging import getLogger, error -from ptrace.syscall.socketcall_constants import SOCKETCALL from ptrace.error import PTRACE_ERRORS, writeError from ptrace.ctypes_tools import formatAddress import re + class SyscallTracer(Application): + def __init__(self): Application.__init__(self) @@ -27,48 +28,51 @@ def setupLog(self): if self.options.output: fd = open(self.options.output, 'w') + self._output = fd else: fd = stderr + self._output = None self._setupLog(fd) def parseOptions(self): - parser = OptionParser(usage="%prog [options] -- program [arg1 arg2 ...]") + parser = OptionParser( + usage="%prog [options] -- program [arg1 arg2 ...]") self.createCommonOptions(parser) parser.add_option("--enter", help="Show system call enter and exit", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--profiler", help="Use profiler", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--type", help="Display arguments type and result type (default: no)", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--name", help="Display argument name (default: no)", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--string-length", "-s", help="String max length (default: 300)", - type="int", default=300) + type="int", default=300) parser.add_option("--array-count", help="Maximum number of array items (default: 20)", - type="int", default=20) + type="int", default=20) parser.add_option("--raw-socketcall", help="Raw socketcall form", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--output", "-o", help="Write output to specified log file", - type="str") - parser.add_option("--ignore-regex", help="Regex used to filter syscall names (eg. --ignore='^(gettimeofday|futex|f?stat)')", - type="str") - parser.add_option("--address", help="Display structure addressl", - action="store_true", default=False) + type="str") + parser.add_option("--ignore-regex", help="Regex used to filter syscall names (e.g. --ignore='^(gettimeofday|futex|f?stat)')", + type="str") + parser.add_option("--address", help="Display structure address", + action="store_true", default=False) parser.add_option("--syscalls", '-e', help="Comma separated list of shown system calls (other will be skipped)", - type="str", default=None) + type="str", default=None) parser.add_option("--socket", help="Show only socket functions", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--filename", help="Show only syscall using filename", - action="store_true", default=False) + action="store_true", default=False) parser.add_option("--show-pid", - help="Prefix line with process identifier", - action="store_true", default=False) + help="Prefix line with process identifier", + action="store_true", default=False) parser.add_option("--list-syscalls", - help="Display system calls and exit", - action="store_true", default=False) + help="Display system calls and exit", + action="store_true", default=False) parser.add_option("-i", "--show-ip", - help="print instruction pointer at time of syscall", - action="store_true", default=False) + help="print instruction pointer at time of syscall", + action="store_true", default=False) self.createLogOptions(parser) @@ -97,11 +101,12 @@ valid_names = list(SYSCALL_NAMES.values()) for name in only: if name not in valid_names: - print("ERROR: unknow syscall %r" % name, file=stderr) + print("ERROR: unknown syscall %r" % name, file=stderr) ok = False if not ok: print(file=stderr) - print("Use --list-syscalls options to get system calls list", file=stderr) + print( + "Use --list-syscalls options to get system calls list", file=stderr) exit(1) # remove duplicates only.add(item) @@ -137,7 +142,6 @@ return False def displaySyscall(self, syscall): - name = syscall.name text = syscall.format() if syscall.result is not None: text = "%-40s = %s" % (text, syscall.result_text) @@ -162,13 +166,12 @@ # Wait until next syscall enter try: event = self.debugger.waitSyscall() - process = event.process except ProcessExit as event: self.processExited(event) continue except ProcessSignal as event: event.display() - process.syscall(event.signum) + event.process.syscall(event.signum) continue except NewProcessEvent as event: self.newProcess(event) @@ -178,7 +181,7 @@ continue # Process syscall enter or exit - self.syscall(process) + self.syscall(event.process) def syscall(self, process): state = process.syscall_state @@ -193,8 +196,8 @@ # Display syscall which has not exited state = event.process.syscall_state if (state.next_event == "exit") \ - and (not self.options.enter) \ - and state.syscall: + and (not self.options.enter) \ + and state.syscall: self.displaySyscall(state.syscall) # Display exit message @@ -240,6 +243,8 @@ runProfiler(getLogger(), self._main) else: self._main() + if self._output is not None: + self._output.close() def _main(self): self.debugger = PtraceDebugger() @@ -261,6 +266,6 @@ program[0], program, pid)) return pid + if __name__ == "__main__": SyscallTracer().main() - diff -Nru python-ptrace-0.7/test_doc.py python-ptrace-0.9.3/test_doc.py --- python-ptrace-0.7/test_doc.py 2014-01-03 01:09:50.000000000 +0000 +++ python-ptrace-0.9.3/test_doc.py 2017-02-10 11:41:08.000000000 +0000 @@ -3,6 +3,7 @@ from sys import exit, path as sys_path from os.path import dirname + def testDoc(filename, name=None): print("--- %s: Run tests" % filename) failure, nb_test = testfile( @@ -11,6 +12,7 @@ exit(1) print("--- %s: End of tests" % filename) + def importModule(name): mod = __import__(name) components = name.split('.') @@ -18,6 +20,7 @@ mod = getattr(mod, comp) return mod + def testModule(name): print("--- Test module %s" % name) module = importModule(name) @@ -26,20 +29,22 @@ exit(1) print("--- End of test") + def main(): ptrace_dir = dirname(__file__) sys_path.append(ptrace_dir) # Test documentation in doc/*.rst files - #testDoc('doc/c_tools.rst') + # testDoc('doc/c_tools.rst') # Test documentation of some functions/classes - testModule("ptrace.tools") - testModule("ptrace.signames") - testModule("ptrace.logging_tools") + testModule("ptrace.ctypes_tools") testModule("ptrace.debugger.parse_expr") + testModule("ptrace.logging_tools") + testModule("ptrace.signames") testModule("ptrace.syscall.socketcall") + testModule("ptrace.tools") + if __name__ == "__main__": main() - diff -Nru python-ptrace-0.7/tests/crash/BSDmakefile python-ptrace-0.9.3/tests/crash/BSDmakefile --- python-ptrace-0.7/tests/crash/BSDmakefile 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/tests/crash/BSDmakefile 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,13 @@ +SOURCES=stack_overflow.c div_zero.c call_null.c abort.c fork.c invalid_write.c invalid_read.c +PROGRAMS=${SOURCES:S/.c//g} pthread +CFLAGS=-Wall -O0 -g + +all: $(PROGRAMS) + +pthread: pthread.c + $(CC) -o $@ $(CFLAGS) pthread.c -lpthread + + +clean: + rm -f $(PROGRAMS) + diff -Nru python-ptrace-0.7/tests/crash/Makefile python-ptrace-0.9.3/tests/crash/Makefile --- python-ptrace-0.7/tests/crash/Makefile 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/tests/crash/Makefile 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,13 @@ +CC=gcc +SOURCES=stack_overflow.c div_zero.c call_null.c abort.c fork.c execve.c invalid_write.c invalid_read.c socket_ipv4_tcp.c +PROGRAMS=$(patsubst %.c,%,$(SOURCES)) pthread +CFLAGS=-Wall -Wextra -Werror -O0 -g + +all: $(PROGRAMS) + +pthread: pthread.c + $(CC) -o $@ $(CFLAGS) pthread.c -lpthread + +clean: + rm -f $(PROGRAMS) + diff -Nru python-ptrace-0.7/tests/test_gdb.py python-ptrace-0.9.3/tests/test_gdb.py --- python-ptrace-0.7/tests/test_gdb.py 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/tests/test_gdb.py 2017-02-10 11:41:08.000000000 +0000 @@ -0,0 +1,80 @@ +#!/usr/bin/env python +import os +import re +import subprocess +import sys +import unittest +from ptrace import six + +GDB = os.path.normpath(os.path.join(os.path.dirname(__file__), '..', 'gdb.py')) + + +class TestGdb(unittest.TestCase): + + def run_command(self, command): + if isinstance(command, six.text_type): + command = command.encode('ascii') + command = command + b'\n' + args = [sys.executable, GDB, '--', sys.executable, '-c', 'pass'] + proc = subprocess.Popen(args, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + stdout, _ = proc.communicate(command) + exitcode = proc.wait() + self.assertEqual(exitcode, 0) + if stdout.startswith(b'(gdb) '): + stdout = stdout[6:] + pos = stdout.rfind(b'(gdb) ') + if pos: + stdout = stdout[:pos] + stdout = stdout.rstrip() + if b'Traceback' in stdout: + self.fail('Traceback in output: %r' % stdout) + return stdout + + def check_stdout(self, pattern, stdout): + self.assertTrue(re.search(pattern, stdout, re.MULTILINE), + (pattern, stdout)) + + def test_proc(self): + stdout = self.run_command('proc') + for pattern in ( + b'^Process ID: [0-9]+', + b'^Process state: ', + b'^Process environment: ', + b'^User identifier: [0-9]+', + b'^Group identifier: [0-9]+', + ): + self.assertTrue(re.search(pattern, stdout, re.MULTILINE), + (pattern, stdout)) + + def test_print(self): + stdout = self.run_command('print 1+2') + self.check_stdout(b'^Decimal: 3\n', stdout) + + def test_where(self): + stdout = self.run_command('where') + self.check_stdout(b'^CODE: ', stdout) + + def test_regs(self): + # Just check that the command doesn't raise an exception + self.run_command('regs') + + def test_backtrace(self): + # Just check that the command doesn't raise an exception + self.run_command('backtrace') + + def test_maps(self): + stdout = self.run_command('maps') + self.check_stdout(b'^MAPS: ', stdout) + + def test_dbginfo(self): + stdout = self.run_command('dbginfo') + self.check_stdout(b'^Debugger process ID: [0-9]+', stdout) + self.check_stdout(b'^python-ptrace version [0-9]+\\.[0-9]+', stdout) + self.check_stdout(b'^Website: ', stdout) + + +if __name__ == "__main__": + unittest.main() diff -Nru python-ptrace-0.7/tests/test_strace.py python-ptrace-0.9.3/tests/test_strace.py --- python-ptrace-0.7/tests/test_strace.py 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/tests/test_strace.py 2017-09-18 15:14:16.000000000 +0000 @@ -0,0 +1,99 @@ +#!/usr/bin/env python +import os +import re +import subprocess +import sys +import tempfile +import unittest +from ptrace import six + +STRACE = os.path.normpath(os.path.join( + os.path.dirname(__file__), '..', 'strace.py')) + + +class TestStrace(unittest.TestCase): + + def strace(self, *args): + """ Strace the given command and return the strace output. """ + with tempfile.NamedTemporaryFile(mode='wb+') as temp: + args = (sys.executable, STRACE, '-o', temp.name, '--') + args + with open(os.devnull, "wb") as devnull: + proc = subprocess.Popen(args, + stdout=devnull, + stderr=subprocess.STDOUT) + proc.wait() + + temp.seek(0) + strace = temp.readlines() + strace = b''.join(strace) + self.assertIsNone(re.match(b'^Traceback', strace), strace) + return strace + + def assert_syscall(self, code, regex): + """ + Strace the given python code and match the strace output against the + given regular expression. + """ + stdout = self.strace(sys.executable, '-c', code) + pattern = re.compile(regex, re.MULTILINE) + self.assertTrue(pattern.search(stdout), stdout) + + def test_basic(self): + stdout = self.strace(sys.executable, '-c', 'pass') + for syscall in (b'exit', b'mmap', b'open'): + pattern = re.compile(b'^' + syscall, re.MULTILINE) + self.assertTrue(pattern.search(stdout), stdout) + + def test_getcwd(self): + cwd = os.getcwd() + stdout = self.strace(sys.executable, '-c', 'import os; os.getcwd()') + pattern = re.compile(b'^getcwd\\((.*),', re.MULTILINE) + match = pattern.search(stdout) + self.assertTrue(match, stdout) + expected = repr(cwd) + if six.PY3: + expected = os.fsencode(expected) + self.assertEqual(match.group(1), expected) + + def test_open(self): + if six.PY3: + code = 'open(%a).close()' % __file__ + else: + code = 'open(%r).close()' % __file__ + self.assert_syscall(code, + br"^open(at)?\(.*test_strace\.pyc?', O_RDONLY(\|O_CLOEXEC)?") + + def test_chdir(self): + self.assert_syscall( + "import os; os.chdir('directory')", + br"^chdir\('directory'\)\s+= -2 ENOENT") + + def test_rename(self): + self.assert_syscall( + "import os; os.rename('oldpath', 'newpath')", + br"^rename\('oldpath', 'newpath'\)") + + def test_link(self): + self.assert_syscall( + "import os; os.link('oldpath', 'newpath')", + br"^link\('oldpath', 'newpath'\)") + + def test_symlink(self): + try: + self.assert_syscall( + "import os; os.symlink('target', 'linkpath')", + br"^symlink\('target', 'linkpath'\)") + finally: + try: + os.unlink('linkpath') + except OSError: + pass + + def test_socket(self): + self.assert_syscall( + "import socket; socket.socket(socket.AF_INET,socket.SOCK_STREAM).close()", + br'^socket\(AF_INET, SOCK_STREAM(\|SOCK_CLOEXEC)?') + + +if __name__ == "__main__": + unittest.main() diff -Nru python-ptrace-0.7/TODO python-ptrace-0.9.3/TODO --- python-ptrace-0.7/TODO 2013-02-17 01:44:01.000000000 +0000 +++ python-ptrace-0.9.3/TODO 1970-01-01 00:00:00.000000000 +0000 @@ -1,54 +0,0 @@ -TODO -==== - -Main tasks ----------- - - * Remove ptrace.ctypes_stdint - * Fix strace.py --socketcall: SyscallState.enter() calls ignore_callback - before socketcall are proceed - * Support other backends: - - - GDB MI: http://code.google.com/p/pygdb/ - - ktrace: (FreeBSD and Darwin): would help Darwin support - - utrace (new Linux debugger): http://sourceware.org/systemtap/wiki/utrace - - vtrace? - - PyDBG: works on Windows - - * Backtrace symbols: - - - GNU BFD? - - elfsh? - - addr2line program? - - See dl_iterate_phdr() function of libdl - - * Support other disassemblers (than distorm), and so both Intel syntax (Intel and AT&T) - - - BFD - - http://www.ragestorm.net/distorm/ - - libasm (ERESI) - - libdisasm (bastard) - - http://www.woodmann.com/collaborative/tools/index.php/Category:X86_Disassembler_Libraries - - * Support threads: other backends (than python-ptrace) already support threads - -Minor tasks ------------ - - * setup.py: convert docstrings with 2to3 (run "2to3 -w -d ." ?) - * Fix gdb.py "step" command on a jump. Example where step will never stop: :: - -(gdb) where -ASM 0xb7e3b917: JMP 0xb7e3b8c4 (eb ab) -ASM 0xb7e3b919: LEA ESI, [ESI+0x0] (8db426 00000000) - - * Remove gdb.py "except PtraceError, err: if err.errno == ESRCH" hack, - process death detection should be done by PtraceProcess or PtraceDebugger - * Use Intel hardware breakpoints: set vtrace source code - * Support Darwin: - - - ktrace? need to recompile Darwin kernel with KTRACE option - - get registers: http://unixjunkie.blogspot.com/2006/01/darwin-ptrace-and-registers.html - - PT_DENY_ATTACH: http://steike.com/code/debugging-itunes-with-gdb/ - - PT_DENY_ATTACH: http://landonf.bikemonkey.org/code/macosx/ptrace_deny_attach.20041010201303.11809.mojo.html - diff -Nru python-ptrace-0.7/tox.ini python-ptrace-0.9.3/tox.ini --- python-ptrace-0.7/tox.ini 1970-01-01 00:00:00.000000000 +0000 +++ python-ptrace-0.9.3/tox.ini 2017-02-10 11:22:40.000000000 +0000 @@ -0,0 +1,23 @@ +[tox] +envlist = py2, py3, pep8 + +[testenv] +commands= + python test_doc.py + python runtests.py + +[testenv:py2] +basepython = python + +[testenv:py3] +basepython = python3 + +[testenv:pep8] +deps = flake8 +commands = + flake8 ptrace/ tests/ gdb.py runtests.py setup_cptrace.py setup.py strace.py SYSCALL_PROTOTYPES.codegen.py test_doc.py + +[flake8] +# E501 line too long (88 > 79 characters) +# W503 line break before binary operator +ignore = E501,W503