https://github.com/python/cpython/commit/fb313a3948fb27e18f68c1df9deaa79c2fd394f2
commit: fb313a3948fb27e18f68c1df9deaa79c2fd394f2
branch: 3.14
author: Maurycy Pawłowski-Wieroński <[email protected]>
committer: pablogsal <[email protected]>
date: 2026-10-06T17:13:01+01:00
summary:

[3.14] gh-158539: Fix macOS runtime section lookup for remote debugging 
(GH-158874) (#158906)

files:
A Misc/NEWS.d/next/Library/2026-10-05-18-00-01.gh-issue-158539.k8Lv2a.rst
M Python/remote_debug.h

diff --git 
a/Misc/NEWS.d/next/Library/2026-10-05-18-00-01.gh-issue-158539.k8Lv2a.rst 
b/Misc/NEWS.d/next/Library/2026-10-05-18-00-01.gh-issue-158539.k8Lv2a.rst
new file mode 100644
index 00000000000000..aadac290075abf
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-10-05-18-00-01.gh-issue-158539.k8Lv2a.rst
@@ -0,0 +1,2 @@
+Fix macOS runtime section lookup for remote debugging when virtual memory
+region sizes differ from Mach-O segment file sizes.
diff --git a/Python/remote_debug.h b/Python/remote_debug.h
index 7f963b3243ecb6..4120f3d0d96797 100644
--- a/Python/remote_debug.h
+++ b/Python/remote_debug.h
@@ -274,7 +274,6 @@ _Py_RemoteDebug_CleanupProcHandle(proc_handle_t *handle) {
 static uintptr_t
 return_section_address64(
     const char* section,
-    mach_port_t proc_ref,
     uintptr_t base,
     void* map
 ) {
@@ -284,11 +283,6 @@ return_section_address64(
     int cmd_cnt = 0;
     struct segment_command_64* cmd = map + sizeof(struct mach_header_64);
 
-    mach_vm_size_t size = 0;
-    mach_msg_type_number_t count = sizeof(vm_region_basic_info_data_64_t);
-    mach_vm_address_t address = (mach_vm_address_t)base;
-    vm_region_basic_info_data_64_t r_info;
-    mach_port_t object_name;
     uintptr_t vmaddr = 0;
 
     for (int i = 0; cmd_cnt < 2 && i < ncmds; i++) {
@@ -296,25 +290,8 @@ return_section_address64(
             vmaddr = cmd->vmaddr;
         }
         if (cmd->cmd == LC_SEGMENT_64 && strcmp(cmd->segname, "__DATA") == 0) {
-            while (cmd->filesize != size) {
-                address += size;
-                kern_return_t ret = mach_vm_region(
-                    proc_ref,
-                    &address,
-                    &size,
-                    VM_REGION_BASIC_INFO_64,
-                    (vm_region_info_t)&r_info,  // cppcheck-suppress 
[uninitvar]
-                    &count,
-                    &object_name
-                );
-                if (ret != KERN_SUCCESS) {
-                    PyErr_Format(PyExc_RuntimeError,
-                        "mach_vm_region failed while parsing 64-bit Mach-O 
binary "
-                        "at base address 0x%lx (kern_return_t: %d)",
-                        base, ret);
-                    return 0;
-                }
-            }
+            // The section address only needs the image's ASLR slide.
+            // VM regions need not match the segment's on-disk size.
 
             int nsects = cmd->nsects;
             struct section_64* sec = (struct section_64*)(
@@ -337,7 +314,6 @@ return_section_address64(
 static uintptr_t
 return_section_address32(
     const char* section,
-    mach_port_t proc_ref,
     uintptr_t base,
     void* map
 ) {
@@ -347,11 +323,6 @@ return_section_address32(
     int cmd_cnt = 0;
     struct segment_command* cmd = map + sizeof(struct mach_header);
 
-    mach_vm_size_t size = 0;
-    mach_msg_type_number_t count = sizeof(vm_region_basic_info_data_t);
-    mach_vm_address_t address = (mach_vm_address_t)base;
-    vm_region_basic_info_data_t r_info;
-    mach_port_t object_name;
     uintptr_t vmaddr = 0;
 
     for (int i = 0; cmd_cnt < 2 && i < ncmds; i++) {
@@ -359,25 +330,8 @@ return_section_address32(
             vmaddr = cmd->vmaddr;
         }
         if (cmd->cmd == LC_SEGMENT && strcmp(cmd->segname, "__DATA") == 0) {
-            while (cmd->filesize != size) {
-                address += size;
-                kern_return_t ret = mach_vm_region(
-                    proc_ref,
-                    &address,
-                    &size,
-                    VM_REGION_BASIC_INFO,
-                    (vm_region_info_t)&r_info,  // cppcheck-suppress 
[uninitvar]
-                    &count,
-                    &object_name
-                );
-                if (ret != KERN_SUCCESS) {
-                    PyErr_Format(PyExc_RuntimeError,
-                        "mach_vm_region failed while parsing 32-bit Mach-O 
binary "
-                        "at base address 0x%lx (kern_return_t: %d)",
-                        base, ret);
-                    return 0;
-                }
-            }
+            // The section address only needs the image's ASLR slide.
+            // VM regions need not match the segment's on-disk size.
 
             int nsects = cmd->nsects;
             struct section* sec = (struct section*)(
@@ -400,7 +354,6 @@ return_section_address32(
 static uintptr_t
 return_section_address_fat(
     const char* section,
-    mach_port_t proc_ref,
     uintptr_t base,
     void* map
 ) {
@@ -450,11 +403,11 @@ return_section_address_fat(
             switch (hdr->magic) {
                 case MH_MAGIC:
                 case MH_CIGAM:
-                    return return_section_address32(section, proc_ref, base, 
(void*)hdr);
+                    return return_section_address32(section, base, (void*)hdr);
 
                 case MH_MAGIC_64:
                 case MH_CIGAM_64:
-                    return return_section_address64(section, proc_ref, base, 
(void*)hdr);
+                    return return_section_address64(section, base, (void*)hdr);
 
                 default:
                     PyErr_Format(PyExc_RuntimeError,
@@ -473,7 +426,7 @@ return_section_address_fat(
 }
 
 static uintptr_t
-search_section_in_file(const char* secname, char* path, uintptr_t base, 
mach_vm_size_t size, mach_port_t proc_ref)
+search_section_in_file(const char* secname, char* path, uintptr_t base)
 {
     int fd = open(path, O_RDONLY);
     if (fd == -1) {
@@ -510,15 +463,15 @@ search_section_in_file(const char* secname, char* path, 
uintptr_t base, mach_vm_
     switch (magic) {
     case MH_MAGIC:
     case MH_CIGAM:
-        result = return_section_address32(secname, proc_ref, base, map);
+        result = return_section_address32(secname, base, map);
         break;
     case MH_MAGIC_64:
     case MH_CIGAM_64:
-        result = return_section_address64(secname, proc_ref, base, map);
+        result = return_section_address64(secname, base, map);
         break;
     case FAT_MAGIC:
     case FAT_CIGAM:
-        result = return_section_address_fat(secname, proc_ref, base, map);
+        result = return_section_address_fat(secname, base, map);
         break;
     default:
         PyErr_Format(PyExc_RuntimeError,
@@ -621,7 +574,7 @@ search_map_for_section(proc_handle_t *handle, const char* 
secname, const char* s
         if (strncmp(filename, substr, strlen(substr)) == 0) {
             PyErr_Clear();
             uintptr_t result = search_section_in_file(
-                secname, map_filename, address, size, proc_ref);
+                secname, map_filename, address);
             if (result != 0) {
                 if (validator == NULL || validator(handle, result)) {
                     return result;

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to