15b406d70SFangrui Song //===-- cli-wrapper-mpxtable.cpp --------------------------------*- C++ -*-===//
2307db0f8SAbhishek Aggarwal //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6307db0f8SAbhishek Aggarwal //
7307db0f8SAbhishek Aggarwal //===----------------------------------------------------------------------===//
8307db0f8SAbhishek Aggarwal 
9307db0f8SAbhishek Aggarwal // C++ includes
10307db0f8SAbhishek Aggarwal #include <cerrno>
11307db0f8SAbhishek Aggarwal #include <string>
12307db0f8SAbhishek Aggarwal 
13307db0f8SAbhishek Aggarwal #include "cli-wrapper-mpxtable.h"
14307db0f8SAbhishek Aggarwal #include "lldb/API/SBCommandInterpreter.h"
15307db0f8SAbhishek Aggarwal #include "lldb/API/SBCommandReturnObject.h"
16307db0f8SAbhishek Aggarwal #include "lldb/API/SBMemoryRegionInfo.h"
17307db0f8SAbhishek Aggarwal #include "lldb/API/SBProcess.h"
18307db0f8SAbhishek Aggarwal #include "lldb/API/SBTarget.h"
19307db0f8SAbhishek Aggarwal #include "lldb/API/SBThread.h"
20307db0f8SAbhishek Aggarwal 
21307db0f8SAbhishek Aggarwal #include "llvm/ADT/Triple.h"
22754f3c4aSSimon Pilgrim #include "llvm/ADT/Twine.h"
23307db0f8SAbhishek Aggarwal 
GetPtr(char * cptr,uint64_t & ptr,lldb::SBFrame & frame,lldb::SBCommandReturnObject & result)24307db0f8SAbhishek Aggarwal static bool GetPtr(char *cptr, uint64_t &ptr, lldb::SBFrame &frame,
25307db0f8SAbhishek Aggarwal                    lldb::SBCommandReturnObject &result) {
26307db0f8SAbhishek Aggarwal   if (!cptr) {
27307db0f8SAbhishek Aggarwal     result.SetError("Bad argument.");
28307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
29307db0f8SAbhishek Aggarwal     return false;
30307db0f8SAbhishek Aggarwal   }
31307db0f8SAbhishek Aggarwal 
32307db0f8SAbhishek Aggarwal   lldb::SBValue ptr_addr = frame.GetValueForVariablePath(cptr);
33307db0f8SAbhishek Aggarwal   if (!ptr_addr.IsValid()) {
34307db0f8SAbhishek Aggarwal     result.SetError("Invalid pointer.");
35307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
36307db0f8SAbhishek Aggarwal     return false;
37307db0f8SAbhishek Aggarwal   }
38307db0f8SAbhishek Aggarwal   ptr = ptr_addr.GetLoadAddress();
39307db0f8SAbhishek Aggarwal   return true;
40307db0f8SAbhishek Aggarwal }
41307db0f8SAbhishek Aggarwal 
42307db0f8SAbhishek Aggarwal enum {
43307db0f8SAbhishek Aggarwal   mpx_base_mask_64 = ~(uint64_t)0xFFFULL,
44307db0f8SAbhishek Aggarwal   mpx_bd_mask_64 = 0xFFFFFFF00000ULL,
45307db0f8SAbhishek Aggarwal   bd_r_shift_64 = 20,
46307db0f8SAbhishek Aggarwal   bd_l_shift_64 = 3,
47307db0f8SAbhishek Aggarwal   bt_r_shift_64 = 3,
48307db0f8SAbhishek Aggarwal   bt_l_shift_64 = 5,
49307db0f8SAbhishek Aggarwal   bt_mask_64 = 0x0000000FFFF8ULL,
50307db0f8SAbhishek Aggarwal 
51307db0f8SAbhishek Aggarwal   mpx_base_mask_32 = 0xFFFFFFFFFFFFF000ULL,
52307db0f8SAbhishek Aggarwal   mpx_bd_mask_32 = 0xFFFFF000ULL,
53307db0f8SAbhishek Aggarwal   bd_r_shift_32 = 12,
54307db0f8SAbhishek Aggarwal   bd_l_shift_32 = 2,
55307db0f8SAbhishek Aggarwal   bt_r_shift_32 = 2,
56307db0f8SAbhishek Aggarwal   bt_l_shift_32 = 4,
57307db0f8SAbhishek Aggarwal   bt_mask_32 = 0x00000FFCULL,
58307db0f8SAbhishek Aggarwal };
59307db0f8SAbhishek Aggarwal 
PrintBTEntry(lldb::addr_t lbound,lldb::addr_t ubound,uint64_t value,uint64_t meta,lldb::SBCommandReturnObject & result)60307db0f8SAbhishek Aggarwal static void PrintBTEntry(lldb::addr_t lbound, lldb::addr_t ubound,
61307db0f8SAbhishek Aggarwal                          uint64_t value, uint64_t meta,
62307db0f8SAbhishek Aggarwal                          lldb::SBCommandReturnObject &result) {
63307db0f8SAbhishek Aggarwal   const lldb::addr_t one_cmpl64 = ~((lldb::addr_t)0);
64307db0f8SAbhishek Aggarwal   const lldb::addr_t one_cmpl32 = ~((uint32_t)0);
65307db0f8SAbhishek Aggarwal 
66307db0f8SAbhishek Aggarwal   if ((lbound == one_cmpl64 || one_cmpl32) && ubound == 0) {
67*0f32d003SMuhammad Omair Javaid     result.Printf("Null bounds on map: pointer value = 0x%" PRIu64 "\n", value);
68307db0f8SAbhishek Aggarwal   } else {
69*0f32d003SMuhammad Omair Javaid     result.Printf("    lbound = 0x%" PRIu64 ",", lbound);
70*0f32d003SMuhammad Omair Javaid     result.Printf(" ubound = 0x%" PRIu64 , ubound);
71*0f32d003SMuhammad Omair Javaid     result.Printf(" (pointer value = 0x%" PRIu64 ",", value);
72*0f32d003SMuhammad Omair Javaid     result.Printf(" metadata = 0x%" PRIu64 ")\n", meta);
73307db0f8SAbhishek Aggarwal   }
74307db0f8SAbhishek Aggarwal }
75307db0f8SAbhishek Aggarwal 
GetBTEntryAddr(uint64_t bndcfgu,uint64_t ptr,lldb::SBTarget & target,llvm::Triple::ArchType arch,size_t & size,lldb::addr_t & bt_entry_addr,lldb::SBCommandReturnObject & result,lldb::SBError & error)76307db0f8SAbhishek Aggarwal static bool GetBTEntryAddr(uint64_t bndcfgu, uint64_t ptr,
77307db0f8SAbhishek Aggarwal                            lldb::SBTarget &target, llvm::Triple::ArchType arch,
78307db0f8SAbhishek Aggarwal                            size_t &size, lldb::addr_t &bt_entry_addr,
79307db0f8SAbhishek Aggarwal                            lldb::SBCommandReturnObject &result,
80307db0f8SAbhishek Aggarwal                            lldb::SBError &error) {
81307db0f8SAbhishek Aggarwal   lldb::addr_t mpx_base_mask;
82307db0f8SAbhishek Aggarwal   lldb::addr_t mpx_bd_mask;
83307db0f8SAbhishek Aggarwal   lldb::addr_t bd_r_shift;
84307db0f8SAbhishek Aggarwal   lldb::addr_t bd_l_shift;
85307db0f8SAbhishek Aggarwal   lldb::addr_t bt_r_shift;
86307db0f8SAbhishek Aggarwal   lldb::addr_t bt_l_shift;
87307db0f8SAbhishek Aggarwal   lldb::addr_t bt_mask;
88307db0f8SAbhishek Aggarwal 
89307db0f8SAbhishek Aggarwal   if (arch == llvm::Triple::ArchType::x86_64) {
90307db0f8SAbhishek Aggarwal     mpx_base_mask = mpx_base_mask_64;
91307db0f8SAbhishek Aggarwal     mpx_bd_mask = mpx_bd_mask_64;
92307db0f8SAbhishek Aggarwal     bd_r_shift = bd_r_shift_64;
93307db0f8SAbhishek Aggarwal     bd_l_shift = bd_l_shift_64;
94307db0f8SAbhishek Aggarwal     bt_r_shift = bt_r_shift_64;
95307db0f8SAbhishek Aggarwal     bt_l_shift = bt_l_shift_64;
96307db0f8SAbhishek Aggarwal     bt_mask = bt_mask_64;
97307db0f8SAbhishek Aggarwal   } else if (arch == llvm::Triple::ArchType::x86) {
98307db0f8SAbhishek Aggarwal     mpx_base_mask = mpx_base_mask_32;
99307db0f8SAbhishek Aggarwal     mpx_bd_mask = mpx_bd_mask_32;
100307db0f8SAbhishek Aggarwal     bd_r_shift = bd_r_shift_32;
101307db0f8SAbhishek Aggarwal     bd_l_shift = bd_l_shift_32;
102307db0f8SAbhishek Aggarwal     bt_r_shift = bt_r_shift_32;
103307db0f8SAbhishek Aggarwal     bt_l_shift = bt_l_shift_32;
104307db0f8SAbhishek Aggarwal     bt_mask = bt_mask_32;
105307db0f8SAbhishek Aggarwal   } else {
106307db0f8SAbhishek Aggarwal     result.SetError("Invalid arch.");
107307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
108307db0f8SAbhishek Aggarwal     return false;
109307db0f8SAbhishek Aggarwal   }
110307db0f8SAbhishek Aggarwal 
111307db0f8SAbhishek Aggarwal   size = target.GetAddressByteSize();
112307db0f8SAbhishek Aggarwal   lldb::addr_t mpx_bd_base = bndcfgu & mpx_base_mask;
113307db0f8SAbhishek Aggarwal   lldb::addr_t bd_entry_offset = ((ptr & mpx_bd_mask) >> bd_r_shift)
114307db0f8SAbhishek Aggarwal                                  << bd_l_shift;
115307db0f8SAbhishek Aggarwal   lldb::addr_t bd_entry_addr = mpx_bd_base + bd_entry_offset;
116307db0f8SAbhishek Aggarwal 
117307db0f8SAbhishek Aggarwal   std::vector<uint8_t> bd_entry_v(size);
118307db0f8SAbhishek Aggarwal   size_t ret = target.GetProcess().ReadMemory(
119307db0f8SAbhishek Aggarwal       bd_entry_addr, static_cast<void *>(bd_entry_v.data()), size, error);
120307db0f8SAbhishek Aggarwal   if (ret != size || !error.Success()) {
121307db0f8SAbhishek Aggarwal     result.SetError("Failed access to BD entry.");
122307db0f8SAbhishek Aggarwal     return false;
123307db0f8SAbhishek Aggarwal   }
124307db0f8SAbhishek Aggarwal 
125307db0f8SAbhishek Aggarwal   lldb::SBData data;
126307db0f8SAbhishek Aggarwal   data.SetData(error, bd_entry_v.data(), bd_entry_v.size(),
127307db0f8SAbhishek Aggarwal                target.GetByteOrder(), size);
128307db0f8SAbhishek Aggarwal   lldb::addr_t bd_entry = data.GetAddress(error, 0);
129307db0f8SAbhishek Aggarwal 
130307db0f8SAbhishek Aggarwal   if (!error.Success()) {
131307db0f8SAbhishek Aggarwal     result.SetError("Failed access to BD entry.");
132307db0f8SAbhishek Aggarwal     return false;
133307db0f8SAbhishek Aggarwal   }
134307db0f8SAbhishek Aggarwal 
135307db0f8SAbhishek Aggarwal   if ((bd_entry & 0x01) == 0) {
136307db0f8SAbhishek Aggarwal     result.SetError("Invalid bound directory.");
137307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
138307db0f8SAbhishek Aggarwal     return false;
139307db0f8SAbhishek Aggarwal   }
140307db0f8SAbhishek Aggarwal 
141307db0f8SAbhishek Aggarwal   // Clear status bit.
142307db0f8SAbhishek Aggarwal   //
143307db0f8SAbhishek Aggarwal   bd_entry--;
144307db0f8SAbhishek Aggarwal 
145307db0f8SAbhishek Aggarwal   lldb::addr_t bt_addr = bd_entry & ~bt_r_shift;
146307db0f8SAbhishek Aggarwal   lldb::addr_t bt_entry_offset = ((ptr & bt_mask) >> bt_r_shift) << bt_l_shift;
147307db0f8SAbhishek Aggarwal   bt_entry_addr = bt_addr + bt_entry_offset;
148307db0f8SAbhishek Aggarwal 
149307db0f8SAbhishek Aggarwal   return true;
150307db0f8SAbhishek Aggarwal }
151307db0f8SAbhishek Aggarwal 
GetBTEntry(uint64_t bndcfgu,uint64_t ptr,lldb::SBTarget & target,llvm::Triple::ArchType arch,lldb::SBCommandReturnObject & result,lldb::SBError & error)152307db0f8SAbhishek Aggarwal static bool GetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::SBTarget &target,
153307db0f8SAbhishek Aggarwal                        llvm::Triple::ArchType arch,
154307db0f8SAbhishek Aggarwal                        lldb::SBCommandReturnObject &result,
155307db0f8SAbhishek Aggarwal                        lldb::SBError &error) {
156307db0f8SAbhishek Aggarwal   lldb::addr_t bt_entry_addr;
157307db0f8SAbhishek Aggarwal   size_t size;
158307db0f8SAbhishek Aggarwal   if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
159307db0f8SAbhishek Aggarwal                       error))
160307db0f8SAbhishek Aggarwal     return false;
161307db0f8SAbhishek Aggarwal 
162307db0f8SAbhishek Aggarwal   // bt_entry_v must have space to store the 4 elements of the BT entry (lower
163307db0f8SAbhishek Aggarwal   // boundary,
164307db0f8SAbhishek Aggarwal   // upper boundary, pointer value and meta data), which all have the same size
165307db0f8SAbhishek Aggarwal   // 'size'.
166307db0f8SAbhishek Aggarwal   //
167307db0f8SAbhishek Aggarwal   std::vector<uint8_t> bt_entry_v(size * 4);
168307db0f8SAbhishek Aggarwal   size_t ret = target.GetProcess().ReadMemory(
169307db0f8SAbhishek Aggarwal       bt_entry_addr, static_cast<void *>(bt_entry_v.data()), size * 4, error);
170307db0f8SAbhishek Aggarwal 
171307db0f8SAbhishek Aggarwal   if ((ret != (size * 4)) || !error.Success()) {
172307db0f8SAbhishek Aggarwal     result.SetError("Unsuccessful. Failed access to BT entry.");
173307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
174307db0f8SAbhishek Aggarwal     return false;
175307db0f8SAbhishek Aggarwal   }
176307db0f8SAbhishek Aggarwal 
177307db0f8SAbhishek Aggarwal   lldb::addr_t lbound;
178307db0f8SAbhishek Aggarwal   lldb::addr_t ubound;
179307db0f8SAbhishek Aggarwal   uint64_t value;
180307db0f8SAbhishek Aggarwal   uint64_t meta;
181307db0f8SAbhishek Aggarwal   lldb::SBData data;
182307db0f8SAbhishek Aggarwal   data.SetData(error, bt_entry_v.data(), bt_entry_v.size(),
183307db0f8SAbhishek Aggarwal                target.GetByteOrder(), size);
184307db0f8SAbhishek Aggarwal   lbound = data.GetAddress(error, size * 0);
185307db0f8SAbhishek Aggarwal   ubound = data.GetAddress(error, size * 1);
186307db0f8SAbhishek Aggarwal   value = data.GetAddress(error, size * 2);
187307db0f8SAbhishek Aggarwal   meta = data.GetAddress(error, size * 3);
188307db0f8SAbhishek Aggarwal   // ubound is stored as one's complement.
189307db0f8SAbhishek Aggarwal   if (arch == llvm::Triple::ArchType::x86) {
190307db0f8SAbhishek Aggarwal     ubound = (~ubound) & 0x00000000FFFFFFFF;
191307db0f8SAbhishek Aggarwal   } else {
192307db0f8SAbhishek Aggarwal     ubound = ~ubound;
193307db0f8SAbhishek Aggarwal   }
194307db0f8SAbhishek Aggarwal 
195307db0f8SAbhishek Aggarwal   if (!error.Success()) {
196307db0f8SAbhishek Aggarwal     result.SetError("Failed access to BT entry.");
197307db0f8SAbhishek Aggarwal     return false;
198307db0f8SAbhishek Aggarwal   }
199307db0f8SAbhishek Aggarwal 
200307db0f8SAbhishek Aggarwal   PrintBTEntry(lbound, ubound, value, meta, result);
201307db0f8SAbhishek Aggarwal 
202307db0f8SAbhishek Aggarwal   result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
203307db0f8SAbhishek Aggarwal   return true;
204307db0f8SAbhishek Aggarwal }
205307db0f8SAbhishek Aggarwal 
uIntToU8(uint64_t input,size_t size)206307db0f8SAbhishek Aggarwal static std::vector<uint8_t> uIntToU8(uint64_t input, size_t size) {
207307db0f8SAbhishek Aggarwal   std::vector<uint8_t> output;
208307db0f8SAbhishek Aggarwal   for (size_t i = 0; i < size; i++)
209307db0f8SAbhishek Aggarwal     output.push_back(
210307db0f8SAbhishek Aggarwal         static_cast<uint8_t>((input & (0xFFULL << (i * 8))) >> (i * 8)));
211307db0f8SAbhishek Aggarwal 
212307db0f8SAbhishek Aggarwal   return output;
213307db0f8SAbhishek Aggarwal }
214307db0f8SAbhishek Aggarwal 
SetBTEntry(uint64_t bndcfgu,uint64_t ptr,lldb::addr_t lbound,lldb::addr_t ubound,lldb::SBTarget & target,llvm::Triple::ArchType arch,lldb::SBCommandReturnObject & result,lldb::SBError & error)215307db0f8SAbhishek Aggarwal static bool SetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::addr_t lbound,
216307db0f8SAbhishek Aggarwal                        lldb::addr_t ubound, lldb::SBTarget &target,
217307db0f8SAbhishek Aggarwal                        llvm::Triple::ArchType arch,
218307db0f8SAbhishek Aggarwal                        lldb::SBCommandReturnObject &result,
219307db0f8SAbhishek Aggarwal                        lldb::SBError &error) {
220307db0f8SAbhishek Aggarwal   lldb::addr_t bt_entry_addr;
221307db0f8SAbhishek Aggarwal   size_t size;
222307db0f8SAbhishek Aggarwal 
223307db0f8SAbhishek Aggarwal   if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
224307db0f8SAbhishek Aggarwal                       error))
225307db0f8SAbhishek Aggarwal     return false;
226307db0f8SAbhishek Aggarwal 
227307db0f8SAbhishek Aggarwal   // bt_entry_v must have space to store only 2 elements of the BT Entry, the
228307db0f8SAbhishek Aggarwal   // lower boundary and the upper boundary, which both have size 'size'.
229307db0f8SAbhishek Aggarwal   //
230307db0f8SAbhishek Aggarwal   std::vector<uint8_t> bt_entry_v(size * 2);
231307db0f8SAbhishek Aggarwal 
232307db0f8SAbhishek Aggarwal   std::vector<uint8_t> lbound_v = uIntToU8(lbound, size);
233307db0f8SAbhishek Aggarwal   bt_entry_v.insert(bt_entry_v.begin(), lbound_v.begin(), lbound_v.end());
234307db0f8SAbhishek Aggarwal   std::vector<uint8_t> ubound_v = uIntToU8(~ubound, size);
235307db0f8SAbhishek Aggarwal   bt_entry_v.insert(bt_entry_v.begin() + size, ubound_v.begin(),
236307db0f8SAbhishek Aggarwal                     ubound_v.end());
237307db0f8SAbhishek Aggarwal 
238307db0f8SAbhishek Aggarwal   size_t ret = target.GetProcess().WriteMemory(
239307db0f8SAbhishek Aggarwal       bt_entry_addr, (void *)(bt_entry_v.data()), size * 2, error);
240307db0f8SAbhishek Aggarwal   if ((ret != (size * 2)) || !error.Success()) {
241307db0f8SAbhishek Aggarwal     result.SetError("Failed access to BT entry.");
242307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
243307db0f8SAbhishek Aggarwal     return false;
244307db0f8SAbhishek Aggarwal   }
245307db0f8SAbhishek Aggarwal 
246307db0f8SAbhishek Aggarwal   result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
247307db0f8SAbhishek Aggarwal   return true;
248307db0f8SAbhishek Aggarwal }
249307db0f8SAbhishek Aggarwal 
GetInitInfo(lldb::SBDebugger debugger,lldb::SBTarget & target,llvm::Triple::ArchType & arch,uint64_t & bndcfgu,char * arg,uint64_t & ptr,lldb::SBCommandReturnObject & result,lldb::SBError & error)250307db0f8SAbhishek Aggarwal static bool GetInitInfo(lldb::SBDebugger debugger, lldb::SBTarget &target,
251307db0f8SAbhishek Aggarwal                         llvm::Triple::ArchType &arch, uint64_t &bndcfgu,
252307db0f8SAbhishek Aggarwal                         char *arg, uint64_t &ptr,
253307db0f8SAbhishek Aggarwal                         lldb::SBCommandReturnObject &result,
254307db0f8SAbhishek Aggarwal                         lldb::SBError &error) {
255307db0f8SAbhishek Aggarwal   target = debugger.GetSelectedTarget();
256307db0f8SAbhishek Aggarwal   if (!target.IsValid()) {
257307db0f8SAbhishek Aggarwal     result.SetError("Invalid target.");
258307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
259307db0f8SAbhishek Aggarwal     return false;
260307db0f8SAbhishek Aggarwal   }
261307db0f8SAbhishek Aggarwal 
262307db0f8SAbhishek Aggarwal   const std::string triple_s(target.GetTriple());
263307db0f8SAbhishek Aggarwal   const llvm::Triple triple(triple_s);
264307db0f8SAbhishek Aggarwal 
265307db0f8SAbhishek Aggarwal   arch = triple.getArch();
266307db0f8SAbhishek Aggarwal 
267307db0f8SAbhishek Aggarwal   if ((arch != llvm::Triple::ArchType::x86) &&
268307db0f8SAbhishek Aggarwal       (arch != llvm::Triple::ArchType::x86_64)) {
269307db0f8SAbhishek Aggarwal     result.SetError("Platform not supported.");
270307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
271307db0f8SAbhishek Aggarwal     return false;
272307db0f8SAbhishek Aggarwal   }
273307db0f8SAbhishek Aggarwal 
274307db0f8SAbhishek Aggarwal   lldb::SBFrame frame =
275307db0f8SAbhishek Aggarwal       target.GetProcess().GetSelectedThread().GetSelectedFrame();
276307db0f8SAbhishek Aggarwal   if (!frame.IsValid()) {
277307db0f8SAbhishek Aggarwal     result.SetError("No valid process, thread or frame.");
278307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
279307db0f8SAbhishek Aggarwal     return false;
280307db0f8SAbhishek Aggarwal   }
281307db0f8SAbhishek Aggarwal 
282307db0f8SAbhishek Aggarwal   lldb::SBValue bndcfgu_val = frame.FindRegister("bndcfgu");
283307db0f8SAbhishek Aggarwal   if (!bndcfgu_val.IsValid()) {
284307db0f8SAbhishek Aggarwal     result.SetError("Cannot access register BNDCFGU. Does the target support "
285307db0f8SAbhishek Aggarwal                     "Intel(R) Memory Protection Extensions (Intel(R) MPX)?");
286307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
287307db0f8SAbhishek Aggarwal     return false;
288307db0f8SAbhishek Aggarwal   }
289307db0f8SAbhishek Aggarwal 
290307db0f8SAbhishek Aggarwal   lldb::SBData bndcfgu_data = bndcfgu_val.GetData();
291307db0f8SAbhishek Aggarwal   bndcfgu = bndcfgu_data.GetUnsignedInt64(error, 0);
292307db0f8SAbhishek Aggarwal   if (!error.Success()) {
293307db0f8SAbhishek Aggarwal     result.SetError(error, "Invalid read of register BNDCFGU.");
294307db0f8SAbhishek Aggarwal     return false;
295307db0f8SAbhishek Aggarwal   }
296307db0f8SAbhishek Aggarwal 
297307db0f8SAbhishek Aggarwal   if (!GetPtr(arg, ptr, frame, result))
298307db0f8SAbhishek Aggarwal     return false;
299307db0f8SAbhishek Aggarwal 
300307db0f8SAbhishek Aggarwal   return true;
301307db0f8SAbhishek Aggarwal }
302307db0f8SAbhishek Aggarwal 
303307db0f8SAbhishek Aggarwal class MPXTableShow : public lldb::SBCommandPluginInterface {
304307db0f8SAbhishek Aggarwal public:
DoExecute(lldb::SBDebugger debugger,char ** command,lldb::SBCommandReturnObject & result)3051756630dSRaphael Isemann   bool DoExecute(lldb::SBDebugger debugger, char **command,
3061756630dSRaphael Isemann                  lldb::SBCommandReturnObject &result) override {
307307db0f8SAbhishek Aggarwal 
308307db0f8SAbhishek Aggarwal     if (command) {
309307db0f8SAbhishek Aggarwal       int arg_c = 0;
310307db0f8SAbhishek Aggarwal       char *arg;
311307db0f8SAbhishek Aggarwal 
312307db0f8SAbhishek Aggarwal       while (*command) {
313307db0f8SAbhishek Aggarwal         if (arg_c >= 1) {
314307db0f8SAbhishek Aggarwal           result.SetError("Too many arguments. See help.");
315307db0f8SAbhishek Aggarwal           result.SetStatus(lldb::eReturnStatusFailed);
316307db0f8SAbhishek Aggarwal           return false;
317307db0f8SAbhishek Aggarwal         }
318307db0f8SAbhishek Aggarwal         arg_c++;
319307db0f8SAbhishek Aggarwal         arg = *command;
320307db0f8SAbhishek Aggarwal         command++;
321307db0f8SAbhishek Aggarwal       }
322307db0f8SAbhishek Aggarwal 
323307db0f8SAbhishek Aggarwal       if (!debugger.IsValid()) {
324307db0f8SAbhishek Aggarwal         result.SetError("Invalid debugger.");
325307db0f8SAbhishek Aggarwal         result.SetStatus(lldb::eReturnStatusFailed);
326307db0f8SAbhishek Aggarwal         return false;
327307db0f8SAbhishek Aggarwal       }
328307db0f8SAbhishek Aggarwal 
329307db0f8SAbhishek Aggarwal       lldb::SBTarget target;
330307db0f8SAbhishek Aggarwal       llvm::Triple::ArchType arch;
331307db0f8SAbhishek Aggarwal       lldb::SBError error;
332307db0f8SAbhishek Aggarwal       uint64_t bndcfgu;
333307db0f8SAbhishek Aggarwal       uint64_t ptr;
334307db0f8SAbhishek Aggarwal 
335307db0f8SAbhishek Aggarwal       if (!GetInitInfo(debugger, target, arch, bndcfgu, arg, ptr, result,
336307db0f8SAbhishek Aggarwal                        error))
337307db0f8SAbhishek Aggarwal         return false;
338307db0f8SAbhishek Aggarwal 
339307db0f8SAbhishek Aggarwal       return GetBTEntry(bndcfgu, ptr, target, arch, result, error);
340307db0f8SAbhishek Aggarwal     }
341307db0f8SAbhishek Aggarwal 
342307db0f8SAbhishek Aggarwal     result.SetError("Too few arguments. See help.");
343307db0f8SAbhishek Aggarwal     result.SetStatus(lldb::eReturnStatusFailed);
344307db0f8SAbhishek Aggarwal     return false;
345307db0f8SAbhishek Aggarwal   }
346307db0f8SAbhishek Aggarwal };
347307db0f8SAbhishek Aggarwal 
348307db0f8SAbhishek Aggarwal class MPXTableSet : public lldb::SBCommandPluginInterface {
349307db0f8SAbhishek Aggarwal public:
DoExecute(lldb::SBDebugger debugger,char ** command,lldb::SBCommandReturnObject & result)3501756630dSRaphael Isemann   bool DoExecute(lldb::SBDebugger debugger, char **command,
3511756630dSRaphael Isemann                  lldb::SBCommandReturnObject &result) override {
352307db0f8SAbhishek Aggarwal 
353307db0f8SAbhishek Aggarwal     if (command) {
354307db0f8SAbhishek Aggarwal       int arg_c = 0;
355307db0f8SAbhishek Aggarwal       char *arg[3];
356307db0f8SAbhishek Aggarwal 
357307db0f8SAbhishek Aggarwal       while (*command) {
358307db0f8SAbhishek Aggarwal         arg[arg_c] = *command;
359307db0f8SAbhishek Aggarwal         command++;
360307db0f8SAbhishek Aggarwal         arg_c++;
361307db0f8SAbhishek Aggarwal       }
362307db0f8SAbhishek Aggarwal 
363307db0f8SAbhishek Aggarwal       if (arg_c != 3) {
364307db0f8SAbhishek Aggarwal         result.SetError("Wrong arguments. See help.");
365307db0f8SAbhishek Aggarwal         return false;
366307db0f8SAbhishek Aggarwal       }
367307db0f8SAbhishek Aggarwal 
368307db0f8SAbhishek Aggarwal       if (!debugger.IsValid()) {
369307db0f8SAbhishek Aggarwal         result.SetError("Invalid debugger.");
370307db0f8SAbhishek Aggarwal         return false;
371307db0f8SAbhishek Aggarwal       }
372307db0f8SAbhishek Aggarwal 
373307db0f8SAbhishek Aggarwal       lldb::SBTarget target;
374307db0f8SAbhishek Aggarwal       llvm::Triple::ArchType arch;
375307db0f8SAbhishek Aggarwal       lldb::SBError error;
376307db0f8SAbhishek Aggarwal       uint64_t bndcfgu;
377307db0f8SAbhishek Aggarwal       uint64_t ptr;
378307db0f8SAbhishek Aggarwal 
379307db0f8SAbhishek Aggarwal       if (!GetInitInfo(debugger, target, arch, bndcfgu, arg[0], ptr, result,
380307db0f8SAbhishek Aggarwal                        error))
381307db0f8SAbhishek Aggarwal         return false;
382307db0f8SAbhishek Aggarwal 
383307db0f8SAbhishek Aggarwal       char *endptr;
384307db0f8SAbhishek Aggarwal       errno = 0;
385307db0f8SAbhishek Aggarwal       uint64_t lbound = std::strtoul(arg[1], &endptr, 16);
386307db0f8SAbhishek Aggarwal       if (endptr == arg[1] || errno == ERANGE) {
387307db0f8SAbhishek Aggarwal         result.SetError("Lower Bound: bad argument format.");
388307db0f8SAbhishek Aggarwal         errno = 0;
389307db0f8SAbhishek Aggarwal         return false;
390307db0f8SAbhishek Aggarwal       }
391307db0f8SAbhishek Aggarwal 
392307db0f8SAbhishek Aggarwal       uint64_t ubound = std::strtoul(arg[2], &endptr, 16);
393307db0f8SAbhishek Aggarwal       if (endptr == arg[1] || errno == ERANGE) {
394307db0f8SAbhishek Aggarwal         result.SetError("Upper Bound: bad argument format.");
395307db0f8SAbhishek Aggarwal         errno = 0;
396307db0f8SAbhishek Aggarwal         return false;
397307db0f8SAbhishek Aggarwal       }
398307db0f8SAbhishek Aggarwal 
399307db0f8SAbhishek Aggarwal       return SetBTEntry(bndcfgu, ptr, lbound, ubound, target, arch, result,
400307db0f8SAbhishek Aggarwal                         error);
401307db0f8SAbhishek Aggarwal     }
402307db0f8SAbhishek Aggarwal 
403307db0f8SAbhishek Aggarwal     result.SetError("Too few arguments. See help.");
404307db0f8SAbhishek Aggarwal     return false;
405307db0f8SAbhishek Aggarwal   }
406307db0f8SAbhishek Aggarwal };
407307db0f8SAbhishek Aggarwal 
MPXPluginInitialize(lldb::SBDebugger & debugger)408307db0f8SAbhishek Aggarwal bool MPXPluginInitialize(lldb::SBDebugger &debugger) {
409307db0f8SAbhishek Aggarwal   lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
410307db0f8SAbhishek Aggarwal   lldb::SBCommand mpxTable = interpreter.AddMultiwordCommand(
411307db0f8SAbhishek Aggarwal       "mpx-table", "A utility to access the Intel(R) MPX table entries.");
412307db0f8SAbhishek Aggarwal 
413307db0f8SAbhishek Aggarwal   const char *mpx_show_help = "Show the Intel(R) MPX table entry of a pointer."
414307db0f8SAbhishek Aggarwal                               "\nmpx-table show <pointer>";
415307db0f8SAbhishek Aggarwal   mpxTable.AddCommand("show", new MPXTableShow(), mpx_show_help);
416307db0f8SAbhishek Aggarwal 
417307db0f8SAbhishek Aggarwal   const char *mpx_set_help =
418307db0f8SAbhishek Aggarwal       "Set the Intel(R) MPX table entry of a pointer.\n"
419307db0f8SAbhishek Aggarwal       "mpx-table set <pointer> <lower bound> <upper bound>";
420307db0f8SAbhishek Aggarwal   mpxTable.AddCommand("set", new MPXTableSet(), mpx_set_help);
421307db0f8SAbhishek Aggarwal 
422307db0f8SAbhishek Aggarwal   return true;
423307db0f8SAbhishek Aggarwal }
424