OSX系统下编译ptrace()程序报错,如何正确使用ptrace()?
ptrace() on macOS: Fixing Compilation & Runtime Issues Hey there! I’ve dealt with this exact frustration before—macOS’s ptrace() has some key differences from Linux that trip up a lot of folks. Let’s break down how to get your C program compiling and running properly.
First, Understand the macOS vs. Linux ptrace() Differences
The biggest gotcha is that macOS uses different request codes than Linux. Instead of PTRACE_ATTACH, PTRACE_CONT, etc., macOS uses PT_ATTACH, PT_CONTINUE, and other constants prefixed with PT_ instead of PTRACE_. Using Linux-style constants will throw "undeclared identifier" errors immediately.
Step 1: Include the Correct Headers
Make sure your program includes the macOS-specific header for ptrace():
#include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <errno.h>
<sys/ptrace.h> is where macOS defines ptrace() and all its PT_* request codes. The other headers handle process management, waiting, and error reporting.
Step 2: Write a Minimal Working Example
Here’s a simple demo that traces a child process (avoids most permission headaches initially):
#include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <stdio.h> #include <errno.h> int main() { pid_t child_pid = fork(); if (child_pid == 0) { // Child process: Allow tracing if (ptrace(PT_TRACE_ME, 0, NULL, 0) == -1) { perror("Child: PT_TRACE_ME failed"); return 1; } // Execute a simple command to trace execl("/bin/echo", "echo", "Hello from traced process!", NULL); perror("Child: execl failed"); return 1; } else if (child_pid > 0) { // Parent process: Wait for child to stop after PT_TRACE_ME int status; waitpid(child_pid, &status, 0); // Attach to the child (optional here since PT_TRACE_ME already enables tracing) if (ptrace(PT_ATTACH, child_pid, NULL, 0) == -1) { perror("Parent: PT_ATTACH failed"); return 1; } // Resume the child process if (ptrace(PT_CONTINUE, child_pid, (caddr_t)1, 0) == -1) { perror("Parent: PT_CONTINUE failed"); return 1; } // Wait for child to finish execution waitpid(child_pid, &status, 0); printf("Parent: Trace completed successfully\n"); } else { perror("Fork failed"); return 1; } return 0; }
Step 3: Compile & Run Correctly
Compilation Command
Use macOS’s default compiler (cc, which is Clang under the hood—avoid using a Homebrew-installed GCC unless you know what you’re doing):
cc -o ptrace_demo ptrace_demo.c
If you get linker errors, double-check that you’re not excluding system libraries (the default command links against libSystem.dylib, which includes ptrace()).
Runtime Permissions
macOS’s System Integrity Protection (SIP) restricts tracing for system processes and processes owned by other users. For your own child processes:
- You can run the program normally if you’re tracing a process you started.
- If you get a
ptrace: Operation not permittederror, try running withsudo:sudo ./ptrace_demo
Avoid disabling SIP unless you absolutely need to trace system-level processes—it’s a security feature.
Fixing Common Compilation Errors
- "Undeclared identifier 'PTRACE_ATTACH'": Replace all Linux-style
PTRACE_*constants with macOS’sPT_*equivalents (checkman ptracefor the full list). - "Implicit declaration of function 'ptrace'": You forgot to include
<sys/ptrace.h>—add that header to your program. - Linker errors: Ensure you’re using the system compiler (
cc) and not a cross-compiler targeting Linux.
Check the Manual for More Details
For a full list of supported PT_* requests and behavior, run the man page in your terminal:
man ptrace
It’s the most reliable source for macOS-specific ptrace() usage.
内容的提问来源于stack exchange,提问作者Alexander Mills

