blob: 936ce20303f33f40a2fe768308e6a4417f626960 [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
Chris Lattner24943d22010-06-08 16:52:24 +0000465 StreamString buffer (Stream::eBinary,
466 process->GetAddressByteSize(),
467 process->GetByteOrder());
468
Greg Clayton54e7afa2010-07-09 20:39:50 +0000469 size_t item_byte_size = m_options.m_byte_size;
470
471 if (m_options.m_byte_size == 0)
472 {
473 if (m_options.m_format == eFormatPointer)
474 item_byte_size = buffer.GetAddressByteSize();
475 else
476 item_byte_size = 1;
477 }
478
Chris Lattner24943d22010-06-08 16:52:24 +0000479 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
480
481 if (addr == LLDB_INVALID_ADDRESS)
482 {
483 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
484 result.SetStatus(eReturnStatusFailed);
485 return false;
486 }
487 command.Shift(); // shift off the address argument
488 uint64_t uval64;
489 int64_t sval64;
490 bool success = false;
491 const uint32_t num_value_args = command.GetArgumentCount();
492 uint32_t i;
493 for (i=0; i<num_value_args; ++i)
494 {
495 const char *value_str = command.GetArgumentAtIndex(i);
496
497 switch (m_options.m_format)
498 {
499 case eFormatFloat: // TODO: add support for floats soon
500 case eFormatCharPrintable:
501 case eFormatBytesWithASCII:
502 case eFormatComplex:
503 case eFormatEnum:
504 case eFormatUnicode16:
505 case eFormatUnicode32:
506 case eFormatVectorOfChar:
507 case eFormatVectorOfSInt8:
508 case eFormatVectorOfUInt8:
509 case eFormatVectorOfSInt16:
510 case eFormatVectorOfUInt16:
511 case eFormatVectorOfSInt32:
512 case eFormatVectorOfUInt32:
513 case eFormatVectorOfSInt64:
514 case eFormatVectorOfUInt64:
515 case eFormatVectorOfFloat32:
516 case eFormatVectorOfFloat64:
517 case eFormatVectorOfUInt128:
518 result.AppendError("unsupported format for writing memory");
519 result.SetStatus(eReturnStatusFailed);
520 return false;
521
522 case eFormatDefault:
523 case eFormatBytes:
524 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +0000525 case eFormatPointer:
526
Chris Lattner24943d22010-06-08 16:52:24 +0000527 // Decode hex bytes
528 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
529 if (!success)
530 {
531 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
532 result.SetStatus(eReturnStatusFailed);
533 return false;
534 }
535 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
536 {
537 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
538 result.SetStatus(eReturnStatusFailed);
539 return false;
540 }
541 buffer.PutMaxHex64 (uval64, item_byte_size);
542 break;
543
544 case eFormatBoolean:
545 uval64 = Args::StringToBoolean(value_str, false, &success);
546 if (!success)
547 {
548 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
549 result.SetStatus(eReturnStatusFailed);
550 return false;
551 }
552 buffer.PutMaxHex64 (uval64, item_byte_size);
553 break;
554
555 case eFormatBinary:
556 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
557 if (!success)
558 {
559 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
560 result.SetStatus(eReturnStatusFailed);
561 return false;
562 }
563 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
564 {
565 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
566 result.SetStatus(eReturnStatusFailed);
567 return false;
568 }
569 buffer.PutMaxHex64 (uval64, item_byte_size);
570 break;
571
572 case eFormatChar:
573 case eFormatCString:
574 if (value_str[0])
575 {
576 size_t len = strlen (value_str);
577 // Include the NULL for C strings...
578 if (m_options.m_format == eFormatCString)
579 ++len;
580 Error error;
581 if (process->WriteMemory (addr, value_str, len, error) == len)
582 {
583 addr += len;
584 }
585 else
586 {
587 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
588 result.SetStatus(eReturnStatusFailed);
589 return false;
590 }
591 }
592 break;
593
594 case eFormatDecimal:
595 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
596 if (!success)
597 {
598 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
599 result.SetStatus(eReturnStatusFailed);
600 return false;
601 }
602 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
603 {
604 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608 buffer.PutMaxHex64 (sval64, item_byte_size);
609 break;
610
611 case eFormatUnsigned:
612 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
613 if (!success)
614 {
615 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
616 result.SetStatus(eReturnStatusFailed);
617 return false;
618 }
619 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
620 {
621 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
622 result.SetStatus(eReturnStatusFailed);
623 return false;
624 }
625 buffer.PutMaxHex64 (uval64, item_byte_size);
626 break;
627
628 case eFormatOctal:
629 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
630 if (!success)
631 {
632 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
633 result.SetStatus(eReturnStatusFailed);
634 return false;
635 }
636 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
637 {
638 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
639 result.SetStatus(eReturnStatusFailed);
640 return false;
641 }
642 buffer.PutMaxHex64 (uval64, item_byte_size);
643 break;
644 }
645 }
646
647 if (!buffer.GetString().empty())
648 {
649 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +0000650 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +0000651 return true;
652 else
653 {
654 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
655 result.SetStatus(eReturnStatusFailed);
656 return false;
657 }
658 }
659 return true;
660 }
661
662protected:
663 CommandOptions m_options;
664};
665
666lldb::OptionDefinition
667CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
668{
Jim Ingham34e9a982010-06-15 18:47:14 +0000669 { LLDB_OPT_SET_1, false, "format", 'f', required_argument, NULL, 0, "<format>", "The format value types that will be decoded and written to memory."},
670 { 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 +0000671 { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
672};
673
674
675//-------------------------------------------------------------------------
676// CommandObjectMemory
677//-------------------------------------------------------------------------
678
Greg Clayton63094e02010-06-23 01:19:29 +0000679CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Chris Lattner24943d22010-06-08 16:52:24 +0000680 CommandObjectMultiword ("memory",
681 "A set of commands for operating on a memory.",
682 "memory <subcommand> [<subcommand-options>]")
683{
Greg Clayton63094e02010-06-23 01:19:29 +0000684 LoadSubCommand (interpreter, "read", CommandObjectSP (new CommandObjectMemoryRead ()));
685 LoadSubCommand (interpreter, "write", CommandObjectSP (new CommandObjectMemoryWrite ()));
Chris Lattner24943d22010-06-08 16:52:24 +0000686}
687
688CommandObjectMemory::~CommandObjectMemory ()
689{
690}