Bug Summary

File:tools/lldb/tools/intel-mpx/IntelMPXTablePlugin.cpp
Warning:line 339, column 12
5th function call argument is an uninitialized value

Annotated Source Code

1//===-- IntelMPXTablePlugin.cpp----------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// C++ includes
11#include <cerrno>
12#include <string>
13
14// Project includes
15#include "lldb/API/SBCommandInterpreter.h"
16#include "lldb/API/SBCommandReturnObject.h"
17#include "lldb/API/SBMemoryRegionInfo.h"
18#include "lldb/API/SBProcess.h"
19#include "lldb/API/SBTarget.h"
20#include "lldb/API/SBThread.h"
21
22#include "llvm/ADT/Triple.h"
23
24namespace lldb {
25bool PluginInitialize(lldb::SBDebugger debugger);
26}
27
28static bool GetPtr(char *cptr, uint64_t &ptr, lldb::SBFrame &frame,
29 lldb::SBCommandReturnObject &result) {
30 if (!cptr) {
31 result.SetError("Bad argument.");
32 result.SetStatus(lldb::eReturnStatusFailed);
33 return false;
34 }
35
36 lldb::SBValue ptr_addr = frame.GetValueForVariablePath(cptr);
37 if (!ptr_addr.IsValid()) {
38 result.SetError("Invalid pointer.");
39 result.SetStatus(lldb::eReturnStatusFailed);
40 return false;
41 }
42 ptr = ptr_addr.GetLoadAddress();
43 return true;
44}
45
46enum {
47 mpx_base_mask_64 = ~(uint64_t)0xFFFULL,
48 mpx_bd_mask_64 = 0xFFFFFFF00000ULL,
49 bd_r_shift_64 = 20,
50 bd_l_shift_64 = 3,
51 bt_r_shift_64 = 3,
52 bt_l_shift_64 = 5,
53 bt_mask_64 = 0x0000000FFFF8ULL,
54
55 mpx_base_mask_32 = 0xFFFFFFFFFFFFF000ULL,
56 mpx_bd_mask_32 = 0xFFFFF000ULL,
57 bd_r_shift_32 = 12,
58 bd_l_shift_32 = 2,
59 bt_r_shift_32 = 2,
60 bt_l_shift_32 = 4,
61 bt_mask_32 = 0x00000FFCULL,
62};
63
64static void PrintBTEntry(lldb::addr_t lbound, lldb::addr_t ubound,
65 uint64_t value, uint64_t meta,
66 lldb::SBCommandReturnObject &result) {
67 const lldb::addr_t one_cmpl64 = ~((lldb::addr_t)0);
68 const lldb::addr_t one_cmpl32 = ~((uint32_t)0);
69
70 if ((lbound == one_cmpl64 || one_cmpl32) && ubound == 0) {
71 result.Printf("Null bounds on map: pointer value = 0x%lx\n", value);
72 } else {
73 result.Printf(" lbound = 0x%lx,", lbound);
74 result.Printf(" ubound = 0x%lx", ubound);
75 result.Printf(" (pointer value = 0x%lx,", value);
76 result.Printf(" metadata = 0x%lx)\n", meta);
77 }
78}
79
80static bool GetBTEntryAddr(uint64_t bndcfgu, uint64_t ptr,
81 lldb::SBTarget &target, llvm::Triple::ArchType arch,
82 size_t &size, lldb::addr_t &bt_entry_addr,
83 lldb::SBCommandReturnObject &result,
84 lldb::SBError &error) {
85 lldb::addr_t mpx_base_mask;
86 lldb::addr_t mpx_bd_mask;
87 lldb::addr_t bd_r_shift;
88 lldb::addr_t bd_l_shift;
89 lldb::addr_t bt_r_shift;
90 lldb::addr_t bt_l_shift;
91 lldb::addr_t bt_mask;
92
93 if (arch == llvm::Triple::ArchType::x86_64) {
94 mpx_base_mask = mpx_base_mask_64;
95 mpx_bd_mask = mpx_bd_mask_64;
96 bd_r_shift = bd_r_shift_64;
97 bd_l_shift = bd_l_shift_64;
98 bt_r_shift = bt_r_shift_64;
99 bt_l_shift = bt_l_shift_64;
100 bt_mask = bt_mask_64;
101 } else if (arch == llvm::Triple::ArchType::x86) {
102 mpx_base_mask = mpx_base_mask_32;
103 mpx_bd_mask = mpx_bd_mask_32;
104 bd_r_shift = bd_r_shift_32;
105 bd_l_shift = bd_l_shift_32;
106 bt_r_shift = bt_r_shift_32;
107 bt_l_shift = bt_l_shift_32;
108 bt_mask = bt_mask_32;
109 } else {
110 result.SetError("Invalid arch.");
111 result.SetStatus(lldb::eReturnStatusFailed);
112 return false;
113 }
114
115 size = target.GetAddressByteSize();
116 lldb::addr_t mpx_bd_base = bndcfgu & mpx_base_mask;
117 lldb::addr_t bd_entry_offset = ((ptr & mpx_bd_mask) >> bd_r_shift)
118 << bd_l_shift;
119 lldb::addr_t bd_entry_addr = mpx_bd_base + bd_entry_offset;
120
121 std::vector<uint8_t> bd_entry_v(size);
122 size_t ret = target.GetProcess().ReadMemory(
123 bd_entry_addr, static_cast<void *>(bd_entry_v.data()), size, error);
124 if (ret != size || !error.Success()) {
125 result.SetError("Failed access to BD entry.");
126 return false;
127 }
128
129 lldb::SBData data;
130 data.SetData(error, bd_entry_v.data(), bd_entry_v.size(),
131 target.GetByteOrder(), size);
132 lldb::addr_t bd_entry = data.GetAddress(error, 0);
133
134 if (!error.Success()) {
135 result.SetError("Failed access to BD entry.");
136 return false;
137 }
138
139 if ((bd_entry & 0x01) == 0) {
140 result.SetError("Invalid bound directory.");
141 result.SetStatus(lldb::eReturnStatusFailed);
142 return false;
143 }
144
145 // Clear status bit.
146 //
147 bd_entry--;
148
149 lldb::addr_t bt_addr = bd_entry & ~bt_r_shift;
150 lldb::addr_t bt_entry_offset = ((ptr & bt_mask) >> bt_r_shift) << bt_l_shift;
151 bt_entry_addr = bt_addr + bt_entry_offset;
152
153 return true;
154}
155
156static bool GetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::SBTarget &target,
157 llvm::Triple::ArchType arch,
158 lldb::SBCommandReturnObject &result,
159 lldb::SBError &error) {
160 lldb::addr_t bt_entry_addr;
161 size_t size;
162 if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
163 error))
164 return false;
165
166 // bt_entry_v must have space to store the 4 elements of the BT entry (lower
167 // boundary,
168 // upper boundary, pointer value and meta data), which all have the same size
169 // 'size'.
170 //
171 std::vector<uint8_t> bt_entry_v(size * 4);
172 size_t ret = target.GetProcess().ReadMemory(
173 bt_entry_addr, static_cast<void *>(bt_entry_v.data()), size * 4, error);
174
175 if ((ret != (size * 4)) || !error.Success()) {
176 result.SetError("Unsuccessful. Failed access to BT entry.");
177 result.SetStatus(lldb::eReturnStatusFailed);
178 return false;
179 }
180
181 lldb::addr_t lbound;
182 lldb::addr_t ubound;
183 uint64_t value;
184 uint64_t meta;
185 lldb::SBData data;
186 data.SetData(error, bt_entry_v.data(), bt_entry_v.size(),
187 target.GetByteOrder(), size);
188 lbound = data.GetAddress(error, size * 0);
189 ubound = data.GetAddress(error, size * 1);
190 value = data.GetAddress(error, size * 2);
191 meta = data.GetAddress(error, size * 3);
192 // ubound is stored as one's complement.
193 if (arch == llvm::Triple::ArchType::x86) {
194 ubound = (~ubound) & 0x00000000FFFFFFFF;
195 } else {
196 ubound = ~ubound;
197 }
198
199 if (!error.Success()) {
200 result.SetError("Failed access to BT entry.");
201 return false;
202 }
203
204 PrintBTEntry(lbound, ubound, value, meta, result);
205
206 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
207 return true;
208}
209
210static std::vector<uint8_t> uIntToU8(uint64_t input, size_t size) {
211 std::vector<uint8_t> output;
212 for (size_t i = 0; i < size; i++)
213 output.push_back(
214 static_cast<uint8_t>((input & (0xFFULL << (i * 8))) >> (i * 8)));
215
216 return output;
217}
218
219static bool SetBTEntry(uint64_t bndcfgu, uint64_t ptr, lldb::addr_t lbound,
220 lldb::addr_t ubound, lldb::SBTarget &target,
221 llvm::Triple::ArchType arch,
222 lldb::SBCommandReturnObject &result,
223 lldb::SBError &error) {
224 lldb::addr_t bt_entry_addr;
225 size_t size;
226
227 if (!GetBTEntryAddr(bndcfgu, ptr, target, arch, size, bt_entry_addr, result,
228 error))
229 return false;
230
231 // bt_entry_v must have space to store only 2 elements of the BT Entry, the
232 // lower boundary and the upper boundary, which both have size 'size'.
233 //
234 std::vector<uint8_t> bt_entry_v(size * 2);
235
236 std::vector<uint8_t> lbound_v = uIntToU8(lbound, size);
237 bt_entry_v.insert(bt_entry_v.begin(), lbound_v.begin(), lbound_v.end());
238 std::vector<uint8_t> ubound_v = uIntToU8(~ubound, size);
239 bt_entry_v.insert(bt_entry_v.begin() + size, ubound_v.begin(),
240 ubound_v.end());
241
242 size_t ret = target.GetProcess().WriteMemory(
243 bt_entry_addr, (void *)(bt_entry_v.data()), size * 2, error);
244 if ((ret != (size * 2)) || !error.Success()) {
245 result.SetError("Failed access to BT entry.");
246 result.SetStatus(lldb::eReturnStatusFailed);
247 return false;
248 }
249
250 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
251 return true;
252}
253
254static bool GetInitInfo(lldb::SBDebugger debugger, lldb::SBTarget &target,
255 llvm::Triple::ArchType &arch, uint64_t &bndcfgu,
256 char *arg, uint64_t &ptr,
257 lldb::SBCommandReturnObject &result,
258 lldb::SBError &error) {
259 target = debugger.GetSelectedTarget();
260 if (!target.IsValid()) {
261 result.SetError("Invalid target.");
262 result.SetStatus(lldb::eReturnStatusFailed);
263 return false;
264 }
265
266 const std::string triple_s(target.GetTriple());
267 const llvm::Triple triple(triple_s);
268
269 arch = triple.getArch();
270
271 if ((arch != llvm::Triple::ArchType::x86) &&
272 (arch != llvm::Triple::ArchType::x86_64)) {
273 result.SetError("Platform not supported.");
274 result.SetStatus(lldb::eReturnStatusFailed);
275 return false;
276 }
277
278 lldb::SBFrame frame =
279 target.GetProcess().GetSelectedThread().GetSelectedFrame();
280 if (!frame.IsValid()) {
281 result.SetError("No valid process, thread or frame.");
282 result.SetStatus(lldb::eReturnStatusFailed);
283 return false;
284 }
285
286 lldb::SBValue bndcfgu_val = frame.FindRegister("bndcfgu");
287 if (!bndcfgu_val.IsValid()) {
288 result.SetError(
289 "Cannot access register BNDCFGU. Does the target support MPX?");
290 result.SetStatus(lldb::eReturnStatusFailed);
291 return false;
292 }
293
294 lldb::SBData bndcfgu_data = bndcfgu_val.GetData();
295 bndcfgu = bndcfgu_data.GetUnsignedInt64(error, 0);
296 if (!error.Success()) {
297 result.SetError(error, "Invalid read of register BNDCFGU.");
298 return false;
299 }
300
301 if (!GetPtr(arg, ptr, frame, result))
302 return false;
303
304 return true;
305}
306
307class MPXTableShow : public lldb::SBCommandPluginInterface {
308public:
309 virtual bool DoExecute(lldb::SBDebugger debugger, char **command,
310 lldb::SBCommandReturnObject &result) {
311
312 if (command) {
1
Assuming 'command' is non-null
2
Taking true branch
313 int arg_c = 0;
314 char *arg;
3
'arg' declared without an initial value
315
316 while (*command) {
4
Loop condition is false. Execution continues on line 327
317 if (arg_c >= 1) {
318 result.SetError("Too many arguments. See help.");
319 result.SetStatus(lldb::eReturnStatusFailed);
320 return false;
321 }
322 arg_c++;
323 arg = *command;
324 command++;
325 }
326
327 if (!debugger.IsValid()) {
5
Assuming the condition is false
6
Taking false branch
328 result.SetError("Invalid debugger.");
329 result.SetStatus(lldb::eReturnStatusFailed);
330 return false;
331 }
332
333 lldb::SBTarget target;
334 llvm::Triple::ArchType arch;
335 lldb::SBError error;
336 uint64_t bndcfgu;
337 uint64_t ptr;
338
339 if (!GetInitInfo(debugger, target, arch, bndcfgu, arg, ptr, result,
7
5th function call argument is an uninitialized value
340 error))
341 return false;
342
343 return GetBTEntry(bndcfgu, ptr, target, arch, result, error);
344 }
345
346 result.SetError("Too few arguments. See help.");
347 result.SetStatus(lldb::eReturnStatusFailed);
348 return false;
349 }
350};
351
352class MPXTableSet : public lldb::SBCommandPluginInterface {
353public:
354 virtual bool DoExecute(lldb::SBDebugger debugger, char **command,
355 lldb::SBCommandReturnObject &result) {
356
357 if (command) {
358 int arg_c = 0;
359 char *arg[3];
360
361 while (*command) {
362 arg[arg_c] = *command;
363 command++;
364 arg_c++;
365 }
366
367 if (arg_c != 3) {
368 result.SetError("Wrong arguments. See help.");
369 return false;
370 }
371
372 if (!debugger.IsValid()) {
373 result.SetError("Invalid debugger.");
374 return false;
375 }
376
377 lldb::SBTarget target;
378 llvm::Triple::ArchType arch;
379 lldb::SBError error;
380 uint64_t bndcfgu;
381 uint64_t ptr;
382
383 if (!GetInitInfo(debugger, target, arch, bndcfgu, arg[0], ptr, result,
384 error))
385 return false;
386
387 char *endptr;
388 errno(*__errno_location ()) = 0;
389 uint64_t lbound = std::strtoul(arg[1], &endptr, 16);
390 if (endptr == arg[1] || errno(*__errno_location ()) == ERANGE34) {
391 result.SetError("Lower Bound: bad argument format.");
392 errno(*__errno_location ()) = 0;
393 return false;
394 }
395
396 uint64_t ubound = std::strtoul(arg[2], &endptr, 16);
397 if (endptr == arg[1] || errno(*__errno_location ()) == ERANGE34) {
398 result.SetError("Upper Bound: bad argument format.");
399 errno(*__errno_location ()) = 0;
400 return false;
401 }
402
403 return SetBTEntry(bndcfgu, ptr, lbound, ubound, target, arch, result,
404 error);
405 }
406
407 result.SetError("Too few arguments. See help.");
408 return false;
409 }
410};
411
412bool lldb::PluginInitialize(lldb::SBDebugger debugger) {
413 lldb::SBCommandInterpreter interpreter = debugger.GetCommandInterpreter();
414 lldb::SBCommand mpxTable = interpreter.AddMultiwordCommand(
415 "mpx-table", "A utility to access the MPX table entries.");
416
417 const char *mpx_show_help = "Show the MPX table entry of a pointer.\n"
418 "mpx-table show <pointer>";
419 mpxTable.AddCommand("show", new MPXTableShow(), mpx_show_help);
420
421 const char *mpx_set_help =
422 "Set the MPX table entry of a pointer.\n"
423 "mpx-table set <pointer> <lower bound> <upper bound>";
424 mpxTable.AddCommand("set", new MPXTableSet(), mpx_set_help);
425
426 return true;
427}