xref: /openbsd-src/gnu/llvm/lldb/tools/intel-features/intel-mpx/cli-wrapper-mpxtable.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick //===-- cli-wrapper-mpxtable.cpp --------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick // C++ includes
10061da546Spatrick #include <cerrno>
11061da546Spatrick #include <string>
12061da546Spatrick 
13061da546Spatrick #include "cli-wrapper-mpxtable.h"
14061da546Spatrick #include "lldb/API/SBCommandInterpreter.h"
15061da546Spatrick #include "lldb/API/SBCommandReturnObject.h"
16061da546Spatrick #include "lldb/API/SBMemoryRegionInfo.h"
17061da546Spatrick #include "lldb/API/SBProcess.h"
18061da546Spatrick #include "lldb/API/SBTarget.h"
19061da546Spatrick #include "lldb/API/SBThread.h"
20061da546Spatrick 
21061da546Spatrick #include "llvm/ADT/Triple.h"
22dda28197Spatrick #include "llvm/ADT/Twine.h"
23061da546Spatrick 
GetPtr(char * cptr,uint64_t & ptr,lldb::SBFrame & frame,lldb::SBCommandReturnObject & result)24061da546Spatrick static bool GetPtr(char *cptr, uint64_t &ptr, lldb::SBFrame &frame,
25061da546Spatrick                    lldb::SBCommandReturnObject &result) {
26061da546Spatrick   if (!cptr) {
27061da546Spatrick     result.SetError("Bad argument.");
28061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
29061da546Spatrick     return false;
30061da546Spatrick   }
31061da546Spatrick 
32061da546Spatrick   lldb::SBValue ptr_addr = frame.GetValueForVariablePath(cptr);
33061da546Spatrick   if (!ptr_addr.IsValid()) {
34061da546Spatrick     result.SetError("Invalid pointer.");
35061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
36061da546Spatrick     return false;
37061da546Spatrick   }
38061da546Spatrick   ptr = ptr_addr.GetLoadAddress();
39061da546Spatrick   return true;
40061da546Spatrick }
41061da546Spatrick 
42061da546Spatrick enum {
43061da546Spatrick   mpx_base_mask_64 = ~(uint64_t)0xFFFULL,
44061da546Spatrick   mpx_bd_mask_64 = 0xFFFFFFF00000ULL,
45061da546Spatrick   bd_r_shift_64 = 20,
46061da546Spatrick   bd_l_shift_64 = 3,
47061da546Spatrick   bt_r_shift_64 = 3,
48061da546Spatrick   bt_l_shift_64 = 5,
49061da546Spatrick   bt_mask_64 = 0x0000000FFFF8ULL,
50061da546Spatrick 
51061da546Spatrick   mpx_base_mask_32 = 0xFFFFFFFFFFFFF000ULL,
52061da546Spatrick   mpx_bd_mask_32 = 0xFFFFF000ULL,
53061da546Spatrick   bd_r_shift_32 = 12,
54061da546Spatrick   bd_l_shift_32 = 2,
55061da546Spatrick   bt_r_shift_32 = 2,
56061da546Spatrick   bt_l_shift_32 = 4,
57061da546Spatrick   bt_mask_32 = 0x00000FFCULL,
58061da546Spatrick };
59061da546Spatrick 
PrintBTEntry(lldb::addr_t lbound,lldb::addr_t ubound,uint64_t value,uint64_t meta,lldb::SBCommandReturnObject & result)60061da546Spatrick static void PrintBTEntry(lldb::addr_t lbound, lldb::addr_t ubound,
61061da546Spatrick                          uint64_t value, uint64_t meta,
62061da546Spatrick                          lldb::SBCommandReturnObject &result) {
63061da546Spatrick   const lldb::addr_t one_cmpl64 = ~((lldb::addr_t)0);
64061da546Spatrick   const lldb::addr_t one_cmpl32 = ~((uint32_t)0);
65061da546Spatrick 
66*f6aab3d8Srobert   if ((lbound == one_cmpl64 || lbound == one_cmpl32) && ubound == 0) {
67be691f3bSpatrick     result.Printf("Null bounds on map: pointer value = 0x%" PRIu64 "\n", value);
68061da546Spatrick   } else {
69be691f3bSpatrick     result.Printf("    lbound = 0x%" PRIu64 ",", lbound);
70be691f3bSpatrick     result.Printf(" ubound = 0x%" PRIu64 , ubound);
71be691f3bSpatrick     result.Printf(" (pointer value = 0x%" PRIu64 ",", value);
72be691f3bSpatrick     result.Printf(" metadata = 0x%" PRIu64 ")\n", meta);
73061da546Spatrick   }
74061da546Spatrick }
75061da546Spatrick 
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)76061da546Spatrick static bool GetBTEntryAddr(uint64_t bndcfgu, uint64_t ptr,
77061da546Spatrick                            lldb::SBTarget &target, llvm::Triple::ArchType arch,
78061da546Spatrick                            size_t &size, lldb::addr_t &bt_entry_addr,
79061da546Spatrick                            lldb::SBCommandReturnObject &result,
80061da546Spatrick                            lldb::SBError &error) {
81061da546Spatrick   lldb::addr_t mpx_base_mask;
82061da546Spatrick   lldb::addr_t mpx_bd_mask;
83061da546Spatrick   lldb::addr_t bd_r_shift;
84061da546Spatrick   lldb::addr_t bd_l_shift;
85061da546Spatrick   lldb::addr_t bt_r_shift;
86061da546Spatrick   lldb::addr_t bt_l_shift;
87061da546Spatrick   lldb::addr_t bt_mask;
88061da546Spatrick 
89061da546Spatrick   if (arch == llvm::Triple::ArchType::x86_64) {
90061da546Spatrick     mpx_base_mask = mpx_base_mask_64;
91061da546Spatrick     mpx_bd_mask = mpx_bd_mask_64;
92061da546Spatrick     bd_r_shift = bd_r_shift_64;
93061da546Spatrick     bd_l_shift = bd_l_shift_64;
94061da546Spatrick     bt_r_shift = bt_r_shift_64;
95061da546Spatrick     bt_l_shift = bt_l_shift_64;
96061da546Spatrick     bt_mask = bt_mask_64;
97061da546Spatrick   } else if (arch == llvm::Triple::ArchType::x86) {
98061da546Spatrick     mpx_base_mask = mpx_base_mask_32;
99061da546Spatrick     mpx_bd_mask = mpx_bd_mask_32;
100061da546Spatrick     bd_r_shift = bd_r_shift_32;
101061da546Spatrick     bd_l_shift = bd_l_shift_32;
102061da546Spatrick     bt_r_shift = bt_r_shift_32;
103061da546Spatrick     bt_l_shift = bt_l_shift_32;
104061da546Spatrick     bt_mask = bt_mask_32;
105061da546Spatrick   } else {
106061da546Spatrick     result.SetError("Invalid arch.");
107061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
108061da546Spatrick     return false;
109061da546Spatrick   }
110061da546Spatrick 
111061da546Spatrick   size = target.GetAddressByteSize();
112061da546Spatrick   lldb::addr_t mpx_bd_base = bndcfgu & mpx_base_mask;
113061da546Spatrick   lldb::addr_t bd_entry_offset = ((ptr & mpx_bd_mask) >> bd_r_shift)
114061da546Spatrick                                  << bd_l_shift;
115061da546Spatrick   lldb::addr_t bd_entry_addr = mpx_bd_base + bd_entry_offset;
116061da546Spatrick 
117061da546Spatrick   std::vector<uint8_t> bd_entry_v(size);
118061da546Spatrick   size_t ret = target.GetProcess().ReadMemory(
119061da546Spatrick       bd_entry_addr, static_cast<void *>(bd_entry_v.data()), size, error);
120061da546Spatrick   if (ret != size || !error.Success()) {
121061da546Spatrick     result.SetError("Failed access to BD entry.");
122061da546Spatrick     return false;
123061da546Spatrick   }
124061da546Spatrick 
125061da546Spatrick   lldb::SBData data;
126061da546Spatrick   data.SetData(error, bd_entry_v.data(), bd_entry_v.size(),
127061da546Spatrick                target.GetByteOrder(), size);
128061da546Spatrick   lldb::addr_t bd_entry = data.GetAddress(error, 0);
129061da546Spatrick 
130061da546Spatrick   if (!error.Success()) {
131061da546Spatrick     result.SetError("Failed access to BD entry.");
132061da546Spatrick     return false;
133061da546Spatrick   }
134061da546Spatrick 
135061da546Spatrick   if ((bd_entry & 0x01) == 0) {
136061da546Spatrick     result.SetError("Invalid bound directory.");
137061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
138061da546Spatrick     return false;
139061da546Spatrick   }
140061da546Spatrick 
141061da546Spatrick   // Clear status bit.
142061da546Spatrick   //
143061da546Spatrick   bd_entry--;
144061da546Spatrick 
145061da546Spatrick   lldb::addr_t bt_addr = bd_entry & ~bt_r_shift;
146061da546Spatrick   lldb::addr_t bt_entry_offset = ((ptr & bt_mask) >> bt_r_shift) << bt_l_shift;
147061da546Spatrick   bt_entry_addr = bt_addr + bt_entry_offset;
148061da546Spatrick 
149061da546Spatrick   return true;
150061da546Spatrick }
151061da546Spatrick 
GetBTEntry(uint64_t bndcfgu,uint64_t ptr,lldb::SBTarget & target,llvm::Triple::ArchType arch,lldb::SBCommandReturnObject & result,lldb::SBError & error)152061da546Spatrick static bool GetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::SBTarget &target,
153061da546Spatrick                        llvm::Triple::ArchType arch,
154061da546Spatrick                        lldb::SBCommandReturnObject &result,
155061da546Spatrick                        lldb::SBError &error) {
156061da546Spatrick   lldb::addr_t bt_entry_addr;
157061da546Spatrick   size_t size;
158061da546Spatrick   if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
159061da546Spatrick                       error))
160061da546Spatrick     return false;
161061da546Spatrick 
162061da546Spatrick   // bt_entry_v must have space to store the 4 elements of the BT entry (lower
163061da546Spatrick   // boundary,
164061da546Spatrick   // upper boundary, pointer value and meta data), which all have the same size
165061da546Spatrick   // 'size'.
166061da546Spatrick   //
167061da546Spatrick   std::vector<uint8_t> bt_entry_v(size * 4);
168061da546Spatrick   size_t ret = target.GetProcess().ReadMemory(
169061da546Spatrick       bt_entry_addr, static_cast<void *>(bt_entry_v.data()), size * 4, error);
170061da546Spatrick 
171061da546Spatrick   if ((ret != (size * 4)) || !error.Success()) {
172061da546Spatrick     result.SetError("Unsuccessful. Failed access to BT entry.");
173061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
174061da546Spatrick     return false;
175061da546Spatrick   }
176061da546Spatrick 
177061da546Spatrick   lldb::addr_t lbound;
178061da546Spatrick   lldb::addr_t ubound;
179061da546Spatrick   uint64_t value;
180061da546Spatrick   uint64_t meta;
181061da546Spatrick   lldb::SBData data;
182061da546Spatrick   data.SetData(error, bt_entry_v.data(), bt_entry_v.size(),
183061da546Spatrick                target.GetByteOrder(), size);
184061da546Spatrick   lbound = data.GetAddress(error, size * 0);
185061da546Spatrick   ubound = data.GetAddress(error, size * 1);
186061da546Spatrick   value = data.GetAddress(error, size * 2);
187061da546Spatrick   meta = data.GetAddress(error, size * 3);
188061da546Spatrick   // ubound is stored as one's complement.
189061da546Spatrick   if (arch == llvm::Triple::ArchType::x86) {
190061da546Spatrick     ubound = (~ubound) & 0x00000000FFFFFFFF;
191061da546Spatrick   } else {
192061da546Spatrick     ubound = ~ubound;
193061da546Spatrick   }
194061da546Spatrick 
195061da546Spatrick   if (!error.Success()) {
196061da546Spatrick     result.SetError("Failed access to BT entry.");
197061da546Spatrick     return false;
198061da546Spatrick   }
199061da546Spatrick 
200061da546Spatrick   PrintBTEntry(lbound, ubound, value, meta, result);
201061da546Spatrick 
202061da546Spatrick   result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
203061da546Spatrick   return true;
204061da546Spatrick }
205061da546Spatrick 
uIntToU8(uint64_t input,size_t size)206061da546Spatrick static std::vector<uint8_t> uIntToU8(uint64_t input, size_t size) {
207061da546Spatrick   std::vector<uint8_t> output;
208061da546Spatrick   for (size_t i = 0; i < size; i++)
209061da546Spatrick     output.push_back(
210061da546Spatrick         static_cast<uint8_t>((input & (0xFFULL << (i * 8))) >> (i * 8)));
211061da546Spatrick 
212061da546Spatrick   return output;
213061da546Spatrick }
214061da546Spatrick 
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)215061da546Spatrick static bool SetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::addr_t lbound,
216061da546Spatrick                        lldb::addr_t ubound, lldb::SBTarget &target,
217061da546Spatrick                        llvm::Triple::ArchType arch,
218061da546Spatrick                        lldb::SBCommandReturnObject &result,
219061da546Spatrick                        lldb::SBError &error) {
220061da546Spatrick   lldb::addr_t bt_entry_addr;
221061da546Spatrick   size_t size;
222061da546Spatrick 
223061da546Spatrick   if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
224061da546Spatrick                       error))
225061da546Spatrick     return false;
226061da546Spatrick 
227061da546Spatrick   // bt_entry_v must have space to store only 2 elements of the BT Entry, the
228061da546Spatrick   // lower boundary and the upper boundary, which both have size 'size'.
229061da546Spatrick   //
230061da546Spatrick   std::vector<uint8_t> bt_entry_v(size * 2);
231061da546Spatrick 
232061da546Spatrick   std::vector<uint8_t> lbound_v = uIntToU8(lbound, size);
233061da546Spatrick   bt_entry_v.insert(bt_entry_v.begin(), lbound_v.begin(), lbound_v.end());
234061da546Spatrick   std::vector<uint8_t> ubound_v = uIntToU8(~ubound, size);
235061da546Spatrick   bt_entry_v.insert(bt_entry_v.begin() + size, ubound_v.begin(),
236061da546Spatrick                     ubound_v.end());
237061da546Spatrick 
238061da546Spatrick   size_t ret = target.GetProcess().WriteMemory(
239061da546Spatrick       bt_entry_addr, (void *)(bt_entry_v.data()), size * 2, error);
240061da546Spatrick   if ((ret != (size * 2)) || !error.Success()) {
241061da546Spatrick     result.SetError("Failed access to BT entry.");
242061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
243061da546Spatrick     return false;
244061da546Spatrick   }
245061da546Spatrick 
246061da546Spatrick   result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
247061da546Spatrick   return true;
248061da546Spatrick }
249061da546Spatrick 
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)250061da546Spatrick static bool GetInitInfo(lldb::SBDebugger debugger, lldb::SBTarget &target,
251061da546Spatrick                         llvm::Triple::ArchType &arch, uint64_t &bndcfgu,
252061da546Spatrick                         char *arg, uint64_t &ptr,
253061da546Spatrick                         lldb::SBCommandReturnObject &result,
254061da546Spatrick                         lldb::SBError &error) {
255061da546Spatrick   target = debugger.GetSelectedTarget();
256061da546Spatrick   if (!target.IsValid()) {
257061da546Spatrick     result.SetError("Invalid target.");
258061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
259061da546Spatrick     return false;
260061da546Spatrick   }
261061da546Spatrick 
262061da546Spatrick   const std::string triple_s(target.GetTriple());
263061da546Spatrick   const llvm::Triple triple(triple_s);
264061da546Spatrick 
265061da546Spatrick   arch = triple.getArch();
266061da546Spatrick 
267061da546Spatrick   if ((arch != llvm::Triple::ArchType::x86) &&
268061da546Spatrick       (arch != llvm::Triple::ArchType::x86_64)) {
269061da546Spatrick     result.SetError("Platform not supported.");
270061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
271061da546Spatrick     return false;
272061da546Spatrick   }
273061da546Spatrick 
274061da546Spatrick   lldb::SBFrame frame =
275061da546Spatrick       target.GetProcess().GetSelectedThread().GetSelectedFrame();
276061da546Spatrick   if (!frame.IsValid()) {
277061da546Spatrick     result.SetError("No valid process, thread or frame.");
278061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
279061da546Spatrick     return false;
280061da546Spatrick   }
281061da546Spatrick 
282061da546Spatrick   lldb::SBValue bndcfgu_val = frame.FindRegister("bndcfgu");
283061da546Spatrick   if (!bndcfgu_val.IsValid()) {
284061da546Spatrick     result.SetError("Cannot access register BNDCFGU. Does the target support "
285061da546Spatrick                     "Intel(R) Memory Protection Extensions (Intel(R) MPX)?");
286061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
287061da546Spatrick     return false;
288061da546Spatrick   }
289061da546Spatrick 
290061da546Spatrick   lldb::SBData bndcfgu_data = bndcfgu_val.GetData();
291061da546Spatrick   bndcfgu = bndcfgu_data.GetUnsignedInt64(error, 0);
292061da546Spatrick   if (!error.Success()) {
293061da546Spatrick     result.SetError(error, "Invalid read of register BNDCFGU.");
294061da546Spatrick     return false;
295061da546Spatrick   }
296061da546Spatrick 
297061da546Spatrick   if (!GetPtr(arg, ptr, frame, result))
298061da546Spatrick     return false;
299061da546Spatrick 
300061da546Spatrick   return true;
301061da546Spatrick }
302061da546Spatrick 
303061da546Spatrick class MPXTableShow : public lldb::SBCommandPluginInterface {
304061da546Spatrick public:
DoExecute(lldb::SBDebugger debugger,char ** command,lldb::SBCommandReturnObject & result)305061da546Spatrick   bool DoExecute(lldb::SBDebugger debugger, char **command,
306061da546Spatrick                  lldb::SBCommandReturnObject &result) override {
307061da546Spatrick 
308061da546Spatrick     if (command) {
309061da546Spatrick       int arg_c = 0;
310061da546Spatrick       char *arg;
311061da546Spatrick 
312061da546Spatrick       while (*command) {
313061da546Spatrick         if (arg_c >= 1) {
314061da546Spatrick           result.SetError("Too many arguments. See help.");
315061da546Spatrick           result.SetStatus(lldb::eReturnStatusFailed);
316061da546Spatrick           return false;
317061da546Spatrick         }
318061da546Spatrick         arg_c++;
319061da546Spatrick         arg = *command;
320061da546Spatrick         command++;
321061da546Spatrick       }
322061da546Spatrick 
323061da546Spatrick       if (!debugger.IsValid()) {
324061da546Spatrick         result.SetError("Invalid debugger.");
325061da546Spatrick         result.SetStatus(lldb::eReturnStatusFailed);
326061da546Spatrick         return false;
327061da546Spatrick       }
328061da546Spatrick 
329061da546Spatrick       lldb::SBTarget target;
330061da546Spatrick       llvm::Triple::ArchType arch;
331061da546Spatrick       lldb::SBError error;
332061da546Spatrick       uint64_t bndcfgu;
333061da546Spatrick       uint64_t ptr;
334061da546Spatrick 
335061da546Spatrick       if (!GetInitInfo(debugger, target, arch, bndcfgu, arg, ptr, result,
336061da546Spatrick                        error))
337061da546Spatrick         return false;
338061da546Spatrick 
339061da546Spatrick       return GetBTEntry(bndcfgu, ptr, target, arch, result, error);
340061da546Spatrick     }
341061da546Spatrick 
342061da546Spatrick     result.SetError("Too few arguments. See help.");
343061da546Spatrick     result.SetStatus(lldb::eReturnStatusFailed);
344061da546Spatrick     return false;
345061da546Spatrick   }
346061da546Spatrick };
347061da546Spatrick 
348061da546Spatrick class MPXTableSet : public lldb::SBCommandPluginInterface {
349061da546Spatrick public:
DoExecute(lldb::SBDebugger debugger,char ** command,lldb::SBCommandReturnObject & result)350061da546Spatrick   bool DoExecute(lldb::SBDebugger debugger, char **command,
351061da546Spatrick                  lldb::SBCommandReturnObject &result) override {
352061da546Spatrick 
353061da546Spatrick     if (command) {
354061da546Spatrick       int arg_c = 0;
355061da546Spatrick       char *arg[3];
356061da546Spatrick 
357061da546Spatrick       while (*command) {
358061da546Spatrick         arg[arg_c] = *command;
359061da546Spatrick         command++;
360061da546Spatrick         arg_c++;
361061da546Spatrick       }
362061da546Spatrick 
363061da546Spatrick       if (arg_c != 3) {
364061da546Spatrick         result.SetError("Wrong arguments. See help.");
365061da546Spatrick         return false;
366061da546Spatrick       }
367061da546Spatrick 
368061da546Spatrick       if (!debugger.IsValid()) {
369061da546Spatrick         result.SetError("Invalid debugger.");
370061da546Spatrick         return false;
371061da546Spatrick       }
372061da546Spatrick 
373061da546Spatrick       lldb::SBTarget target;
374061da546Spatrick       llvm::Triple::ArchType arch;
375061da546Spatrick       lldb::SBError error;
376061da546Spatrick       uint64_t bndcfgu;
377061da546Spatrick       uint64_t ptr;
378061da546Spatrick 
379061da546Spatrick       if (!GetInitInfo(debugger, target, arch, bndcfgu, arg[0], ptr, result,
380061da546Spatrick                        error))
381061da546Spatrick         return false;
382061da546Spatrick 
383061da546Spatrick       char *endptr;
384061da546Spatrick       errno = 0;
385061da546Spatrick       uint64_t lbound = std::strtoul(arg[1], &endptr, 16);
386061da546Spatrick       if (endptr == arg[1] || errno == ERANGE) {
387061da546Spatrick         result.SetError("Lower Bound: bad argument format.");
388061da546Spatrick         errno = 0;
389061da546Spatrick         return false;
390061da546Spatrick       }
391061da546Spatrick 
392061da546Spatrick       uint64_t ubound = std::strtoul(arg[2], &endptr, 16);
393061da546Spatrick       if (endptr == arg[1] || errno == ERANGE) {
394061da546Spatrick         result.SetError("Upper Bound: bad argument format.");
395061da546Spatrick         errno = 0;
396061da546Spatrick         return false;
397061da546Spatrick       }
398061da546Spatrick 
399061da546Spatrick       return SetBTEntry(bndcfgu, ptr, lbound, ubound, target, arch, result,
400061da546Spatrick                         error);
401061da546Spatrick     }
402061da546Spatrick 
403061da546Spatrick     result.SetError("Too few arguments. See help.");
404061da546Spatrick     return false;
405061da546Spatrick   }
406061da546Spatrick };
407061da546Spatrick 
MPXPluginInitialize(lldb::SBDebugger & debugger)408061da546Spatrick bool MPXPluginInitialize(lldb::SBDebugger &debugger) {
409061da546Spatrick   lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
410061da546Spatrick   lldb::SBCommand mpxTable = interpreter.AddMultiwordCommand(
411061da546Spatrick       "mpx-table", "A utility to access the Intel(R) MPX table entries.");
412061da546Spatrick 
413061da546Spatrick   const char *mpx_show_help = "Show the Intel(R) MPX table entry of a pointer."
414061da546Spatrick                               "\nmpx-table show <pointer>";
415061da546Spatrick   mpxTable.AddCommand("show", new MPXTableShow(), mpx_show_help);
416061da546Spatrick 
417061da546Spatrick   const char *mpx_set_help =
418061da546Spatrick       "Set the Intel(R) MPX table entry of a pointer.\n"
419061da546Spatrick       "mpx-table set <pointer> <lower bound> <upper bound>";
420061da546Spatrick   mpxTable.AddCommand("set", new MPXTableSet(), mpx_set_help);
421061da546Spatrick 
422061da546Spatrick   return true;
423061da546Spatrick }
424