1 //===-- RegisterContextOpenBSDKernel_i386.cpp -----------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #if defined(__OpenBSD__) 10 #include <sys/types.h> 11 #include <sys/time.h> 12 #define _KERNEL 13 #include <machine/cpu.h> 14 #undef _KERNEL 15 #include <machine/pcb.h> 16 #include <frame.h> 17 #endif 18 19 #include "RegisterContextOpenBSDKernel_i386.h" 20 21 #include "lldb/Target/Process.h" 22 #include "lldb/Target/Thread.h" 23 #include "lldb/Utility/RegisterValue.h" 24 #include "llvm/Support/Endian.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 29 RegisterContextOpenBSDKernel_i386::RegisterContextOpenBSDKernel_i386( 30 Thread &thread, RegisterInfoInterface *register_info, lldb::addr_t pcb_addr) 31 : RegisterContextPOSIX_x86(thread, 0, register_info), m_pcb_addr(pcb_addr) { 32 } 33 34 bool RegisterContextOpenBSDKernel_i386::ReadGPR() { return true; } 35 36 bool RegisterContextOpenBSDKernel_i386::ReadFPR() { return true; } 37 38 bool RegisterContextOpenBSDKernel_i386::WriteGPR() { 39 assert(0); 40 return false; 41 } 42 43 bool RegisterContextOpenBSDKernel_i386::WriteFPR() { 44 assert(0); 45 return false; 46 } 47 48 bool RegisterContextOpenBSDKernel_i386::ReadRegister( 49 const RegisterInfo *reg_info, RegisterValue &value) { 50 if (m_pcb_addr == LLDB_INVALID_ADDRESS) 51 return false; 52 53 #ifdef __i386__ 54 struct pcb pcb; 55 56 Status error; 57 size_t rd = 58 m_thread.GetProcess()->ReadMemory(m_pcb_addr, &pcb, sizeof(pcb), error); 59 if (rd != sizeof(pcb)) 60 return false; 61 62 if ((pcb.pcb_flags & PCB_SAVECTX) != 0) { 63 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 64 switch (reg) { 65 return true; 66 case lldb_esp_i386: 67 value = (u_int32_t)pcb.pcb_ebp; 68 return true; 69 case lldb_ebp_i386: 70 value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_ebp, error); 71 case lldb_eip_i386: 72 value = m_thread.GetProcess()->ReadPointerFromMemory(pcb.pcb_ebp + 4, 73 error); 74 return true; 75 } 76 return false; 77 } 78 79 /* 80 Usually pcb is written in `cpu_switchto` function. This function writes 81 registers as same as the structure of `swichframe` in the stack. 82 We read the frame if it is. 83 */ 84 struct switchframe sf; 85 rd = m_thread.GetProcess()->ReadMemory(pcb.pcb_esp, &sf, sizeof(sf), error); 86 if (rd != sizeof(sf)) 87 return false; 88 89 uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB]; 90 switch (reg) { 91 #define PCBREG(x, offset) \ 92 case lldb_##x##_i386: \ 93 value = (u_int32_t)(pcb.pcb_##x + (offset)); \ 94 return true; 95 #define SFREG(x) \ 96 case lldb_##x##_i386: \ 97 value = sf.sf_##x; \ 98 return true; 99 100 SFREG(edi); 101 SFREG(esi); 102 SFREG(ebx); 103 SFREG(eip); 104 PCBREG(ebp); 105 PCBREG(esp); 106 } 107 #endif 108 return false; 109 } 110 111 bool RegisterContextOpenBSDKernel_i386::WriteRegister( 112 const RegisterInfo *reg_info, const RegisterValue &value) { 113 return false; 114 } 115