L4Re - L4 Runtime Environment
examples/sys/singlestep/main.c

This example shows how a thread can be single stepped on the x86 architecture.

/*
* (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
* Alexander Warg <warg@os.inf.tu-dresden.de>,
* Björn Döbel <doebel@os.inf.tu-dresden.de>
* economic rights: Technische Universität Dresden (Germany)
*
* This file is part of TUD:OS and distributed under the terms of the
* GNU General Public License 2.
* Please see the COPYING-GPL-2 file for details.
*/
/*
* Single stepping example for the x86-32 architecture.
*/
#include <l4/sys/ipc.h>
#include <l4/sys/factory.h>
#include <l4/sys/thread.h>
#include <l4/sys/utcb.h>
#include <l4/sys/kdebug.h>
#include <l4/util/util.h>
#include <l4/re/env.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static char thread_stack[8 << 10];
static void thread_func(void)
{
while (1)
{
unsigned long d = 0;
/* Enable single stepping */
asm volatile("pushf; pop %0; or $256,%0; push %0; popf\n"
: "=r" (d) : "r" (d));
/* Some instructions */
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("mov $0x12345000, %%edx" : : : "edx"); // a non-existent cap
asm volatile("int $0x30\n");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
/* Disabled single stepping */
asm volatile("pushf; pop %0; and $~256,%0; push %0; popf\n"
: "=r" (d) : "r" (d));
/* You won't see those */
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
}
int main(void)
{
int ipc_stat = 0;
l4_umword_t mr0, mr1;
printf("Singlestep testing\n");
return 1;
l4_touch_rw(thread_stack, sizeof(thread_stack));
l4_touch_ro(thread_func, 1);
tag = l4_factory_create_thread(l4re_env()->factory, th);
if (l4_error(tag))
return 1;
l4_thread_control_bind((l4_utcb_t *)l4re_env()->first_free_utcb,
L4RE_THIS_TASK_CAP);
if (l4_error(tag))
return 2;
tag = l4_thread_ex_regs(th, (l4_umword_t)thread_func,
(l4_umword_t)thread_stack + sizeof(thread_stack),
0);
if (l4_error(tag))
return 3;
tag = l4_scheduler_run_thread(l4re_env()->scheduler, th, &sp);
if (l4_error(tag))
return 4;
/* Pager/Exception loop */
{
printf("l4_ipc_receive failed");
return 5;
}
memcpy(&exc, l4_utcb_exc(), sizeof(exc));
mr0 = l4_utcb_mr()->mr[0];
mr1 = l4_utcb_mr()->mr[1];
for (;;)
{
{
printf("PC = %08lx Trap = %08lx Err = %08lx, SP = %08lx SC-Nr: %lx\n",
l4_utcb_exc_pc(&exc), exc.trapno, exc.err,
exc.sp, exc.err >> 3);
if (exc.err >> 3)
{
if (!(exc.err & 4))
{
if (ipc_stat)
enter_kdebug("Should not be 1");
}
else
{
if (!ipc_stat)
enter_kdebug("Should not be 0");
}
ipc_stat = !ipc_stat;
}
l4_sleep(100);
}
else
printf("Umm, non-handled request: %ld, %08lx %08lx\n",
l4_msgtag_label(tag), mr0, mr1);
memcpy(l4_utcb_exc(), &exc, sizeof(exc));
/* Reply and wait */
if (l4_msgtag_has_error(tag = l4_ipc_call(th, u, tag, L4_IPC_NEVER)))
{
printf("l4_ipc_call failed\n");
return 5;
}
memcpy(&exc, l4_utcb_exc(), sizeof(exc));
mr0 = l4_utcb_mr()->mr[0];
mr1 = l4_utcb_mr()->mr[1];
}
return 0;
}