openpilot is an open source driver assistance system. openpilot performs the functions of Automated Lane Centering and Adaptive Cruise Control for over 200 supported car makes and models.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

340 lines
12 KiB

5 years ago
diff --git a/.travis.yml b/.travis.yml
index 9cc00ec..8a2d6c7 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -12,6 +12,7 @@ env:
- PYVERSION=python3.4
- PYVERSION=python3.5
- PYVERSION=python3.6
+ - PYVERSION=python3.7
addons:
apt:
diff --git a/configure.ac b/configure.ac
index 0858fc3..8827b3a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,7 +23,7 @@ AS_IF([test x"$host_cpu" = xx86_64],
],
[AC_MSG_NOTICE([Threading support will be disabled (only works on x86-64)])
AC_DEFINE([ENABLE_THREADS], [0], [Threads are enabled.])
- AC_DEFINE([USE_ELF64], [0], [Expect 64-bit ELF symbols.])
+ AC_DEFINE([USE_ELF64], [1], [Expect 64-bit ELF symbols.])
])
AC_DEFINE_UNQUOTED([HOST_CPU], ["$host_cpu"], [CPU of target architecture.])
@@ -111,7 +111,12 @@ PKG_CHECK_MODULES([PY36], [python-3.6], [enable_py36="yes"], [AC_MSG_WARN([Build
AM_CONDITIONAL([ENABLE_PY36], [test x"$enable_py36" = xyes])
AM_COND_IF([ENABLE_PY36], [AC_DEFINE([ENABLE_PY36], [1], [Python 3.6 will be enabled])])
-AS_IF([test x"$enable_py26" = xyes -o x"$enable_py34" = xyes -o x"$enable_py36" = xyes],
+enable_py37=no
+PKG_CHECK_MODULES([PY37], [python-3.7], [enable_py37="yes"], [AC_MSG_WARN([Building without Python 3.7 support])])
+AM_CONDITIONAL([ENABLE_PY37], [test x"$enable_py37" = xyes])
+AM_COND_IF([ENABLE_PY37], [AC_DEFINE([ENABLE_PY37], [1], [Python 3.7 will be enabled])])
+
+AS_IF([test x"$enable_py26" = xyes -o x"$enable_py34" = xyes -o x"$enable_py36" = xyes -o x"$enable_py37" = xyes],
[AC_MSG_NOTICE([Found at least one copy of Python.h])],
[AC_MSG_ERROR([Failed to find a supported Python.h])]
)
@@ -127,7 +132,8 @@ echo
echo " with threads = $enable_threads"
echo " with Python 2.6/7 = $enable_py26"
echo " with Python 3.4/5 = $enable_py34"
-echo " with Python 3.6+ = $enable_py36"
+echo " with Python 3.6 = $enable_py36"
+echo " with Python 3.7+ = $enable_py37"
echo
echo " CXX = $CXX"
echo " CXXFLAGS = $CXXFLAGS"
diff --git a/docs/faq.rst b/docs/faq.rst
index 6fe8d1e..da6cec8 100644
--- a/docs/faq.rst
+++ b/docs/faq.rst
@@ -7,7 +7,7 @@ What Python Versions Are Supported?
Python 2 is tested with Python 2.6 and 2.7. Earlier versions of Python 2 are
likely to work as well, but have not been tested.
-Python 3 is tested with Python 3.4, 3.5, and 3.6. Python 3.6 introduces a new
+Python 3 is tested with Python 3.4, 3.5, 3.6 and 3.7 Python 3.6 introduces a new
ABI for the ``PyCodeObject`` type, so Pyflame only supports the Python 3
versions that header files were available for when Pyflame was compiled.
diff --git a/docs/man.md b/docs/man.md
index 1aa8d25..538a764 100644
--- a/docs/man.md
+++ b/docs/man.md
@@ -87,7 +87,7 @@ The following options are less commonly used.
cases when profiling embedded Python builds (e.g. uWSGI), and only if
pyflame doesn't automatically detect the correct ABI. *VERSION* should be a
two digit integer consisting of the Python major and minor version, e.g. 27
- for Python 2.7 or 36 for Python 3.6.
+ for Python 2.7, 36 for Python 3.6 or 37 for Python 3.7.
**--flamechart**
: Print the timestamp for each stack. This is useful for generating "flame
diff --git a/docs/pyflame.man b/docs/pyflame.man
index 971a1de..7fdeb85 100644
--- a/docs/pyflame.man
+++ b/docs/pyflame.man
@@ -119,7 +119,7 @@ uWSGI), and only if pyflame doesn\[aq]t automatically detect the correct
ABI.
\f[I]VERSION\f[] should be a two digit integer consisting of the Python
major and minor version, e.g.
-27 for Python 2.7 or 36 for Python 3.6.
+27 for Python 2.7, 36 for Python 3.6 or 37 for Python 3.7.
.RS
.RE
.TP
diff --git a/src/Makefile.am b/src/Makefile.am
index 11d8ab6..4a62bdb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,11 +2,11 @@
#
# The way this code is structured is the code that know about Python interpreter
# internals is in frob.cc. This file isn't compiled directly, instead there are
-# files frob{26,34,36}.cc that define preprocessor macros to compile frob.cc for
+# files frob{26,34,36,37}.cc that define preprocessor macros to compile frob.cc for
# different Python ABIs.
#
# The libtool magic here makes it so that frob26.cc is compiled with python2
-# flags, and frob3{4,6}.cc are compiled with python3.4/3.6 flags.
+# flags, and frob3{4,6,7}.cc are compiled with python3.4/3.6/3.7 flags.
bin_PROGRAMS = pyflame
pyflame_SOURCES = aslr.cc frame.cc thread.cc namespace.cc posix.cc prober.cc ptrace.cc pyflame.cc pyfrob.cc symbol.cc
@@ -34,3 +34,11 @@ libfrob36_la_CXXFLAGS = $(PY36_CFLAGS)
noinst_LTLIBRARIES += libfrob36.la
pyflame_LDADD += libfrob36.la
endif
+
+if ENABLE_PY37
+libfrob37_la_SOURCES = frob37.cc offset37.c
+libfrob37_la_CFLAGS = $(PY37_CFLAGS)
+libfrob37_la_CXXFLAGS = $(PY37_CFLAGS)
+noinst_LTLIBRARIES += libfrob37.la
+pyflame_LDADD += libfrob37.la
+endif
diff --git a/src/frob.cc b/src/frob.cc
index 6fcff39..c1c5b30 100644
--- a/src/frob.cc
+++ b/src/frob.cc
@@ -17,6 +17,7 @@
// information.
#include <Python.h>
+
#include <frameobject.h>
#if PYFLAME_PY_VERSION >= 34
@@ -89,6 +90,22 @@ unsigned long ByteData(unsigned long addr) {
return addr + offsetof(PyBytesObject, ob_sval);
}
+#elif PYFLAME_PY_VERSION == 37
+namespace py37 {
+std::string StringDataPython3(pid_t pid, unsigned long addr);
+
+unsigned long StringSize(unsigned long addr) {
+ return addr + offsetof(PyVarObject, ob_size);
+}
+
+std::string StringData(pid_t pid, unsigned long addr) {
+ return StringDataPython3(pid, addr);
+}
+
+unsigned long ByteData(unsigned long addr) {
+ return addr + offsetof(PyBytesObject, ob_sval);
+}
+
#else
static_assert(false, "uh oh, bad PYFLAME_PY_VERSION");
#endif
diff --git a/src/prober.cc b/src/prober.cc
index a691c83..c653357 100644
--- a/src/prober.cc
+++ b/src/prober.cc
@@ -64,7 +64,7 @@ static const char usage_str[] =
" -x, --exclude-idle Exclude idle time from statistics\n"
"\n"
"Advanced Options:\n"
- " --abi Force a particular Python ABI (26, 34, 36)\n"
+ " --abi Force a particular Python ABI (26, 34, 36, 37)\n"
" --flamechart Include timestamps for generating Chrome "
"\"flamecharts\"\n");
@@ -79,6 +79,9 @@ static const int build_abis[] = {
#ifdef ENABLE_PY36
36,
#endif
+#ifdef ENABLE_PY37
+ 37,
+#endif
};
static_assert(sizeof(build_abis) > 0, "No Python ABIs detected!");
@@ -221,6 +224,9 @@ int Prober::ParseOpts(int argc, char **argv) {
case 36:
abi_ = PyABI::Py36;
break;
+ case 37:
+ abi_ = PyABI::Py37;
+ break;
default:
std::cerr << "Unknown or unsupported ABI version: " << abi_version
<< "\n";
diff --git a/src/ptrace.cc b/src/ptrace.cc
index 610fabb..85483ad 100644
--- a/src/ptrace.cc
+++ b/src/ptrace.cc
@@ -122,6 +122,7 @@ void PtraceInterrupt(pid_t pid) {
DoWait(pid);
}
+#if 0
user_regs_struct PtraceGetRegs(pid_t pid) {
user_regs_struct regs;
if (ptrace(PTRACE_GETREGS, pid, 0, &regs)) {
@@ -139,6 +140,7 @@ void PtraceSetRegs(pid_t pid, user_regs_struct regs) {
throw PtraceException(ss.str());
}
}
+#endif
void PtracePoke(pid_t pid, unsigned long addr, long data) {
if (ptrace(PTRACE_POKEDATA, pid, addr, (void *)data)) {
diff --git a/src/pyfrob.cc b/src/pyfrob.cc
index 7c0588d..b280d96 100644
--- a/src/pyfrob.cc
+++ b/src/pyfrob.cc
@@ -14,6 +14,7 @@
#include "./pyfrob.h"
+#include <cstddef>
#include <fstream>
#include <sstream>
@@ -25,6 +26,8 @@
#include "./ptrace.h"
#include "./symbol.h"
+extern size_t PYFLAME_PYTHON37_OFFSET;
+
#define FROB_FUNCS \
std::vector<Thread> GetThreads(pid_t pid, PyAddresses addr, \
bool enable_threads);
@@ -126,11 +129,20 @@ FROB_FUNCS
}
#endif
+#ifdef ENABLE_PY37
+namespace py37 {
+FROB_FUNCS
+extern size_t tstate_offset;
+}
+#endif
+
// Fill the addrs_ member
int PyFrob::set_addrs_(PyABI *abi) {
Namespace ns(pid_);
try {
addrs_ = Addrs(pid_, &ns, abi);
+ if (*abi >= PyABI::Py37)
+ addrs_.tstate_addr += PYFLAME_PYTHON37_OFFSET;
} catch (const SymbolException &exc) {
return 1;
}
@@ -172,6 +184,11 @@ int PyFrob::DetectABI(PyABI abi) {
case PyABI::Py36:
get_threads_ = py36::GetThreads;
break;
+#endif
+#ifdef ENABLE_PY37
+ case PyABI::Py37:
+ get_threads_ = py37::GetThreads;
+ break;
#endif
default:
std::ostringstream os;
@@ -198,4 +215,5 @@ std::string PyFrob::Status() const {
std::vector<Thread> PyFrob::GetThreads(void) const {
return get_threads_(pid_, addrs_, enable_threads_);
}
+
} // namespace pyflame
diff --git a/src/symbol.cc b/src/symbol.cc
index 39c3e81..3a6123c 100644
--- a/src/symbol.cc
+++ b/src/symbol.cc
@@ -137,31 +137,43 @@ PyABI ELF::WalkTable(int sym, int str, PyAddresses *addrs) {
reinterpret_cast<const sym_t *>(p() + s->sh_offset + i * s->sh_entsize);
const char *name =
reinterpret_cast<const char *>(p() + d->sh_offset + sym->st_name);
- if (!addrs->tstate_addr && strcmp(name, "_PyThreadState_Current") == 0) {
- addrs->tstate_addr = static_cast<unsigned long>(sym->st_value);
- } else if (!addrs->interp_head_addr && strcmp(name, "interp_head") == 0) {
- addrs->interp_head_addr = static_cast<unsigned long>(sym->st_value);
- } else if (!addrs->interp_head_addr &&
- strcmp(name, "PyInterpreterState_Head") == 0) {
- addrs->interp_head_fn_addr = static_cast<unsigned long>(sym->st_value);
- } else if (!have_abi) {
+ if (!addrs->tstate_addr) {
+ if (strcmp(name, "_PyThreadState_Current") == 0) {
+ addrs->tstate_addr = static_cast<unsigned long>(sym->st_value);
+ } else if (strcmp(name, "_PyRuntime") == 0) {
+ addrs->tstate_addr = static_cast<unsigned long>(sym->st_value);
+ }
+ }
+
+ if (!addrs->interp_head_addr) {
+ if (strcmp(name, "interp_head") == 0) {
+ addrs->interp_head_addr = static_cast<unsigned long>(sym->st_value);
+ } else if (strcmp(name, "PyInterpreterState_Head") == 0) {
+ addrs->interp_head_fn_addr = static_cast<unsigned long>(sym->st_value);
+ }
+ }
+
+ if (!have_abi) {
if (strcmp(name, "PyString_Type") == 0) {
// If we find PyString_Type, this is some kind of Python 2.
have_abi = true;
abi = PyABI::Py26;
- } else if (strcmp(name, "PyBytes_Type") == 0) {
+ } else if (strcmp(name, "PyBytes_Type") == 0 && abi < PyABI::Py34) {
// If we find PyBytes_Type, it's Python 3. Continue looping though, in
- // case we see a Python 3.6 symbol.
+ // case we see a Python 3.6+ symbol.
abi = PyABI::Py34;
} else if (strcmp(name, "_PyEval_RequestCodeExtraIndex") == 0 ||
strcmp(name, "_PyCode_GetExtra") == 0 ||
strcmp(name, "_PyCode_SetExtra") == 0) {
// Symbols added for Python 3.6, see:
// https://www.python.org/dev/peps/pep-0523/
- have_abi = true;
abi = PyABI::Py36;
+ } else if (strcmp(name, "_PyRuntime") == 0) {
+ have_abi = true;
+ abi = PyABI::Py37;
}
}
+
}
return abi;
}
diff --git a/src/symbol.h b/src/symbol.h
index bb92b9a..818424d 100644
--- a/src/symbol.h
+++ b/src/symbol.h
@@ -53,7 +53,8 @@ enum class PyABI {
Unknown = 0, // Unknown Python ABI
Py26 = 26, // ABI for Python 2.6/2.7
Py34 = 34, // ABI for Python 3.4/3.5
- Py36 = 36 // ABI for Python 3.6
+ Py36 = 36, // ABI for Python 3.6
+ Py37 = 37 // ABI for Python 3.7
};
// Symbols