1 //===-- 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
16 #include "lldb/Core/DataBufferHeap.h"
17 #include "lldb/Core/DataExtractor.h"
18 #include "lldb/Core/Debugger.h"
19 #include "lldb/Core/StreamString.h"
20 #include "lldb/Interpreter/Args.h"
21 #include "lldb/Interpreter/CommandReturnObject.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/Options.h"
24 #include "lldb/Target/Process.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //----------------------------------------------------------------------
30 // Read memory from the inferior process
31 //----------------------------------------------------------------------
32 class CommandObjectMemoryRead : public CommandObject
33 {
34 public:
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
199     Execute (CommandInterpreter &interpreter,
200              Args& command,
201              CommandReturnObject &result)
202     {
203         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
204         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 
313 protected:
314     CommandOptions m_options;
315 };
316 
317 lldb::OptionDefinition
318 CommandObjectMemoryRead::CommandOptions::g_option_table[] =
319 {
320     { 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."},
324     { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
325 };
326 
327 
328 //----------------------------------------------------------------------
329 // Write memory to the inferior process
330 //----------------------------------------------------------------------
331 class CommandObjectMemoryWrite : public CommandObject
332 {
333 public:
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
444     Execute (CommandInterpreter &interpreter,
445              Args& command,
446              CommandReturnObject &result)
447     {
448         Process *process = interpreter.GetDebugger().GetExecutionContext().process;
449         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 
651 protected:
652     CommandOptions m_options;
653 };
654 
655 lldb::OptionDefinition
656 CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
657 {
658     { 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."},
660     { 0, false, NULL, 0, 0, NULL, 0, NULL, NULL }
661 };
662 
663 
664 //-------------------------------------------------------------------------
665 // CommandObjectMemory
666 //-------------------------------------------------------------------------
667 
668 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
669     CommandObjectMultiword ("memory",
670                             "A set of commands for operating on a memory.",
671                             "memory <subcommand> [<subcommand-options>]")
672 {
673     LoadSubCommand (interpreter, "read",  CommandObjectSP (new CommandObjectMemoryRead ()));
674     LoadSubCommand (interpreter, "write", CommandObjectSP (new CommandObjectMemoryWrite ()));
675 }
676 
677 CommandObjectMemory::~CommandObjectMemory ()
678 {
679 }
680