blob: 9400200070a2e03cba2b87e4f9212c7e1e91bc96 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- CommandObjectMemory.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#include "CommandObjectMemory.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000016#include "lldb/Core/DataBufferHeap.h"
17#include "lldb/Core/DataExtractor.h"
Greg Clayton63094e02010-06-23 01:19:29 +000018#include "lldb/Core/Debugger.h"
Chris Lattner24943d22010-06-08 16:52:24 +000019#include "lldb/Core/StreamString.h"
Greg Clayton63094e02010-06-23 01:19:29 +000020#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000021#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000022#include "lldb/Interpreter/CommandInterpreter.h"
23#include "lldb/Interpreter/Options.h"
Chris Lattner24943d22010-06-08 16:52:24 +000024#include "lldb/Target/Process.h"
25
26using namespace lldb;
27using namespace lldb_private;
28
29//----------------------------------------------------------------------
30// Read memory from the inferior process
31//----------------------------------------------------------------------
32class CommandObjectMemoryRead : public CommandObject
33{
34public:
35
36 class CommandOptions : public Options
37 {
38 public:
39 CommandOptions () :
40 Options()
41 {
42 ResetOptionValues();
43 }
44
45 virtual
46 ~CommandOptions ()
47 {
48 }
49
50 virtual Error
51 SetOptionValue (int option_idx, const char *option_arg)
52 {
53 Error error;
54 char short_option = (char) m_getopt_table[option_idx].val;
55
56 switch (short_option)
57 {
58 case 'f':
59 error = Args::StringToFormat (option_arg, m_format);
60
61 switch (m_format)
62 {
63 default:
64 break;
65
66 case eFormatBoolean:
67 if (m_byte_size == 0)
68 m_byte_size = 1;
69 if (m_num_per_line == 0)
70 m_num_per_line = 1;
71 break;
72
73 case eFormatCString:
74 if (m_num_per_line == 0)
75 m_num_per_line = 1;
76 break;
77
78 case eFormatPointer:
79 break;
80
81 case eFormatBinary:
82 case eFormatFloat:
83 case eFormatOctal:
84 case eFormatDecimal:
85 case eFormatEnum:
86 case eFormatUnicode16:
87 case eFormatUnicode32:
88 case eFormatUnsigned:
89 if (m_byte_size == 0)
90 m_byte_size = 4;
91 if (m_num_per_line == 0)
92 m_num_per_line = 1;
93 break;
94
95 case eFormatBytes:
96 case eFormatBytesWithASCII:
97 case eFormatChar:
98 case eFormatCharPrintable:
99 if (m_byte_size == 0)
100 m_byte_size = 1;
101 break;
102 case eFormatComplex:
103 if (m_byte_size == 0)
104 m_byte_size = 8;
105 break;
106 case eFormatHex:
107 if (m_byte_size == 0)
108 m_byte_size = 4;
109 break;
110
111 case eFormatVectorOfChar:
112 case eFormatVectorOfSInt8:
113 case eFormatVectorOfUInt8:
114 case eFormatVectorOfSInt16:
115 case eFormatVectorOfUInt16:
116 case eFormatVectorOfSInt32:
117 case eFormatVectorOfUInt32:
118 case eFormatVectorOfSInt64:
119 case eFormatVectorOfUInt64:
120 case eFormatVectorOfFloat32:
121 case eFormatVectorOfFloat64:
122 case eFormatVectorOfUInt128:
123 break;
124 }
125 break;
126
127 case 'l':
128 m_num_per_line = Args::StringToUInt32 (option_arg, 0);
129 if (m_num_per_line == 0)
130 error.SetErrorStringWithFormat("Invalid value for --num-per-line option '%s'. Must be positive integer value.\n", option_arg);
131 break;
132
133 case 'c':
134 m_count = Args::StringToUInt32 (option_arg, 0);
135 if (m_count == 0)
136 error.SetErrorStringWithFormat("Invalid value for --count option '%s'. Must be positive integer value.\n", option_arg);
137 break;
138
139 case 's':
140 m_byte_size = Args::StringToUInt32 (option_arg, 0);
141 if (m_byte_size == 0)
142 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
143 break;
144
145 default:
146 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
147 break;
148 }
149 return error;
150 }
151
152 void
153 ResetOptionValues ()
154 {
155 Options::ResetOptionValues();
156 m_format = eFormatBytesWithASCII;
157 m_byte_size = 0;
158 m_count = 0;
159 m_num_per_line = 0;
160 }
161
162 const lldb::OptionDefinition*
163 GetDefinitions ()
164 {
165 return g_option_table;
166 }
167
168 // Options table: Required for subclasses of Options.
169
170 static lldb::OptionDefinition g_option_table[];
171
172 // Instance variables to hold the values for command options.
173 lldb::Format m_format;
174 uint32_t m_byte_size;
175 uint32_t m_count;
176 uint32_t m_num_per_line;
177 };
178
179 CommandObjectMemoryRead () :
180 CommandObject ("memory read",
181 "Read memory from the process being debugged.",
182 "memory read [<cmd-options>] <start-addr> [<end-addr>]",
183 eFlagProcessMustBeLaunched)
184 {
185 }
186
187 virtual
188 ~CommandObjectMemoryRead ()
189 {
190 }
191
192 Options *
193 GetOptions ()
194 {
195 return &m_options;
196 }
197
198 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000199 Execute (CommandInterpreter &interpreter,
200 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000201 CommandReturnObject &result)
202 {
Greg Clayton63094e02010-06-23 01:19:29 +0000203 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000204 if (process == NULL)
205 {
206 result.AppendError("need a process to read memory");
207 result.SetStatus(eReturnStatusFailed);
208 return false;
209 }
210 const size_t argc = command.GetArgumentCount();
211
212 if (argc == 0 || argc > 2)
213 {
214 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
215 result.SetStatus(eReturnStatusFailed);
216 return false;
217 }
218
219 size_t item_byte_size = m_options.m_byte_size;
220 if (item_byte_size == 0)
221 {
222 if (m_options.m_format == eFormatPointer)
223 item_byte_size = process->GetAddressByteSize();
224 else
225 item_byte_size = 1;
226 }
227
228 size_t item_count = m_options.m_count;
229
230 size_t num_per_line = m_options.m_num_per_line;
231 if (num_per_line == 0)
232 {
233 num_per_line = (16/item_byte_size);
234 if (num_per_line == 0)
235 num_per_line = 1;
236 }
237
238 size_t total_byte_size = m_options.m_count * item_byte_size;
239 if (total_byte_size == 0)
240 total_byte_size = 32;
241
242 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
243
244 if (addr == LLDB_INVALID_ADDRESS)
245 {
246 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
247 result.SetStatus(eReturnStatusFailed);
248 return false;
249 }
250
251 if (argc == 2)
252 {
253 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
254 if (end_addr == LLDB_INVALID_ADDRESS)
255 {
256 result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
257 result.SetStatus(eReturnStatusFailed);
258 return false;
259 }
260 else if (end_addr <= addr)
261 {
262 result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
263 result.SetStatus(eReturnStatusFailed);
264 return false;
265 }
266 else if (item_count != 0)
267 {
268 result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
269 result.SetStatus(eReturnStatusFailed);
270 return false;
271 }
272
273 total_byte_size = end_addr - addr;
274 item_count = total_byte_size / item_byte_size;
275 }
276 else
277 {
278 if (item_count == 0)
279 item_count = 32;
280 }
281
282 DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
283 Error error;
284 size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
285 if (bytes_read == 0)
286 {
287 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
288 result.AppendError(error.AsCString());
289 result.SetStatus(eReturnStatusFailed);
290 return false;
291 }
292
293 if (bytes_read < total_byte_size)
294 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
295
296 result.SetStatus(eReturnStatusSuccessFinishResult);
297 DataExtractor data(data_sp, process->GetByteOrder(), process->GetAddressByteSize());
298
299 Stream &output_stream = result.GetOutputStream();
300 data.Dump(&output_stream,
301 0,
302 m_options.m_format,
303 item_byte_size,
304 item_count,
305 num_per_line,
306 addr,
307 0,
308 0);
309 output_stream.EOL();
310 return true;
311 }
312
313protected:
314 CommandOptions m_options;
315};
316
317lldb::OptionDefinition
318CommandObjectMemoryRead::CommandOptions::g_option_table[] =
319{
Jim Ingham34e9a982010-06-15 18:47:14 +0000320 { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "<format>", "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
321 { LLDB_OPT_SET_1, false, "size", 's', required_argument, NULL, 0, "<byte-size>","The size in bytes to use when displaying with the selected format."},
322 { LLDB_OPT_SET_1, false, "num-per-line", 'l', required_argument, NULL, 0, "<N>", "The number of items per line to display."},
323 { LLDB_OPT_SET_1, false, "count", 'c', required_argument, NULL, 0, "<N>", "The number of total items to display."},
Chris Lattner24943d22010-06-08 16:52:24 +0000324 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
325};
326
327
328//----------------------------------------------------------------------
329// Write memory to the inferior process
330//----------------------------------------------------------------------
331class CommandObjectMemoryWrite : public CommandObject
332{
333public:
334
335 class CommandOptions : public Options
336 {
337 public:
338 CommandOptions () :
339 Options()
340 {
341 ResetOptionValues();
342 }
343
344 virtual
345 ~CommandOptions ()
346 {
347 }
348
349 virtual Error
350 SetOptionValue (int option_idx, const char *option_arg)
351 {
352 Error error;
353 char short_option = (char) m_getopt_table[option_idx].val;
354 switch (short_option)
355 {
356 case 'f':
357 error = Args::StringToFormat (option_arg, m_format);
358 break;
359
360 case 's':
361 m_byte_size = Args::StringToUInt32 (option_arg, 0);
362 if (m_byte_size == 0)
363 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
364 break;
365
366
367 default:
368 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
369 break;
370 }
371 return error;
372 }
373
374 void
375 ResetOptionValues ()
376 {
377 Options::ResetOptionValues();
378 m_format = eFormatBytes;
379 m_byte_size = 1;
380 }
381
382 const lldb::OptionDefinition*
383 GetDefinitions ()
384 {
385 return g_option_table;
386 }
387
388 // Options table: Required for subclasses of Options.
389
390 static lldb::OptionDefinition g_option_table[];
391
392 // Instance variables to hold the values for command options.
393 lldb::Format m_format;
394 uint32_t m_byte_size;
395 };
396
397 CommandObjectMemoryWrite () :
398 CommandObject ("memory write",
399 "Write memory to the process being debugged.",
400 "memory write [<cmd-options>] <addr> [value1 value2 ...]",
401 eFlagProcessMustBeLaunched)
402 {
403 }
404
405 virtual
406 ~CommandObjectMemoryWrite ()
407 {
408 }
409
410 Options *
411 GetOptions ()
412 {
413 return &m_options;
414 }
415
416 bool
417 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
418 {
419 if (total_byte_size > 8)
420 return false;
421
422 if (total_byte_size == 8)
423 return true;
424
425 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
426 return uval64 <= max;
427 }
428
429 bool
430 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
431 {
432 if (total_byte_size > 8)
433 return false;
434
435 if (total_byte_size == 8)
436 return true;
437
438 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
439 const int64_t min = ~(max);
440 return min <= sval64 && sval64 <= max;
441 }
442
443 virtual bool
Greg Clayton63094e02010-06-23 01:19:29 +0000444 Execute (CommandInterpreter &interpreter,
445 Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000446 CommandReturnObject &result)
447 {
Greg Clayton63094e02010-06-23 01:19:29 +0000448 Process *process = interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000449 if (process == NULL)
450 {
451 result.AppendError("need a process to read memory");
452 result.SetStatus(eReturnStatusFailed);
453 return false;
454 }
455
456 const size_t argc = command.GetArgumentCount();
457
458 if (argc < 2)
459 {
460 result.AppendErrorWithFormat ("%s takes an address and at least one value.\n", m_cmd_name.c_str());
461 result.SetStatus(eReturnStatusFailed);
462 return false;
463 }
464
465 size_t item_byte_size = m_options.m_byte_size ? m_options.m_byte_size : 1;
466 StreamString buffer (Stream::eBinary,
467 process->GetAddressByteSize(),
468 process->GetByteOrder());
469
470 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
471
472 if (addr == LLDB_INVALID_ADDRESS)
473 {
474 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
475 result.SetStatus(eReturnStatusFailed);
476 return false;
477 }
478 command.Shift(); // shift off the address argument
479 uint64_t uval64;
480 int64_t sval64;
481 bool success = false;
482 const uint32_t num_value_args = command.GetArgumentCount();
483 uint32_t i;
484 for (i=0; i<num_value_args; ++i)
485 {
486 const char *value_str = command.GetArgumentAtIndex(i);
487
488 switch (m_options.m_format)
489 {
490 case eFormatFloat: // TODO: add support for floats soon
491 case eFormatCharPrintable:
492 case eFormatBytesWithASCII:
493 case eFormatComplex:
494 case eFormatEnum:
495 case eFormatUnicode16:
496 case eFormatUnicode32:
497 case eFormatVectorOfChar:
498 case eFormatVectorOfSInt8:
499 case eFormatVectorOfUInt8:
500 case eFormatVectorOfSInt16:
501 case eFormatVectorOfUInt16:
502 case eFormatVectorOfSInt32:
503 case eFormatVectorOfUInt32:
504 case eFormatVectorOfSInt64:
505 case eFormatVectorOfUInt64:
506 case eFormatVectorOfFloat32:
507 case eFormatVectorOfFloat64:
508 case eFormatVectorOfUInt128:
509 result.AppendError("unsupported format for writing memory");
510 result.SetStatus(eReturnStatusFailed);
511 return false;
512
513 case eFormatDefault:
514 case eFormatBytes:
515 case eFormatHex:
516 // Decode hex bytes
517 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
518 if (!success)
519 {
520 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
521 result.SetStatus(eReturnStatusFailed);
522 return false;
523 }
524 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
525 {
526 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
527 result.SetStatus(eReturnStatusFailed);
528 return false;
529 }
530 buffer.PutMaxHex64 (uval64, item_byte_size);
531 break;
532
533 case eFormatBoolean:
534 uval64 = Args::StringToBoolean(value_str, false, &success);
535 if (!success)
536 {
537 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
538 result.SetStatus(eReturnStatusFailed);
539 return false;
540 }
541 buffer.PutMaxHex64 (uval64, item_byte_size);
542 break;
543
544 case eFormatBinary:
545 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
546 if (!success)
547 {
548 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
549 result.SetStatus(eReturnStatusFailed);
550 return false;
551 }
552 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
553 {
554 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
555 result.SetStatus(eReturnStatusFailed);
556 return false;
557 }
558 buffer.PutMaxHex64 (uval64, item_byte_size);
559 break;
560
561 case eFormatChar:
562 case eFormatCString:
563 if (value_str[0])
564 {
565 size_t len = strlen (value_str);
566 // Include the NULL for C strings...
567 if (m_options.m_format == eFormatCString)
568 ++len;
569 Error error;
570 if (process->WriteMemory (addr, value_str, len, error) == len)
571 {
572 addr += len;
573 }
574 else
575 {
576 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
577 result.SetStatus(eReturnStatusFailed);
578 return false;
579 }
580 }
581 break;
582
583 case eFormatDecimal:
584 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
585 if (!success)
586 {
587 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
588 result.SetStatus(eReturnStatusFailed);
589 return false;
590 }
591 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
592 {
593 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
594 result.SetStatus(eReturnStatusFailed);
595 return false;
596 }
597 buffer.PutMaxHex64 (sval64, item_byte_size);
598 break;
599
600 case eFormatUnsigned:
601 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
602 if (!success)
603 {
604 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
609 {
610 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
611 result.SetStatus(eReturnStatusFailed);
612 return false;
613 }
614 buffer.PutMaxHex64 (uval64, item_byte_size);
615 break;
616
617 case eFormatOctal:
618 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
619 if (!success)
620 {
621 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
622 result.SetStatus(eReturnStatusFailed);
623 return false;
624 }
625 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
626 {
627 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
631 buffer.PutMaxHex64 (uval64, item_byte_size);
632 break;
633 }
634 }
635
636 if (!buffer.GetString().empty())
637 {
638 Error error;
639 if (process->WriteMemory (addr, buffer.GetString().data(), buffer.GetString().size(), error) == buffer.GetString().size())
640 return true;
641 else
642 {
643 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
644 result.SetStatus(eReturnStatusFailed);
645 return false;
646 }
647 }
648 return true;
649 }
650
651protected:
652 CommandOptions m_options;
653};
654
655lldb::OptionDefinition
656CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
657{
Jim Ingham34e9a982010-06-15 18:47:14 +0000658 { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "<format>", "The format value types that will be decoded and written to memory."},
659 { LLDB_OPT_SET_1, false, "size", 's', required_argument, NULL, 0, "<byte-size>","The size in bytes of the values to write to memory."},
Chris Lattner24943d22010-06-08 16:52:24 +0000660 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
661};
662
663
664//-------------------------------------------------------------------------
665// CommandObjectMemory
666//-------------------------------------------------------------------------
667
Greg Clayton63094e02010-06-23 01:19:29 +0000668CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000669 CommandObjectMultiword ("memory",
670 "A set of commands for operating on a memory.",
671 "memory <subcommand> [<subcommand-options>]")
672{
Greg Clayton63094e02010-06-23 01:19:29 +0000673 LoadSubCommand (interpreter, "read", CommandObjectSP (new CommandObjectMemoryRead ()));
674 LoadSubCommand (interpreter, "write", CommandObjectSP (new CommandObjectMemoryWrite ()));
Chris Lattner24943d22010-06-08 16:52:24 +0000675}
676
677CommandObjectMemory::~CommandObjectMemory ()
678{
679}