xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/OpenBSDKernel/RegisterContextOpenBSDKernel_i386.cpp (revision 3d61058aa5c692477b6d18acfbbdb653a9930ff9)
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