From 233ef26e4d67e6916de7829d880d78bbc2b6dd82 Mon Sep 17 00:00:00 2001 From: Gunnar Beutner Date: Sat, 26 Jun 2021 14:56:28 +0200 Subject: [PATCH] Kernel+Userland: Add x86_64 registers to RegisterState/PtraceRegisters --- Kernel/Arch/x86/RegisterState.h | 73 +++++++++++++++++++- Kernel/Arch/x86/common/Interrupts.cpp | 38 +++++++++- Kernel/PerformanceManager.h | 12 ++++ Kernel/Scheduler.cpp | 3 +- Kernel/Syscall.cpp | 56 ++++++++++++--- Kernel/Syscalls/get_stack_bounds.cpp | 8 ++- Kernel/Thread.cpp | 10 ++- Userland/Applications/CrashReporter/main.cpp | 12 ++++ Userland/Libraries/LibC/sys/arch/i386/regs.h | 21 ++++++ Userland/Libraries/LibDebug/DebugInfo.cpp | 8 ++- Userland/Libraries/LibDebug/DebugSession.cpp | 8 +++ Userland/Libraries/LibDebug/DebugSession.h | 27 ++++++-- Userland/Utilities/strace.cpp | 12 ++++ 13 files changed, 265 insertions(+), 23 deletions(-) diff --git a/Kernel/Arch/x86/RegisterState.h b/Kernel/Arch/x86/RegisterState.h index 0f0d2f3a5f9..299eecf3610 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 a5b619735fb..b205b9ad63f 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 2f480c05900..eb340c80206 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 b98e8308d38..1aca27dd2d0 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 f7b32d1748b..5912986b66b 100644 --- a/Kernel/Syscall.cpp +++ b/Kernel/Syscall.cpp @@ -90,7 +90,11 @@ KResultOr 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 ce8512a48e6..c3d0220073c 100644 --- a/Kernel/Syscalls/get_stack_bounds.cpp +++ b/Kernel/Syscalls/get_stack_bounds.cpp @@ -12,7 +12,13 @@ namespace Kernel { KResultOr Process::sys$get_stack_bounds(Userspace user_stack_base, Userspace 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 b2cc4692468..5af5c1b35c2 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 b0f2b857c9a..1a9dedff279 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 e2319c57b7e..d276152579b 100644 --- a/Userland/Libraries/LibC/sys/arch/i386/regs.h +++ b/Userland/Libraries/LibC/sys/arch/i386/regs.h @@ -9,6 +9,7 @@ #include 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 3e91bd10420..fb8398d5ff1 100644 --- a/Userland/Libraries/LibDebug/DebugInfo.cpp +++ b/Userland/Libraries/LibDebug/DebugInfo.cpp @@ -167,7 +167,13 @@ NonnullOwnPtrVector 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 c874f5a12cd..96aca1d8945 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 f668b0f6d95..a81dd70e32a 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 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(current_breakpoint.value().address); + auto breakpoint_addr = reinterpret_cast(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 12f6d326892..a8709e2bb50 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),