From 77844d2619201330bc572006f82a457430e0d015 Mon Sep 17 00:00:00 2001 From: Bill Sommerfeld <sommerfeld@hamachi.org> Date: Fri, 16 Feb 2024 15:40:06 +0100 Subject: [PATCH] python/python39: Turn on CTF for Python 3.9 and fix the pstack helper --- components/python/python39/patches/08-py_db.patch | 111 +++++++++++++++++++++++++++++++++++++------------------ components/python/python39/Makefile | 4 + 2 files changed, 77 insertions(+), 38 deletions(-) diff --git a/components/python/python39/Makefile b/components/python/python39/Makefile index 20f0232..75b1487 100644 --- a/components/python/python39/Makefile +++ b/components/python/python39/Makefile @@ -26,11 +26,13 @@ # USE_OPENSSL11= yes +USE_PARALLEL_BUILD= yes +USE_CTF= yes include ../../../make-rules/shared-macros.mk COMPONENT_NAME= Python COMPONENT_VERSION= 3.9.18 -COMPONENT_REVISION= 1 +COMPONENT_REVISION= 2 PYTHON_VERSION = $(subst $(space),.,$(wordlist 1,2,$(subst ., ,$(COMPONENT_VERSION)))) COMPONENT_SUMMARY= The Python interpreter, libraries and utilities COMPONENT_PROJECT_URL= https://python.org/ diff --git a/components/python/python39/patches/08-py_db.patch b/components/python/python39/patches/08-py_db.patch index 6990c36..d1ec9dc 100644 --- a/components/python/python39/patches/08-py_db.patch +++ b/components/python/python39/patches/08-py_db.patch @@ -37,9 +37,9 @@ if test "x$(ENSUREPIP)" != "xno" ; then \ case $(ENSUREPIP) in \ upgrade) ensurepip="--upgrade" ;; \ ---- Python-3.9.1/py_db/libpython39_db.c -+++ Python-3.9.1/py_db/libpython39_db.c -@@ -0,0 +1,596 @@ +--- Python-3.9.18/py_db/libpython39_db.c.~1~ 2024-02-12 12:48:39.903737823 -0800 ++++ Python-3.9.18/py_db/libpython39_db.c 2024-02-12 13:04:54.724880396 -0800 +@@ -0,0 +1,633 @@ +/* + * CDDL HEADER START + * @@ -79,11 +79,20 @@ + +#include "libpython39_db.h" + ++/* Maximum number of pieces of the core eval function */ ++#define NEVAL 2 ++struct pydb_code_range { ++ uintptr_t base; ++ size_t size; ++}; ++ +struct pydb_agent { + struct ps_prochandle *pdb_ph; + int pdb_vers; -+ int pdb_is_64bit; ++ int pdb_is_64bit:1; ++ int pdb_has_eval:1; + int pdb_datamodel; ++ struct pydb_code_range pdb_eval_code[NEVAL]; +}; + +typedef uintptr_t (*pdi_next_cb_t)(pydb_iter_t *); @@ -191,16 +200,22 @@ + + /* + * Python's line number algorithm is arcane. See here for details: -+ * http://svn.python.org/projects/python/trunk/Objects/lnotab_notes.txt ++ * https://github.com/python/cpython/blob/main/Objects/lnotab_notes.txt + */ + + line = firstline; + for (addr = i = 0; i < lnotab_len; i += 2) { -+ if (addr + lnotab[i] > lastinst) { ++ int addr_incr = lnotab[i]; ++ int line_incr = lnotab[i+1]; ++ ++ addr += addr_incr; ++ if (addr > lastinst) { + break; + } -+ addr += lnotab[i]; -+ line += lnotab[i + 1]; ++ if (line_incr > 0x80) { ++ line_incr -= 0x100; ++ } ++ line += line_incr; + } + + return (line); @@ -336,6 +351,24 @@ + return (read_sz); +} + ++static void ++pydb_find_eval(pydb_agent_t *py) { ++ ps_sym_t psym; ++ ++ if (ps_pglobal_sym(py->pdb_ph, LIBPYTHON, "_PyEval_EvalFrameDefault", &psym) ++ == PS_OK) { ++ py->pdb_eval_code[0].base = psym.st_value; ++ py->pdb_eval_code[0].size = psym.st_size; ++ py->pdb_has_eval = 1; ++ } ++ if (ps_pglobal_sym(py->pdb_ph, LIBPYTHON, "_PyEval_EvalFrameDefault.cold", &psym) ++ == PS_OK) { ++ py->pdb_eval_code[1].base = psym.st_value; ++ py->pdb_eval_code[1].size = psym.st_size; ++ py->pdb_has_eval = 1; ++ } ++} ++ + +static int +pydb_frameinfo(pydb_agent_t *py, uintptr_t addr, char *funcnm, @@ -415,42 +448,46 @@ + * Return a description about a PyFrameObject, if the object is + * actually a PyFrameObject. In this case, the pc argument is checked + * to make sure that it came from a function that takes a PyFrameObject -+ * as its first (argv[0]) argument. ++ * as its second (argv[1]) argument. + */ +int -+pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc, uintptr_t frame_addr, ++pydb_pc_frameinfo_argv(pydb_agent_t *py, uintptr_t pc, const long *argv, + char *fbuf, size_t bufsz) +{ + char funcname[1024]; + char filename[1024]; + int lineno; -+ int rc; -+ ps_sym_t psym; ++ int i, rc; ++ uintptr_t frame_addr = argv[1]; ++ ++ if (!py->pdb_has_eval) { ++ pydb_find_eval(py); ++ if (!py->pdb_has_eval) ++ return (-1); ++ } + + /* -+ * If PC doesn't match PyEval_EvalFrameEx in either libpython -+ * or the executable, don't decode it. ++ * If the PC isn't inside one of the eval code ranges, ++ * don't decode it. + */ -+ if (ps_pglobal_sym(py->pdb_ph, LIBPYTHON, "PyEval_EvalFrameEx", &psym) -+ != PS_OK) { -+ return (-1); ++ for (i = 0; i < NEVAL; i++) { ++ struct pydb_code_range *r = &py->pdb_eval_code[i]; ++ ++ if (pc >= r->base && pc < (r->base + r->size)) { ++ ++ rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname), ++ filename, sizeof (filename), &lineno); ++ if (rc < 0) { ++ return (-1); ++ } ++ ++ (void) snprintf(fbuf, bufsz, "[ %s:%d (%s) ]\n", filename, lineno, ++ funcname); ++ return (0); ++ } + } + -+ /* If symbol found, ensure that PC falls within PyEval_EvalFrameEx. */ -+ if (pc < psym.st_value || pc > psym.st_value + psym.st_size) { -+ return (-1); -+ } -+ -+ rc = pydb_frameinfo(py, frame_addr, funcname, sizeof (funcname), -+ filename, sizeof (filename), &lineno); -+ if (rc < 0) { -+ return (-1); -+ } -+ -+ (void) snprintf(fbuf, bufsz, "[ %s:%d (%s) ]\n", filename, lineno, -+ funcname); -+ -+ return (0); ++ return (-1); +} + +/* @@ -636,8 +673,8 @@ + + free(iter); +} ---- Python-3.9.1/py_db/libpython39_db.h -+++ Python-3.9.1/py_db/libpython39_db.h +--- Python-3.9.18/py_db/libpython39_db.h.~1~ 2024-02-12 12:48:39.904029254 -0800 ++++ Python-3.9.18/py_db/libpython39_db.h 2024-02-12 13:04:59.939924305 -0800 @@ -0,0 +1,73 @@ +/* + * CDDL HEADER START @@ -693,8 +730,8 @@ + * Used by callers that don't know if they're looking at PyFrameObject. + * Checks PC for traceable functions. + */ -+extern int pydb_pc_frameinfo(pydb_agent_t *py, uintptr_t pc, -+ uintptr_t frame_addr, char *fbuf, size_t bufsz); ++extern int pydb_pc_frameinfo_argv(pydb_agent_t *py, uintptr_t pc, ++ const long *argv, char *fbuf, size_t bufsz); + +/* Iterator functions */ +typedef struct pydb_iter pydb_iter_t; @@ -746,7 +783,7 @@ + pydb_agent_destroy; + pydb_frame_iter_init; + pydb_get_frameinfo; -+ pydb_pc_frameinfo; ++ pydb_pc_frameinfo_argv; + pydb_interp_iter_init; + pydb_thread_iter_init; + pydb_iter_fini; -- Gitblit v1.9.3