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);
}