From ba0bbba6c69abbee480717e1ecf853fbdf81cee5 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 26 Jun 2025 10:54:47 -0600 Subject: [PATCH 1/2] Before this change it was not possible to attach to a process on arm64 mac. The primary issue was that we weren't building the attach.dylib for all targets; but even once we did that we had to ensure that we were exiting successfully after injecting into the process. We pulled in the compile changes from https://github.com/JetBrains/intellij-community/commit/2e7109f6fe37cf3ba74778b72bfbe9ddeb8ca4b4 Co-authored-by: @artemmukhin Co-authored-by: Cole Miller --- build_attach_binaries.py | 14 +++++++++----- .../add_code_to_python_process.py | 9 ++++++--- .../linux_and_mac/compile_mac.sh | 18 ++++++++++++++---- src/debugpy/_vendored/pydevd/pydevd_tracing.py | 5 +++-- 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/build_attach_binaries.py b/build_attach_binaries.py index dc38fa08e..317f07980 100644 --- a/build_attach_binaries.py +++ b/build_attach_binaries.py @@ -1,6 +1,7 @@ # This script is used for building the pydevd binaries import argparse import os +import platform def build_pydevd_binaries(force: bool): os.environ["PYDEVD_USE_CYTHON"] = "yes" @@ -20,16 +21,19 @@ def build_pydevd_binaries(force: bool): # Run the appropriate batch script to build the binaries if necessary. pydevd_attach_to_process_root = os.path.join(pydevd_root, "pydevd_attach_to_process") - if os.name == "nt": + if platform.system() == "Windows": if not os.path.exists(os.path.join(pydevd_attach_to_process_root, "attach_amd64.dll")) or force: os.system(os.path.join(pydevd_attach_to_process_root, "windows", "compile_windows.bat")) - elif os.name == "posix": + elif platform.system() == "Linux": if not os.path.exists(os.path.join(pydevd_attach_to_process_root, "attach_linux_amd64.so")) or force: os.system(os.path.join(pydevd_attach_to_process_root, "linux_and_mac", "compile_linux.sh")) - else: - if not os.path.exists(os.path.join(pydevd_attach_to_process_root, "attach_x86_64.dylib")) or force: + elif platform.system() == "Darwin": + if not os.path.exists(os.path.join(pydevd_attach_to_process_root, "attach.dylib")) or force: os.system(os.path.join(pydevd_attach_to_process_root, "linux_and_mac", "compile_mac.sh")) - + else: + print("unsupported platform.system(): {}".format(platform.system())) + exit(1) + if __name__ == "__main__": arg_parser = argparse.ArgumentParser(description="Build the pydevd binaries.") diff --git a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py index 2e328f617..8f5372cbc 100644 --- a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py +++ b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/add_code_to_python_process.py @@ -183,7 +183,7 @@ def get_target_filename(is_target_process_64=None, prefix=None, extension=None): print("Unable to attach to process in platform: %s", sys.platform) return None - if arch.lower() not in ("amd64", "x86", "x86_64", "i386", "x86"): + if arch.lower() not in ("arm64", "amd64", "x86", "x86_64", "i386", "x86"): # We don't support this processor by default. Still, let's support the case where the # user manually compiled it himself with some heuristics. # @@ -237,8 +237,11 @@ def get_target_filename(is_target_process_64=None, prefix=None, extension=None): if not prefix: # Default is looking for the attach_ / attach_linux - if IS_WINDOWS or IS_MAC: # just the extension changes + if IS_WINDOWS: # just the extension changes prefix = "attach_" + elif IS_MAC: + prefix = "attach" + suffix = "" elif IS_LINUX: prefix = "attach_linux_" # historically it has a different name else: @@ -525,7 +528,7 @@ def run_python_code_mac(pid, python_code, connect_debugger_tracing=False, show_d cmd.extend( [ "-o 'process detach'", - "-o 'script import os; os._exit(1)'", + "-o 'script import os; os._exit(0)'", ] ) diff --git a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh index 34a65b755..537148c58 100755 --- a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh +++ b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh @@ -1,4 +1,14 @@ -set -e -SRC="$(dirname "$0")/.." -g++ -fPIC -D_REENTRANT -std=c++11 -D_FORTIFY_SOURCE=2 -arch x86_64 -c $SRC/linux_and_mac/attach.cpp -o $SRC/attach_x86_64.o -g++ -dynamiclib -nostartfiles -arch x86_64 -lc $SRC/attach_x86_64.o -o $SRC/attach_x86_64.dylib +#!/bin/bash +set -euxo pipefail + +clang++ -fPIC -D_REENTRANT -std=c++11 -arch arm64 -c -o attach_arm64.o attach.cpp +clang++ -dynamiclib -nostartfiles -arch arm64 -o attach_arm64.dylib attach_arm64.o -lc +rm attach_arm64.o + +clang++ -fPIC -D_REENTRANT -std=c++11 -arch x86_64 -c -o attach_x86_64.o attach.cpp +clang++ -dynamiclib -nostartfiles -arch x86_64 -o attach_x86_64.dylib attach_x86_64.o -lc +rm attach_x86_64.o + +lipo -create attach_arm64.dylib attach_x86_64.dylib -output attach.dylib +rm attach_arm64.dylib attach_x86_64.dylib +mv attach.dylib ../attach.dylib diff --git a/src/debugpy/_vendored/pydevd/pydevd_tracing.py b/src/debugpy/_vendored/pydevd/pydevd_tracing.py index dca75d330..41135d7dc 100644 --- a/src/debugpy/_vendored/pydevd/pydevd_tracing.py +++ b/src/debugpy/_vendored/pydevd/pydevd_tracing.py @@ -201,7 +201,7 @@ def get_python_helper_lib_filename(): pydev_log.info("Unable to set trace to all threads in platform: %s", sys.platform) return None - if arch.lower() not in ("amd64", "x86", "x86_64", "i386", "x86"): + if arch.lower() not in ("arm64", "amd64", "x86", "x86_64", "i386", "x86"): # We don't support this processor by default. Still, let's support the case where the # user manually compiled it himself with some heuristics. # @@ -251,7 +251,8 @@ def get_python_helper_lib_filename(): suffix = suffix_32 if IS_WINDOWS or IS_MAC: # just the extension changes - prefix = "attach_" + prefix = "attach" + suffix = "" elif IS_LINUX: # prefix = "attach_linux_" # historically it has a different name else: From 75e41b5918dab29815e55a6fa9d927008c4bac26 Mon Sep 17 00:00:00 2001 From: Conrad Irwin Date: Thu, 26 Jun 2025 11:18:21 -0600 Subject: [PATCH 2/2] Use g++ on macOS (with -D_FORTIFY_SOURCE=2) --- .../linux_and_mac/compile_mac.sh | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh index 537148c58..9e8794c63 100755 --- a/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh +++ b/src/debugpy/_vendored/pydevd/pydevd_attach_to_process/linux_and_mac/compile_mac.sh @@ -1,14 +1,14 @@ #!/bin/bash -set -euxo pipefail +set -e +SRC="$(dirname "$0")/.." -clang++ -fPIC -D_REENTRANT -std=c++11 -arch arm64 -c -o attach_arm64.o attach.cpp -clang++ -dynamiclib -nostartfiles -arch arm64 -o attach_arm64.dylib attach_arm64.o -lc -rm attach_arm64.o +g++ -fPIC -D_REENTRANT -std=c++11 -D_FORTIFY_SOURCE=2 -arch arm64 -c -o "$SRC/attach_arm64.o" "$SRC/linux_and_mac/attach.cpp" +g++ -dynamiclib -nostartfiles -arch arm64 -o "$SRC/attach_arm64.dylib" "$SRC/attach_arm64.o" -lc +rm "$SRC/attach_arm64.o" -clang++ -fPIC -D_REENTRANT -std=c++11 -arch x86_64 -c -o attach_x86_64.o attach.cpp -clang++ -dynamiclib -nostartfiles -arch x86_64 -o attach_x86_64.dylib attach_x86_64.o -lc -rm attach_x86_64.o +g++ -fPIC -D_REENTRANT -std=c++11 -D_FORTIFY_SOURCE=2 -arch x86_64 -c -o "$SRC/attach_x86_64.o" "$SRC/linux_and_mac/attach.cpp" +g++ -dynamiclib -nostartfiles -arch x86_64 -o "$SRC/attach_x86_64.dylib" "$SRC/attach_x86_64.o" -lc +rm "$SRC/attach_x86_64.o" -lipo -create attach_arm64.dylib attach_x86_64.dylib -output attach.dylib -rm attach_arm64.dylib attach_x86_64.dylib -mv attach.dylib ../attach.dylib +lipo -create "$SRC/attach_arm64.dylib" "$SRC/attach_x86_64.dylib" -output "$SRC/attach.dylib" +rm "$SRC/attach_arm64.dylib" "$SRC/attach_x86_64.dylib"