Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0e3933d
gh-141770: Annotate anonymous mmap only for debug build
corona10 Nov 28, 2025
8b7023e
Apply annotation feature to modules
corona10 Nov 29, 2025
816d962
Add NEWS.d
corona10 Nov 29, 2025
979ce02
nit
corona10 Nov 29, 2025
b3d8547
Update Include/internal/pycore_pymem.h
corona10 Nov 29, 2025
0c5a495
Address code review
corona10 Nov 29, 2025
e757dd9
Address code review
corona10 Nov 29, 2025
cb9509b
Change annotation prefix
corona10 Nov 30, 2025
855742b
nit
corona10 Nov 30, 2025
32cc007
Address code review
corona10 Dec 1, 2025
49b4f95
Apply suggestions from code review
corona10 Dec 2, 2025
1b88b75
Address code review
corona10 Dec 2, 2025
e2eedbc
Address code review
corona10 Dec 2, 2025
a680677
test
corona10 Dec 3, 2025
8ec4d73
Add Include/internal/pycore_mmap.h
corona10 Dec 3, 2025
c0e08b6
fix
corona10 Dec 3, 2025
e66e650
Update PC
corona10 Dec 3, 2025
b0ca751
Update
corona10 Dec 3, 2025
c9138de
Update Whats News
corona10 Dec 3, 2025
8f77e0d
Merge remote-tracking branch 'upstream/main' into gh-141770
corona10 Dec 4, 2025
8706fce
Address code review
corona10 Dec 4, 2025
8ce8281
lint
corona10 Dec 4, 2025
d71a744
Update
corona10 Dec 4, 2025
4dd1ee4
Address code review
corona10 Dec 4, 2025
fee757e
Apply suggestions from code review
corona10 Dec 5, 2025
a240b3c
Update Objects/obmalloc.c
corona10 Dec 5, 2025
805c539
Address code review
corona10 Dec 5, 2025
795d31c
Update Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-18-14-28.gh-issu…
corona10 Dec 5, 2025
be4d550
Address code review
corona10 Dec 5, 2025
290864a
Address code review
corona10 Dec 5, 2025
b287e0c
nit
corona10 Dec 5, 2025
1619f95
Update Misc/NEWS.d/next/Core_and_Builtins/2025-11-29-18-14-28.gh-issu…
corona10 Dec 6, 2025
a1ad592
Update Include/internal/pycore_mmap.h
corona10 Dec 8, 2025
e4e4835
Update Modules/_ctypes/malloc_closure.c
corona10 Dec 8, 2025
0429a0a
Update Include/internal/pycore_mmap.h
corona10 Dec 8, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1253,6 +1253,12 @@ Build changes
modules that are missing or packaged separately.
(Contributed by Stan Ulbrych and Petr Viktorin in :gh:`139707`.)

* Annotating anonymous mmap usage is now supported if Linux kernel supports
:manpage:`PR_SET_VMA_ANON_NAME <PR_SET_VMA(2const)>` (Linux 5.17 or newer).
Annotations are visible in ``/proc/<pid>/maps`` if the kernel supports the feature
and :option:`-X dev <-X>` is passed to the Python or Python is built in :ref:`debug mode <debug-build>`.
(Contributed by Donghee Na in :gh:`141770`)


Porting to Python 3.15
======================
Expand Down
45 changes: 45 additions & 0 deletions Include/internal/pycore_mmap.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#ifndef Py_INTERNAL_MMAP_H
#define Py_INTERNAL_MMAP_H

#ifdef __cplusplus
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif

#include "pycore_pystate.h"

#if defined(HAVE_PR_SET_VMA_ANON_NAME) && defined(__linux__)
# include <linux/prctl.h>
# include <sys/prctl.h>
#endif

#if defined(HAVE_PR_SET_VMA_ANON_NAME) && defined(__linux__)
static inline void
_PyAnnotateMemoryMap(void *addr, size_t size, const char *name)
{
#ifndef Py_DEBUG
if (!_Py_GetConfig()->dev_mode) {
return;
}
#endif
assert(strlen(name) < 80);
int old_errno = errno;
prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, (unsigned long)addr, size, name);
/* Ignore errno from prctl */
/* See: https://bugzilla.redhat.com/show_bug.cgi?id=2302746 */
errno = old_errno;
}
#else
static inline void
_PyAnnotateMemoryMap(void *Py_UNUSED(addr), size_t Py_UNUSED(size), const char *Py_UNUSED(name))
{
}
#endif

#ifdef __cplusplus
}
#endif
#endif // !Py_INTERNAL_MMAP_H
1 change: 1 addition & 0 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,7 @@ PYTHON_HEADERS= \
$(srcdir)/Include/internal/pycore_long.h \
$(srcdir)/Include/internal/pycore_memoryobject.h \
$(srcdir)/Include/internal/pycore_mimalloc.h \
$(srcdir)/Include/internal/pycore_mmap.h \
$(srcdir)/Include/internal/pycore_modsupport.h \
$(srcdir)/Include/internal/pycore_moduleobject.h \
$(srcdir)/Include/internal/pycore_namespace.h \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Annotate anonymous mmap usage only when supported by the
Linux kernel and if ``-X dev`` is used or Python is built in debug mode. Patch by Donghee Na.
5 changes: 4 additions & 1 deletion Modules/_ctypes/malloc_closure.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
# endif
#endif
#include "ctypes.h"
#include "pycore_mmap.h" // _PyAnnotateMemoryMap()

/* BLOCKSIZE can be adjusted. Larger blocksize will take a larger memory
overhead, but allocate less blocks from the system. It may be that some
Expand Down Expand Up @@ -74,14 +75,16 @@ static void more_core(void)
if (item == NULL)
return;
#else
size_t mem_size = count * sizeof(ITEM);
item = (ITEM *)mmap(NULL,
count * sizeof(ITEM),
mem_size,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS,
-1,
0);
if (item == (void *)MAP_FAILED)
return;
_PyAnnotateMemoryMap(item, mem_size, "cpython:ctypes");
#endif

#ifdef MALLOC_CLOSURE_DEBUG
Expand Down
2 changes: 2 additions & 0 deletions Modules/mmapmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "pycore_abstract.h" // _Py_convert_optional_to_ssize_t()
#include "pycore_bytesobject.h" // _PyBytes_Find()
#include "pycore_fileutils.h" // _Py_stat_struct
#include "pycore_mmap.h" // _PyAnnotateMemoryMap()
#include "pycore_weakref.h" // FT_CLEAR_WEAKREFS()

#include <stddef.h> // offsetof()
Expand Down Expand Up @@ -1951,6 +1952,7 @@ new_mmap_object(PyTypeObject *type, PyObject *args, PyObject *kwdict)
PyErr_SetFromErrno(PyExc_OSError);
return NULL;
}
_PyAnnotateMemoryMap(m_obj->data, map_size, "cpython:mmap");
m_obj->access = (access_mode)access;
return (PyObject *)m_obj;
}
Expand Down
2 changes: 2 additions & 0 deletions Objects/obmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "Python.h"
#include "pycore_interp.h" // _PyInterpreterState_HasFeature
#include "pycore_mmap.h" // _PyAnnotateMemoryMap()
#include "pycore_object.h" // _PyDebugAllocatorStats() definition
#include "pycore_obmalloc.h"
#include "pycore_obmalloc_init.h"
Expand Down Expand Up @@ -467,6 +468,7 @@ _PyMem_ArenaAlloc(void *Py_UNUSED(ctx), size_t size)
if (ptr == MAP_FAILED)
return NULL;
assert(ptr != NULL);
_PyAnnotateMemoryMap(ptr, size, "cpython:pymalloc");
return ptr;
#else
return malloc(size);
Expand Down
1 change: 1 addition & 0 deletions PCbuild/pythoncore.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,7 @@
<ClInclude Include="..\Include\internal\pycore_llist.h" />
<ClInclude Include="..\Include\internal\pycore_lock.h" />
<ClInclude Include="..\Include\internal\pycore_long.h" />
<ClInclude Include="..\Include\internal\pycore_mmap.h" />
<ClInclude Include="..\Include\internal\pycore_modsupport.h" />
<ClInclude Include="..\Include\internal\pycore_moduleobject.h" />
<ClInclude Include="..\Include\internal\pycore_namespace.h" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/pythoncore.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -735,6 +735,9 @@
<ClInclude Include="..\Include\internal\pycore_long.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_mmap.h">
<Filter>Include\internal</Filter>
</ClInclude>
<ClInclude Include="..\Include\internal\pycore_modsupport.h">
<Filter>Include\internal</Filter>
</ClInclude>
Expand Down
4 changes: 4 additions & 0 deletions Python/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "pycore_intrinsics.h"
#include "pycore_list.h"
#include "pycore_long.h"
#include "pycore_mmap.h"
#include "pycore_opcode_metadata.h"
#include "pycore_opcode_utils.h"
#include "pycore_optimizer.h"
Expand Down Expand Up @@ -75,6 +76,9 @@ jit_alloc(size_t size)
int prot = PROT_READ | PROT_WRITE;
unsigned char *memory = mmap(NULL, size, prot, flags, -1, 0);
int failed = memory == MAP_FAILED;
if (!failed) {
_PyAnnotateMemoryMap(memory, size, "cpython:jit");
}
#endif
if (failed) {
jit_error("unable to allocate memory");
Expand Down
2 changes: 2 additions & 0 deletions Python/perf_jit_trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include "pycore_ceval.h" // _PyPerf_Callbacks
#include "pycore_frame.h"
#include "pycore_interp.h"
#include "pycore_mmap.h" // _PyAnnotateMemoryMap()
#include "pycore_runtime.h" // _PyRuntime

#ifdef PY_HAVE_PERF_TRAMPOLINE
Expand Down Expand Up @@ -1085,6 +1086,7 @@ static void* perf_map_jit_init(void) {
close(fd);
return NULL; // Memory mapping failed
}
_PyAnnotateMemoryMap(perf_jit_map_state.mapped_buffer, page_size, "cpython:perf_jit_trampoline");
#endif

perf_jit_map_state.mapped_size = page_size;
Expand Down
2 changes: 2 additions & 0 deletions Python/perf_trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ any DWARF information available for them).
#include "Python.h"
#include "pycore_ceval.h" // _PyPerf_Callbacks
#include "pycore_interpframe.h" // _PyFrame_GetCode()
#include "pycore_mmap.h" // _PyAnnotateMemoryMap()
#include "pycore_runtime.h" // _PyRuntime


Expand Down Expand Up @@ -290,6 +291,7 @@ new_code_arena(void)
perf_status = PERF_STATUS_FAILED;
return -1;
}
_PyAnnotateMemoryMap(memory, mem_size, "cpython:perf_trampoline");
void *start = &_Py_trampoline_func_start;
void *end = &_Py_trampoline_func_end;
size_t code_size = end - start;
Expand Down
19 changes: 19 additions & 0 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5587,6 +5587,13 @@ AC_CHECK_DECLS([UT_NAMESIZE],
[],
[@%:@include <utmp.h>])

AC_CHECK_DECLS([PR_SET_VMA_ANON_NAME],
[AC_DEFINE([HAVE_PR_SET_VMA_ANON_NAME], [1],
[Define if you have the 'PR_SET_VMA_ANON_NAME' constant.])],
[],
[@%:@include <linux/prctl.h>
@%:@include <sys/prctl.h>])

# check for openpty, login_tty, and forkpty

AC_CHECK_FUNCS([openpty], [],
Expand Down
7 changes: 7 additions & 0 deletions pyconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@
/* Define to 1 if you have the <db.h> header file. */
#undef HAVE_DB_H

/* Define to 1 if you have the declaration of 'PR_SET_VMA_ANON_NAME', and to 0
if you don't. */
#undef HAVE_DECL_PR_SET_VMA_ANON_NAME

/* Define to 1 if you have the declaration of 'RTLD_DEEPBIND', and to 0 if you
don't. */
#undef HAVE_DECL_RTLD_DEEPBIND
Expand Down Expand Up @@ -996,6 +1000,9 @@
/* Define if your compiler supports function prototype */
#undef HAVE_PROTOTYPES

/* Define if you have the 'PR_SET_VMA_ANON_NAME' constant. */
#undef HAVE_PR_SET_VMA_ANON_NAME

/* Define to 1 if you have the 'pthread_condattr_setclock' function. */
#undef HAVE_PTHREAD_CONDATTR_SETCLOCK

Expand Down
Loading