summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGunnar Beutner <gbeutner@serenityos.org>2021-06-26 14:56:28 +0200
committerAndreas Kling <kling@serenityos.org>2021-06-27 15:46:42 +0200
commit233ef26e4d67e6916de7829d880d78bbc2b6dd82 (patch)
tree6e1dc19888d510a53d3ec700bbbf56a54d27ef64
parent10ca7f18a7e46a67deb3d69db435ff127391f8ed (diff)
downloadserenity-233ef26e4d67e6916de7829d880d78bbc2b6dd82.zip
Kernel+Userland: Add x86_64 registers to RegisterState/PtraceRegisters
-rw-r--r--Kernel/Arch/x86/RegisterState.h73
-rw-r--r--Kernel/Arch/x86/common/Interrupts.cpp38
-rw-r--r--Kernel/PerformanceManager.h12
-rw-r--r--Kernel/Scheduler.cpp3
-rw-r--r--Kernel/Syscall.cpp56
-rw-r--r--Kernel/Syscalls/get_stack_bounds.cpp8
-rw-r--r--Kernel/Thread.cpp10
-rw-r--r--Userland/Applications/CrashReporter/main.cpp12
-rw-r--r--Userland/Libraries/LibC/sys/arch/i386/regs.h21
-rw-r--r--Userland/Libraries/LibDebug/DebugInfo.cpp8
-rw-r--r--Userland/Libraries/LibDebug/DebugSession.cpp8
-rw-r--r--Userland/Libraries/LibDebug/DebugSession.h27
-rw-r--r--Userland/Utilities/strace.cpp12
13 files changed, 265 insertions, 23 deletions
diff --git a/Kernel/Arch/x86/RegisterState.h b/Kernel/Arch/x86/RegisterState.h
index 0f0d2f3a5f..299eecf361 100644
--- a/Kernel/Arch/x86/RegisterState.h
+++ b/Kernel/Arch/x86/RegisterState.h
@@ -15,6 +15,7 @@
namespace Kernel {
struct [[gnu::packed]] RegisterState {
+#if ARCH(I386)
FlatPtr ss;
FlatPtr gs;
FlatPtr fs;
@@ -28,27 +29,55 @@ struct [[gnu::packed]] RegisterState {
FlatPtr edx;
FlatPtr ecx;
FlatPtr eax;
+#else
+ FlatPtr rdi;
+ FlatPtr rsi;
+ FlatPtr rbp;
+ FlatPtr rsp;
+ FlatPtr rbx;
+ FlatPtr rdx;
+ FlatPtr rcx;
+ FlatPtr rax;
+ FlatPtr r8;
+ FlatPtr r9;
+ FlatPtr r10;
+ FlatPtr r11;
+ FlatPtr r12;
+ FlatPtr r13;
+ FlatPtr r14;
+ FlatPtr r15;
+#endif
u16 exception_code;
u16 isr_number;
#if ARCH(X86_64)
u32 padding;
#endif
+#if ARCH(I386)
FlatPtr eip;
+#else
+ FlatPtr rip;
+#endif
FlatPtr cs;
+#if ARCH(I386)
FlatPtr eflags;
FlatPtr userspace_esp;
FlatPtr userspace_ss;
+#else
+ FlatPtr rflags;
+ FlatPtr userspace_rsp;
+#endif
};
#if ARCH(I386)
# define REGISTER_STATE_SIZE (19 * 4)
#else
-# define REGISTER_STATE_SIZE (19 * 8)
+# define REGISTER_STATE_SIZE (21 * 8)
#endif
static_assert(REGISTER_STATE_SIZE == sizeof(RegisterState));
inline void copy_kernel_registers_into_ptrace_registers(PtraceRegisters& ptrace_regs, const RegisterState& kernel_regs)
{
+#if ARCH(I386)
ptrace_regs.eax = kernel_regs.eax,
ptrace_regs.ecx = kernel_regs.ecx,
ptrace_regs.edx = kernel_regs.edx,
@@ -59,6 +88,26 @@ inline void copy_kernel_registers_into_ptrace_registers(PtraceRegisters& ptrace_
ptrace_regs.edi = kernel_regs.edi,
ptrace_regs.eip = kernel_regs.eip,
ptrace_regs.eflags = kernel_regs.eflags,
+#else
+ ptrace_regs.rax = kernel_regs.rax,
+ ptrace_regs.rcx = kernel_regs.rcx,
+ ptrace_regs.rdx = kernel_regs.rdx,
+ ptrace_regs.rbx = kernel_regs.rbx,
+ ptrace_regs.rsp = kernel_regs.userspace_rsp,
+ ptrace_regs.rbp = kernel_regs.rbp,
+ ptrace_regs.rsi = kernel_regs.rsi,
+ ptrace_regs.rdi = kernel_regs.rdi,
+ ptrace_regs.rip = kernel_regs.rip,
+ ptrace_regs.r8 = kernel_regs.r8;
+ ptrace_regs.r9 = kernel_regs.r9;
+ ptrace_regs.r10 = kernel_regs.r10;
+ ptrace_regs.r11 = kernel_regs.r11;
+ ptrace_regs.r12 = kernel_regs.r12;
+ ptrace_regs.r13 = kernel_regs.r13;
+ ptrace_regs.r14 = kernel_regs.r14;
+ ptrace_regs.r15 = kernel_regs.r15;
+ ptrace_regs.rflags = kernel_regs.rflags,
+#endif
ptrace_regs.cs = 0;
ptrace_regs.ss = 0;
ptrace_regs.ds = 0;
@@ -69,6 +118,7 @@ inline void copy_kernel_registers_into_ptrace_registers(PtraceRegisters& ptrace_
inline void copy_ptrace_registers_into_kernel_registers(RegisterState& kernel_regs, const PtraceRegisters& ptrace_regs)
{
+#if ARCH(I386)
kernel_regs.eax = ptrace_regs.eax;
kernel_regs.ecx = ptrace_regs.ecx;
kernel_regs.edx = ptrace_regs.edx;
@@ -79,6 +129,27 @@ inline void copy_ptrace_registers_into_kernel_registers(RegisterState& kernel_re
kernel_regs.edi = ptrace_regs.edi;
kernel_regs.eip = ptrace_regs.eip;
kernel_regs.eflags = (kernel_regs.eflags & ~safe_eflags_mask) | (ptrace_regs.eflags & safe_eflags_mask);
+#else
+ kernel_regs.rax = ptrace_regs.rax;
+ kernel_regs.rcx = ptrace_regs.rcx;
+ kernel_regs.rdx = ptrace_regs.rdx;
+ kernel_regs.rbx = ptrace_regs.rbx;
+ kernel_regs.rsp = ptrace_regs.rsp;
+ kernel_regs.rbp = ptrace_regs.rbp;
+ kernel_regs.rsi = ptrace_regs.rsi;
+ kernel_regs.rdi = ptrace_regs.rdi;
+ kernel_regs.rip = ptrace_regs.rip;
+ kernel_regs.r8 = ptrace_regs.r8;
+ kernel_regs.r9 = ptrace_regs.r9;
+ kernel_regs.r10 = ptrace_regs.r10;
+ kernel_regs.r11 = ptrace_regs.r11;
+ kernel_regs.r12 = ptrace_regs.r12;
+ kernel_regs.r13 = ptrace_regs.r13;
+ kernel_regs.r14 = ptrace_regs.r14;
+ kernel_regs.r15 = ptrace_regs.r15;
+ // FIXME: do we need a separate safe_rflags_mask here?
+ kernel_regs.rflags = (kernel_regs.rflags & ~safe_eflags_mask) | (ptrace_regs.rflags & safe_eflags_mask);
+#endif
}
struct [[gnu::packed]] DebugRegisterState {
diff --git a/Kernel/Arch/x86/common/Interrupts.cpp b/Kernel/Arch/x86/common/Interrupts.cpp
index a5b619735f..b205b9ad63 100644
--- a/Kernel/Arch/x86/common/Interrupts.cpp
+++ b/Kernel/Arch/x86/common/Interrupts.cpp
@@ -117,6 +117,7 @@ asm( \
static void dump(const RegisterState& regs)
{
+#if ARCH(I386)
u16 ss;
u32 esp;
@@ -127,14 +128,33 @@ static void dump(const RegisterState& regs)
ss = regs.userspace_ss;
esp = regs.userspace_esp;
}
+#else
+ u64 rsp;
+
+ if (!(regs.cs & 3))
+ rsp = regs.rsp;
+ else
+ rsp = regs.userspace_rsp;
+#endif
dbgln("Exception code: {:04x} (isr: {:04x})", regs.exception_code, regs.isr_number);
+#if ARCH(I386)
dbgln(" pc={:04x}:{:08x} eflags={:08x}", (u16)regs.cs, regs.eip, regs.eflags);
dbgln(" stack={:04x}:{:08x}", ss, esp);
dbgln(" ds={:04x} es={:04x} fs={:04x} gs={:04x}", (u16)regs.ds, (u16)regs.es, (u16)regs.fs, (u16)regs.gs);
dbgln(" eax={:08x} ebx={:08x} ecx={:08x} edx={:08x}", regs.eax, regs.ebx, regs.ecx, regs.edx);
dbgln(" ebp={:08x} esp={:08x} esi={:08x} edi={:08x}", regs.ebp, regs.esp, regs.esi, regs.edi);
dbgln(" cr0={:08x} cr2={:08x} cr3={:08x} cr4={:08x}", read_cr0(), read_cr2(), read_cr3(), read_cr4());
+#else
+ dbgln(" pc={:04x}:{:16x} rflags={:16x}", (u16)regs.cs, regs.rip, regs.rflags);
+ dbgln(" stack={:16x}", rsp);
+ // FIXME: Add fs_base and gs_base here
+ dbgln(" rax={:16x} rbx={:16x} rcx={:16x} rdx={:16x}", regs.rax, regs.rbx, regs.rcx, regs.rdx);
+ dbgln(" rbp={:16x} rsp={:16x} rsi={:16x} rdi={:16x}", regs.rbp, regs.rsp, regs.rsi, regs.rdi);
+ dbgln(" r8={:16x} r9={:16x} r10={:16x} r11={:16x}", regs.r8, regs.r9, regs.r10, regs.r11);
+ dbgln(" r12={:16x} r13={:16x} r14={:16x} r15={:16x}", regs.r12, regs.r13, regs.r14, regs.r15);
+ dbgln(" cr0={:16x} cr2={:16x} cr3={:16x} cr4={:16x}", read_cr0(), read_cr2(), read_cr3(), read_cr4());
+#endif
}
void handle_crash(RegisterState& regs, const char* description, int signal, bool out_of_memory)
@@ -155,7 +175,13 @@ void handle_crash(RegisterState& regs, const char* description, int signal, bool
PANIC("Crash in ring 0");
}
- process->crash(signal, regs.eip, out_of_memory);
+ FlatPtr ip;
+#if ARCH(I386)
+ ip = regs.eip;
+#else
+ ip = regs.rip;
+#endif
+ process->crash(signal, ip, out_of_memory);
}
EH_ENTRY_NO_CODE(6, illegal_instruction);
@@ -237,8 +263,14 @@ void page_fault_handler(TrapFrame* trap)
current_thread->set_handling_page_fault(false);
};
- if (!faulted_in_kernel && !MM.validate_user_stack(current_thread->process(), VirtualAddress(regs.userspace_esp))) {
- dbgln("Invalid stack pointer: {}", VirtualAddress(regs.userspace_esp));
+ VirtualAddress userspace_sp;
+#if ARCH(I386)
+ userspace_sp = VirtualAddress { regs.userspace_esp };
+#else
+ userspace_sp = VirtualAddress { regs.userspace_rsp };
+#endif
+ if (!faulted_in_kernel && !MM.validate_user_stack(current_thread->process(), userspace_sp)) {
+ dbgln("Invalid stack pointer: {}", userspace_sp);
handle_crash(regs, "Bad stack on page fault", SIGSTKFLT);
}
diff --git a/Kernel/PerformanceManager.h b/Kernel/PerformanceManager.h
index 2f480c0590..eb340c8020 100644
--- a/Kernel/PerformanceManager.h
+++ b/Kernel/PerformanceManager.h
@@ -61,9 +61,15 @@ public:
if (current_thread.is_profiling_suppressed())
return;
if (auto* event_buffer = current_thread.process().current_perf_events_buffer()) {
+#if ARCH(I386)
[[maybe_unused]] auto rc = event_buffer->append_with_eip_and_ebp(
current_thread.pid(), current_thread.tid(),
regs.eip, regs.ebp, PERF_EVENT_SAMPLE, lost_time, 0, 0, nullptr);
+#else
+ [[maybe_unused]] auto rc = event_buffer->append_with_eip_and_ebp(
+ current_thread.pid(), current_thread.tid(),
+ regs.rip, regs.rbp, PERF_EVENT_SAMPLE, lost_time, 0, 0, nullptr);
+#endif
}
}
@@ -113,9 +119,15 @@ public:
if (thread.is_profiling_suppressed())
return;
if (auto* event_buffer = thread.process().current_perf_events_buffer()) {
+#if ARCH(I386)
[[maybe_unused]] auto rc = event_buffer->append_with_eip_and_ebp(
thread.pid(), thread.tid(),
regs.eip, regs.ebp, PERF_EVENT_PAGE_FAULT, 0, 0, 0, nullptr);
+#else
+ [[maybe_unused]] auto rc = event_buffer->append_with_eip_and_ebp(
+ thread.pid(), thread.tid(),
+ regs.rip, regs.rbp, PERF_EVENT_PAGE_FAULT, 0, 0, 0, nullptr);
+#endif
}
}
diff --git a/Kernel/Scheduler.cpp b/Kernel/Scheduler.cpp
index b98e8308d3..1aca27dd2d 100644
--- a/Kernel/Scheduler.cpp
+++ b/Kernel/Scheduler.cpp
@@ -594,10 +594,11 @@ void dump_thread_list()
#if ARCH(I386)
if (!thread.current_trap())
return thread.tss().eip;
+ return thread.get_register_dump_from_stack().eip;
#else
PANIC("get_eip() not implemented");
+ return thread.get_register_dump_from_stack().rip;
#endif
- return thread.get_register_dump_from_stack().eip;
};
Thread::for_each([&](Thread& thread) {
diff --git a/Kernel/Syscall.cpp b/Kernel/Syscall.cpp
index f7b32d1748..5912986b66 100644
--- a/Kernel/Syscall.cpp
+++ b/Kernel/Syscall.cpp
@@ -90,7 +90,11 @@ KResultOr<FlatPtr> handle(RegisterState& regs, FlatPtr function, FlatPtr arg1, F
// These syscalls need special handling since they never return to the caller.
if (auto* tracer = process.tracer(); tracer && tracer->is_tracing_syscalls()) {
+#if ARCH(I386)
regs.eax = 0;
+#else
+ regs.rax = 0;
+#endif
tracer->set_trace_syscalls(false);
process.tracer_trap(*current_thread, regs); // this triggers SIGTRAP and stops the thread!
}
@@ -165,26 +169,46 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap)
static constexpr FlatPtr iopl_mask = 3u << 12;
- if ((regs.eflags & (iopl_mask)) != 0) {
+ FlatPtr flags;
+#if ARCH(I386)
+ flags = regs.eflags;
+#else
+ flags = regs.rflags;
+#endif
+
+ if ((flags & (iopl_mask)) != 0) {
PANIC("Syscall from process with IOPL != 0");
}
// NOTE: We take the big process lock before inspecting memory regions.
process.big_lock().lock();
- if (!MM.validate_user_stack(process, VirtualAddress(regs.userspace_esp))) {
- dbgln("Invalid stack pointer: {:p}", regs.userspace_esp);
+ VirtualAddress userspace_sp;
+#if ARCH(I386)
+ userspace_sp = VirtualAddress { regs.userspace_esp };
+#else
+ userspace_sp = VirtualAddress { regs.userspace_rsp };
+#endif
+ if (!MM.validate_user_stack(process, userspace_sp)) {
+ dbgln("Invalid stack pointer: {:p}", userspace_sp);
handle_crash(regs, "Bad stack on syscall entry", SIGSTKFLT);
}
- auto* calling_region = MM.find_user_region_from_vaddr(process.space(), VirtualAddress(regs.eip));
+ VirtualAddress ip;
+#if ARCH(I386)
+ ip = VirtualAddress { regs.eip };
+#else
+ ip = VirtualAddress { regs.rip };
+#endif
+
+ auto* calling_region = MM.find_user_region_from_vaddr(process.space(), ip);
if (!calling_region) {
- dbgln("Syscall from {:p} which has no associated region", regs.eip);
+ dbgln("Syscall from {:p} which has no associated region", ip);
handle_crash(regs, "Syscall from unknown region", SIGSEGV);
}
if (calling_region->is_writable()) {
- dbgln("Syscall from writable memory at {:p}", regs.eip);
+ dbgln("Syscall from writable memory at {:p}", ip);
handle_crash(regs, "Syscall from writable memory", SIGSEGV);
}
@@ -193,16 +217,32 @@ NEVER_INLINE void syscall_handler(TrapFrame* trap)
handle_crash(regs, "Syscall from non-syscall region", SIGSEGV);
}
+#if ARCH(I386)
auto function = regs.eax;
auto arg1 = regs.edx;
auto arg2 = regs.ecx;
auto arg3 = regs.ebx;
+#else
+ auto function = regs.rax;
+ auto arg1 = regs.rdx;
+ auto arg2 = regs.rcx;
+ auto arg3 = regs.rbx;
+#endif
auto result = Syscall::handle(regs, function, arg1, arg2, arg3);
- if (result.is_error())
+ if (result.is_error()) {
+#if ARCH(I386)
regs.eax = result.error();
- else
+#else
+ regs.rax = result.error();
+#endif
+ } else {
+#if ARCH(I386)
regs.eax = result.value();
+#else
+ regs.rax = result.value();
+#endif
+ }
process.big_lock().unlock();
diff --git a/Kernel/Syscalls/get_stack_bounds.cpp b/Kernel/Syscalls/get_stack_bounds.cpp
index ce8512a48e..c3d0220073 100644
--- a/Kernel/Syscalls/get_stack_bounds.cpp
+++ b/Kernel/Syscalls/get_stack_bounds.cpp
@@ -12,7 +12,13 @@ namespace Kernel {
KResultOr<int> Process::sys$get_stack_bounds(Userspace<FlatPtr*> user_stack_base, Userspace<size_t*> user_stack_size)
{
- FlatPtr stack_pointer = Thread::current()->get_register_dump_from_stack().userspace_esp;
+ auto& regs = Thread::current()->get_register_dump_from_stack();
+ FlatPtr stack_pointer;
+#if ARCH(I386)
+ stack_pointer = regs.userspace_esp;
+#else
+ stack_pointer = regs.userspace_rsp;
+#endif
auto* stack_region = space().find_region_containing(Range { VirtualAddress(stack_pointer), 1 });
// The syscall handler should have killed us if we had an invalid stack pointer.
diff --git a/Kernel/Thread.cpp b/Kernel/Thread.cpp
index b2cc469246..5af5c1b35c 100644
--- a/Kernel/Thread.cpp
+++ b/Kernel/Thread.cpp
@@ -812,7 +812,8 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
dbgln_if(SIGNAL_DEBUG, "Setting up user stack to return to EIP {:p}, ESP {:p}", ret_eip, old_esp);
#elif ARCH(X86_64)
- FlatPtr* stack = &state.userspace_esp;
+ FlatPtr* stack = &state.userspace_rsp;
+ TODO();
#endif
#if ARCH(I386)
@@ -855,7 +856,12 @@ DispatchSignalResult Thread::dispatch_signal(u8 signal)
// valid (fork, exec etc) but the tss will, so we use that instead.
auto& regs = get_register_dump_from_stack();
setup_stack(regs);
- regs.eip = process.signal_trampoline().get();
+ auto signal_trampoline_addr = process.signal_trampoline().get();
+#if ARCH(I386)
+ regs.eip = signal_trampoline_addr;
+#else
+ regs.rip = signal_trampoline_addr;
+#endif
#if ARCH(I386)
dbgln_if(SIGNAL_DEBUG, "Thread in state '{}' has been primed with signal handler {:04x}:{:08x} to deliver {}", state_string(), m_tss.cs, m_tss.eip, signal);
diff --git a/Userland/Applications/CrashReporter/main.cpp b/Userland/Applications/CrashReporter/main.cpp
index b0f2b857c9..1a9dedff27 100644
--- a/Userland/Applications/CrashReporter/main.cpp
+++ b/Userland/Applications/CrashReporter/main.cpp
@@ -87,11 +87,23 @@ static TitleAndText build_cpu_registers(const ELF::Core::ThreadInfo& thread_info
StringBuilder builder;
+#if ARCH(I386)
builder.appendff("eax={:08x} ebx={:08x} ecx={:08x} edx={:08x}", regs.eax, regs.ebx, regs.ecx, regs.edx);
builder.append('\n');
builder.appendff("ebp={:08x} esp={:08x} esi={:08x} edi={:08x}", regs.ebp, regs.esp, regs.esi, regs.edi);
builder.append('\n');
builder.appendff("eip={:08x} eflags={:08x}", regs.eip, regs.eflags);
+#else
+ builder.appendff("rax={:16x} rbx={:16x} rcx={:16x} rdx={:16x}", regs.rax, regs.rbx, regs.rcx, regs.rdx);
+ builder.append('\n');
+ builder.appendff("rbp={:16x} rsp={:16x} rsi={:16x} rdi={:16x}", regs.rbp, regs.rsp, regs.rsi, regs.rdi);
+ builder.append('\n');
+ builder.appendff(" r8={:16x} r9={:16x} r10={:16x} r11={:16x}", regs.r8, regs.r9, regs.r10, regs.r11);
+ builder.append('\n');
+ builder.appendff("r12={:16x} r13={:16x} r14={:16x} r15={:16x}", regs.r12, regs.r13, regs.r14, regs.r15);
+ builder.append('\n');
+ builder.appendff("rip={:16x} rflags={:16x}", regs.rip, regs.rflags);
+#endif
return {
String::formatted("Thread #{} (TID {})", thread_index, thread_info.tid),
diff --git a/Userland/Libraries/LibC/sys/arch/i386/regs.h b/Userland/Libraries/LibC/sys/arch/i386/regs.h
index e2319c57b7..d276152579 100644
--- a/Userland/Libraries/LibC/sys/arch/i386/regs.h
+++ b/Userland/Libraries/LibC/sys/arch/i386/regs.h
@@ -9,6 +9,7 @@
#include <AK/Types.h>
struct [[gnu::packed]] PtraceRegisters {
+#if ARCH(I386)
u32 eax;
u32 ecx;
u32 edx;
@@ -19,6 +20,26 @@ struct [[gnu::packed]] PtraceRegisters {
u32 edi;
u32 eip;
u32 eflags;
+#else
+ u64 rax;
+ u64 rcx;
+ u64 rdx;
+ u64 rbx;
+ u64 rsp;
+ u64 rbp;
+ u64 rsi;
+ u64 rdi;
+ u64 rip;
+ u64 r8;
+ u64 r9;
+ u64 r10;
+ u64 r11;
+ u64 r12;
+ u64 r13;
+ u64 r14;
+ u64 r15;
+ u64 rflags;
+#endif
u32 cs;
u32 ss;
u32 ds;
diff --git a/Userland/Libraries/LibDebug/DebugInfo.cpp b/Userland/Libraries/LibDebug/DebugInfo.cpp
index 3e91bd1042..fb8398d5ff 100644
--- a/Userland/Libraries/LibDebug/DebugInfo.cpp
+++ b/Userland/Libraries/LibDebug/DebugInfo.cpp
@@ -167,7 +167,13 @@ NonnullOwnPtrVector<DebugInfo::VariableInfo> DebugInfo::get_variables_in_current
// TODO: We can store the scopes in a better data structure
for (const auto& scope : m_scopes) {
- if (regs.eip - m_base_address < scope.address_low || regs.eip - m_base_address >= scope.address_high)
+ FlatPtr ip;
+#if ARCH(I386)
+ ip = regs.eip;
+#else
+ ip = regs.rip;
+#endif
+ if (ip - m_base_address < scope.address_low || ip - m_base_address >= scope.address_high)
continue;
for (const auto& die_entry : scope.dies_of_variables) {
diff --git a/Userland/Libraries/LibDebug/DebugSession.cpp b/Userland/Libraries/LibDebug/DebugSession.cpp
index c874f5a12c..96aca1d894 100644
--- a/Userland/Libraries/LibDebug/DebugSession.cpp
+++ b/Userland/Libraries/LibDebug/DebugSession.cpp
@@ -324,7 +324,11 @@ void* DebugSession::single_step()
auto regs = get_registers();
constexpr u32 TRAP_FLAG = 0x100;
+#if ARCH(I386)
regs.eflags |= TRAP_FLAG;
+#else
+ regs.rflags |= TRAP_FLAG;
+#endif
set_registers(regs);
continue_debuggee();
@@ -335,7 +339,11 @@ void* DebugSession::single_step()
}
regs = get_registers();
+#if ARCH(I386)
regs.eflags &= ~(TRAP_FLAG);
+#else
+ regs.rflags &= ~(TRAP_FLAG);
+#endif
set_registers(regs);
#if ARCH(I386)
return (void*)regs.eip;
diff --git a/Userland/Libraries/LibDebug/DebugSession.h b/Userland/Libraries/LibDebug/DebugSession.h
index f668b0f6d9..a81dd70e32 100644
--- a/Userland/Libraries/LibDebug/DebugSession.h
+++ b/Userland/Libraries/LibDebug/DebugSession.h
@@ -218,6 +218,12 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
auto regs = get_registers();
+#if ARCH(I386)
+ FlatPtr current_instruction = regs.eip;
+#else
+ FlatPtr current_instruction = regs.rip;
+#endif
+
auto debug_status = peek_debug(DEBUG_STATUS_REGISTER);
if (debug_status.has_value() && (debug_status.value() & 0b1111) > 0) {
// Tripped a watchpoint
@@ -233,8 +239,12 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
auto required_ebp = watchpoint.value().ebp;
auto found_ebp = false;
- u32 current_ebp = regs.ebp;
- u32 current_instruction = regs.eip;
+#if ARCH(I386)
+ FlatPtr current_ebp = regs.ebp;
+#else
+ FlatPtr current_ebp = regs.rbp;
+#endif
+
do {
if (current_ebp == required_ebp) {
found_ebp = true;
@@ -259,22 +269,27 @@ void DebugSession::run(DesiredInitialDebugeeState initial_debugee_state, Callbac
Optional<BreakPoint> current_breakpoint;
if (state == State::FreeRun || state == State::Syscall) {
- current_breakpoint = m_breakpoints.get((void*)((uintptr_t)regs.eip - 1));
+ current_breakpoint = m_breakpoints.get((void*)((uintptr_t)current_instruction - 1));
if (current_breakpoint.has_value())
state = State::FreeRun;
} else {
- current_breakpoint = m_breakpoints.get((void*)regs.eip);
+ current_breakpoint = m_breakpoints.get((void*)current_instruction);
}
if (current_breakpoint.has_value()) {
// We want to make the breakpoint transparent to the user of the debugger.
- // To achieive this, we perform two rollbacks:
+ // To achieve this, we perform two rollbacks:
// 1. Set regs.eip to point at the actual address of the instruction we breaked on.
// regs.eip currently points to one byte after the address of the original instruction,
// because the cpu has just executed the INT3 we patched into the instruction.
// 2. We restore the original first byte of the instruction,
// because it was patched with INT3.
- regs.eip = reinterpret_cast<u32>(current_breakpoint.value().address);
+ auto breakpoint_addr = reinterpret_cast<uintptr_t>(current_breakpoint.value().address);
+#if ARCH(I386)
+ regs.eip = breakpoint_addr;
+#else
+ regs.rip = breakpoint_addr;
+#endif
set_registers(regs);
disable_breakpoint(current_breakpoint.value().address);
}
diff --git a/Userland/Utilities/strace.cpp b/Userland/Utilities/strace.cpp
index 12f6d32689..a8709e2bb5 100644
--- a/Userland/Utilities/strace.cpp
+++ b/Userland/Utilities/strace.cpp
@@ -128,10 +128,18 @@ int main(int argc, char** argv)
perror("getregs");
return 1;
}
+#if ARCH(I386)
u32 syscall_index = regs.eax;
u32 arg1 = regs.edx;
u32 arg2 = regs.ecx;
u32 arg3 = regs.ebx;
+#else
+ u64 syscall_index = regs.rax;
+ u64 arg1 = regs.rdx;
+ u64 arg2 = regs.rcx;
+ u64 arg3 = regs.rbx;
+#endif
+
if (ptrace(PT_SYSCALL, g_pid, 0, 0) == -1) {
perror("syscall");
@@ -147,7 +155,11 @@ int main(int argc, char** argv)
return 1;
}
+#if ARCH(I386)
u32 res = regs.eax;
+#else
+ u64 res = regs.rax;
+#endif
auto string = String::formatted("{}({:#08x}, {:#08x}, {:#08x})\t={}\n",
Syscall::to_string((Syscall::Function)syscall_index),