Conditional move experiments
example3.c source
Project updated · 12 May 2010
/* * example3.c * - Example program for the "Emulating the CMOV instruction" article. * - This example skips over the "UD2" instructions in the slave process. * * Michal Ludvig <michal@logix.cz> (c) 2003 * Homepage: /devel/cmov-article * * This code is public domain. Use it as you want to, * but don't blame me if something doesn't work as you * expect. */ #define _GNU_SOURCE #include <stdio.h> #include <errno.h> #include <unistd.h> #include <string.h> #include <stdlib.h> #include <signal.h> #include <sys/user.h> #include <sys/wait.h> #include <sys/types.h> #include <sys/ptrace.h> #ifndef offsetof #define offsetof(STRUCT,MEMBER) ((long)&((STRUCT *)0)->MEMBER) #endif void child () { ptrace (PTRACE_TRACEME, 0, NULL, NULL); /* ud2 is an official "Undefined instruction", opcode 0x0f 0x0b */ asm ("ud2"); exit (5); } /* Skip over "ud2" instructions. */ int handle_SIGILL (pid_t pid) { long eip_offset = offsetof (struct user, regs.eip); long eip, opcode; /* Read EIP, i.e. the address where the exception occured. */ eip = ptrace (PTRACE_PEEKUSER, pid, eip_offset, NULL); if (eip == -1 && errno) return -1; /* Read instruction opcode from that address. */ opcode = ptrace (PTRACE_PEEKTEXT, pid, eip, NULL); if (opcode == -1 && errno) return -1; /* Test if it is a "known" instruction, i.e. "ud2". */ if ((opcode & 0x00FF) != 0x0f && (opcode & 0xFF00) >> 8 != 0x0b) return -1; /* Increment the instruction pointer by 2, i.e. skip over "ud2" */ if (ptrace (PTRACE_POKEUSER, pid, eip_offset, eip + 2)) return -1; return 0; } void parent () { int status; pid_t pid; while ((pid = wait4 (-1, &status, WUNTRACED, NULL)) >= 0) { printf ("PID[%lu]: ", pid); if (WIFEXITED (status)) printf ("WEXITSTATUS: %d\n", WEXITSTATUS (status)); else if (WIFSIGNALED (status)) printf ("WTERMSIG: %d (%s)\n", WTERMSIG (status), strsignal (WTERMSIG (status))); else if (WIFSTOPPED (status)) { int signal = WSTOPSIG (status); printf ("WSTOPSIG: %d (%s)\n", signal, strsignal (signal)); if (signal == SIGILL && handle_SIGILL (pid) == 0) signal = 0; ptrace (PTRACE_CONT, pid, NULL, signal); } } } int main () { if (fork ()) parent (); else child (); exit (0); }