2026. 9. 1. 11:07

Remote debug of macOS application using Xcode

https://medium.com/@alkenso/remote-debug-of-macos-application-using-xcode-1d714d6314bb

 

Remote debug of macOS application using Xcode

Note: my goal is create short and accurate guide about macOS remote debugging, to be used as fast reference

medium.com

Summary

  1. Turn on Xcode feature
    • defaults write com.apple.dt.Xcode IDEDebuggerFeatureSetting 12
  2. Copy 'debugserver' to the target VM
    • From "/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Versions/A/Resources/debugserver"
  3. Lauch and debug the app
    • In target VM
      • Attach
        • ./debugserver ip:port --attach=pid
        • ./debugserver ip:port --attach=name
      • Lauch
        • ./debugserver ip:port /path/to/executable
    • In Host
      • Switch Lauch to 'Custom LLDM commands' in Scheme > Info
        • Enter the command 'process connect connect://ip:port'
  4. Collect debug symbols of the target VM
    1. Collect debug symbols from the target machine using 'dyld-shared-cache-extractor'
    2. Get OS version and build number
      1. sw_vers -productVersion → 12.6.1
      2. sw_vers -buildVersion → 21G217
    3. Copy all symbols under ~/Library/Developer/Xcode/macOS DeviceSupport/12.6.1 (21G217)
    4. Restart Xcode
2025. 5. 23. 18:47

A lambda to a pointer to function

Recently, I changed the lambda code to capture a local variable, and then the code didn't compile.
What I found was that only a lambda without capture can be converted to a function pointer.

 

[expr.prim.lambda]

The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type's function call operator. The value returned by this conversion function shall be the address of a function that, when invoked, has the same effect as invoking the closure type's function call operator.
2025. 1. 10. 18:14

How to change the parent process when calling CreateProcess API

Usually, the parent process is the process that creats the new process. But you can change this behavior by setting STARTUPINFOEX.lpAttributeList.

HANDLE hParentProcess{ nullptr };
LPPROC_THREAD_ATTRIBUTE_LIST attrList{ nullptr };


// Initialize LPPROC_THREAD_ATTRIBUTE_LIST
hParentProcess = OpenProcess(PROCESS_CREATE_PROCESS, FALSE, parentProcessId);

SIZE_T attrListSize = 0;
InitializeProcThreadAttributeList(nullptr, 1, 0, &attrListSize);
attrList = (LPPROC_THREAD_ATTRIBUTE_LIST)malloc(attrListSize);

InitializeProcThreadAttributeList(attrList, 1, 0, &attrListSize);

UpdateProcThreadAttribute(attrList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &hParentProcess,
	sizeof(hParentProcess), nullptr, nullptr);


// Set LPPROC_THREAD_ATTRIBUTE_LIST to the STARTUPINFOEX
STARTUPINFOEX  si = { sizeof(si) };
si.StartupInfo.cb = sizeof(si);
si.lpAttributeList = attrList;

PROCESS_INFORMATION pi = { 0 };


CreateProcess(nullptr, argv[1], nullptr, nullptr, FALSE, EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, &si.StartupInfo, &pi);