1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 23:17:45 +00:00

CPU: Handle breakpoint trap

Also, start working on the debugger app.
This commit is contained in:
Itamar 2020-04-03 14:50:17 +03:00 committed by Andreas Kling
parent c112f53357
commit 77f671b462
10 changed files with 184 additions and 23 deletions

8
Applications/Debugger/Makefile Executable file
View file

@ -0,0 +1,8 @@
OBJS = \
main.o
PROGRAM = Debugger
LIB_DEPS = Core
include ../../Makefile.common

View file

@ -0,0 +1,123 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <AK/Assertions.h>
#include <LibC/sys/arch/i386/regs.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <unistd.h>
static int usage()
{
printf("usage: sdb [command...]\n");
return 1;
}
static int g_pid = -1;
static void handle_sigint(int)
{
if (g_pid == -1)
return;
if (ptrace(PT_DETACH, g_pid, 0, 0) == -1) {
perror("detach");
}
}
void run_child_and_attach(char** argv)
{
int pid = fork();
if (!pid) {
if (ptrace(PT_TRACE_ME, 0, 0, 0) == -1) {
perror("traceme");
return exit(1);
}
int rc = execvp(argv[1], &argv[1]);
if (rc < 0) {
perror("execvp");
exit(1);
}
ASSERT_NOT_REACHED();
}
if (waitpid(pid, nullptr, WSTOPPED) != pid) {
perror("waitpid");
exit(1);
}
g_pid = pid;
}
int main(int argc, char** argv)
{
if (argc == 1)
return usage();
run_child_and_attach(argv);
struct sigaction sa;
memset(&sa, 0, sizeof(struct sigaction));
sa.sa_handler = handle_sigint;
sigaction(SIGINT, &sa, nullptr);
if (ptrace(PT_ATTACH, g_pid, 0, 0) == -1) {
perror("attach");
return 1;
}
if (waitpid(g_pid, nullptr, WSTOPPED) != g_pid) {
perror("waitpid");
return 1;
}
if (ptrace(PT_CONTINUE, g_pid, 0, 0) == -1) {
perror("continue");
}
// wait for breakpoint
if (waitpid(g_pid, nullptr, WSTOPPED) != g_pid) {
perror("waitpid");
return 1;
}
printf("hit breakpoint\n");
sleep(1);
if (ptrace(PT_CONTINUE, g_pid, 0, 0) == -1) {
perror("continue");
}
if (waitpid(g_pid, nullptr, WSTOPPED) != g_pid) {
perror("waitpid");
return 1;
}
}

8
Demos/Debugee/Makefile Normal file
View file

@ -0,0 +1,8 @@
OBJS = \
main.o
PROGRAM = Debugee
# LIB_DEPS = Core
include ../../Makefile.common

8
Demos/Debugee/main.cpp Normal file
View file

@ -0,0 +1,8 @@
#include <cstdio>
int main(int, char**)
{
printf("before breakpoint\n");
asm("int3");
printf("after breakpoint\n");
return 0;
}

View file

@ -297,6 +297,21 @@ void page_fault_handler(RegisterState regs)
} }
} }
EH_ENTRY_NO_CODE(3, breakpoint);
void breakpoint_handler(RegisterState regs)
{
clac();
if (!Process::current || Process::current->is_ring0()) {
klog() << "Breakpoint Trap in Ring0";
hang();
return;
}
if (Thread::current->tracer()) {
Thread::current->tracer()->set_regs(regs);
}
Thread::current->send_urgent_signal_to_self(SIGTRAP);
}
#define EH(i, msg) \ #define EH(i, msg) \
static void _exception##i() \ static void _exception##i() \
{ \ { \
@ -316,7 +331,6 @@ void page_fault_handler(RegisterState regs)
EH(1, "Debug exception") EH(1, "Debug exception")
EH(2, "Unknown error") EH(2, "Unknown error")
EH(3, "Breakpoint")
EH(4, "Overflow") EH(4, "Overflow")
EH(5, "Bounds check") EH(5, "Bounds check")
EH(8, "Double fault") EH(8, "Double fault")
@ -486,7 +500,7 @@ void idt_init()
register_interrupt_handler(0x00, divide_error_asm_entry); register_interrupt_handler(0x00, divide_error_asm_entry);
register_interrupt_handler(0x01, _exception1); register_interrupt_handler(0x01, _exception1);
register_interrupt_handler(0x02, _exception2); register_interrupt_handler(0x02, _exception2);
register_interrupt_handler(0x03, _exception3); register_user_callable_interrupt_handler(0x03, breakpoint_asm_entry);
register_interrupt_handler(0x04, _exception4); register_interrupt_handler(0x04, _exception4);
register_interrupt_handler(0x05, _exception5); register_interrupt_handler(0x05, _exception5);
register_interrupt_handler(0x06, illegal_instruction_asm_entry); register_interrupt_handler(0x06, illegal_instruction_asm_entry);

View file

@ -36,6 +36,7 @@
#include <Kernel/Forward.h> #include <Kernel/Forward.h>
#include <Kernel/KResult.h> #include <Kernel/KResult.h>
#include <Kernel/Scheduler.h> #include <Kernel/Scheduler.h>
#include <Kernel/ThreadTracer.h>
#include <Kernel/UnixTypes.h> #include <Kernel/UnixTypes.h>
#include <LibC/fd_set.h> #include <LibC/fd_set.h>

View file

@ -25,6 +25,7 @@
*/ */
#include <AK/Memory.h> #include <AK/Memory.h>
#include <AK/kmalloc.h>
#include <Kernel/ThreadTracer.h> #include <Kernel/ThreadTracer.h>
namespace Kernel { namespace Kernel {

View file

@ -26,11 +26,8 @@
#pragma once #pragma once
#include <AK/CircularDeque.h>
#include <AK/NonnullOwnPtr.h> #include <AK/NonnullOwnPtr.h>
#include <AK/Optional.h> #include <AK/Optional.h>
#include <AK/RefCounted.h>
#include <Kernel/Arch/i386/CPU.h>
#include <Kernel/UnixTypes.h> #include <Kernel/UnixTypes.h>
#include <LibC/sys/arch/i386/regs.h> #include <LibC/sys/arch/i386/regs.h>

View file

@ -143,8 +143,10 @@ cp ../Applications/DisplayProperties/DisplayProperties mnt/bin/DisplayProperties
cp ../Applications/Welcome/Welcome mnt/bin/Welcome cp ../Applications/Welcome/Welcome mnt/bin/Welcome
cp ../Applications/Help/Help mnt/bin/Help cp ../Applications/Help/Help mnt/bin/Help
cp ../Applications/Browser/Browser mnt/bin/Browser cp ../Applications/Browser/Browser mnt/bin/Browser
cp ../Applications/Debugger/Debugger mnt/bin/sdb
cp ../Games/Solitaire/Solitaire mnt/bin/Solitaire cp ../Games/Solitaire/Solitaire mnt/bin/Solitaire
cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld cp ../Demos/HelloWorld/HelloWorld mnt/bin/HelloWorld
cp ../Demos/Debugee/Debugee mnt/bin/Debugee
cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery cp ../Demos/WidgetGallery/WidgetGallery mnt/bin/WidgetGallery
cp ../Demos/Fire/Fire mnt/bin/Fire cp ../Demos/Fire/Fire mnt/bin/Fire
cp ../Demos/DynamicLink/LinkDemo/LinkDemo mnt/bin/LinkDemo cp ../Demos/DynamicLink/LinkDemo/LinkDemo mnt/bin/LinkDemo

View file

@ -25,25 +25,24 @@
*/ */
#pragma once #pragma once
#include <AK/kmalloc.h> #include <AK/Types.h>
#include <bits/stdint.h>
struct [[gnu::packed]] PtraceRegisters struct [[gnu::packed]] PtraceRegisters
{ {
uint32_t eax; u32 eax;
uint32_t ecx; u32 ecx;
uint32_t edx; u32 edx;
uint32_t ebx; u32 ebx;
uint32_t esp; u32 esp;
uint32_t ebp; u32 ebp;
uint32_t esi; u32 esi;
uint32_t edi; u32 edi;
uint32_t eip; u32 eip;
uint32_t eflags; u32 eflags;
uint32_t cs; u32 cs;
uint32_t ss; u32 ss;
uint32_t ds; u32 ds;
uint32_t es; u32 es;
uint32_t fs; u32 fs;
uint32_t gs; u32 gs;
}; };