blob: c731c61836cb603f8a63efe830d0ab57b08ed7ac [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:
Greg Claytonf15996e2011-04-07 22:46:35 +000039 CommandOptions (CommandInterpreter &interpreter) :
40 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +000041 {
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
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000145 case 'o':
Greg Clayton537a7a82010-10-20 20:54:39 +0000146 m_outfile_filespec.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000147 break;
148
149 case 'b':
150 m_output_as_binary = true;
151 break;
152
153 case 'a':
154 m_append_to_outfile = true;
155 break;
156
Chris Lattner24943d22010-06-08 16:52:24 +0000157 default:
158 error.SetErrorStringWithFormat("Unrecognized short option '%c'.\n", short_option);
159 break;
160 }
161 return error;
162 }
163
164 void
165 ResetOptionValues ()
166 {
Chris Lattner24943d22010-06-08 16:52:24 +0000167 m_format = eFormatBytesWithASCII;
168 m_byte_size = 0;
169 m_count = 0;
170 m_num_per_line = 0;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000171 m_outfile_filespec.Clear();
172 m_append_to_outfile = false;
173 m_output_as_binary = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000174 }
175
Greg Claytonb3448432011-03-24 21:19:54 +0000176 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000177 GetDefinitions ()
178 {
179 return g_option_table;
180 }
181
182 // Options table: Required for subclasses of Options.
183
Greg Claytonb3448432011-03-24 21:19:54 +0000184 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000185
186 // Instance variables to hold the values for command options.
187 lldb::Format m_format;
188 uint32_t m_byte_size;
189 uint32_t m_count;
190 uint32_t m_num_per_line;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000191 FileSpec m_outfile_filespec;
192 bool m_append_to_outfile;
193 bool m_output_as_binary;
Chris Lattner24943d22010-06-08 16:52:24 +0000194 };
195
Greg Clayton238c0a12010-09-18 01:14:36 +0000196 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
197 CommandObject (interpreter,
198 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000199 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000200 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000201 eFlagProcessMustBeLaunched),
202 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000203 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000204 CommandArgumentEntry arg1;
205 CommandArgumentEntry arg2;
206 CommandArgumentData start_addr_arg;
207 CommandArgumentData end_addr_arg;
208
209 // Define the first (and only) variant of this arg.
210 start_addr_arg.arg_type = eArgTypeStartAddress;
211 start_addr_arg.arg_repetition = eArgRepeatPlain;
212
213 // There is only one variant this argument could be; put it into the argument entry.
214 arg1.push_back (start_addr_arg);
215
216 // Define the first (and only) variant of this arg.
217 end_addr_arg.arg_type = eArgTypeEndAddress;
218 end_addr_arg.arg_repetition = eArgRepeatOptional;
219
220 // There is only one variant this argument could be; put it into the argument entry.
221 arg2.push_back (end_addr_arg);
222
223 // Push the data for the first argument into the m_arguments vector.
224 m_arguments.push_back (arg1);
225 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000226 }
227
228 virtual
229 ~CommandObjectMemoryRead ()
230 {
231 }
232
233 Options *
234 GetOptions ()
235 {
236 return &m_options;
237 }
238
239 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000240 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000241 CommandReturnObject &result)
242 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000243 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000244 if (process == NULL)
245 {
246 result.AppendError("need a process to read memory");
247 result.SetStatus(eReturnStatusFailed);
248 return false;
249 }
250 const size_t argc = command.GetArgumentCount();
251
252 if (argc == 0 || argc > 2)
253 {
254 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
255 result.SetStatus(eReturnStatusFailed);
256 return false;
257 }
258
259 size_t item_byte_size = m_options.m_byte_size;
260 if (item_byte_size == 0)
261 {
262 if (m_options.m_format == eFormatPointer)
Greg Clayton395fc332011-02-15 21:59:32 +0000263 item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000264 else
265 item_byte_size = 1;
266 }
267
268 size_t item_count = m_options.m_count;
269
270 size_t num_per_line = m_options.m_num_per_line;
271 if (num_per_line == 0)
272 {
273 num_per_line = (16/item_byte_size);
274 if (num_per_line == 0)
275 num_per_line = 1;
276 }
277
278 size_t total_byte_size = m_options.m_count * item_byte_size;
279 if (total_byte_size == 0)
280 total_byte_size = 32;
281
282 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
283
284 if (addr == LLDB_INVALID_ADDRESS)
285 {
286 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
287 result.SetStatus(eReturnStatusFailed);
288 return false;
289 }
290
291 if (argc == 2)
292 {
293 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
294 if (end_addr == LLDB_INVALID_ADDRESS)
295 {
296 result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
297 result.SetStatus(eReturnStatusFailed);
298 return false;
299 }
300 else if (end_addr <= addr)
301 {
302 result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
303 result.SetStatus(eReturnStatusFailed);
304 return false;
305 }
306 else if (item_count != 0)
307 {
308 result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
309 result.SetStatus(eReturnStatusFailed);
310 return false;
311 }
312
313 total_byte_size = end_addr - addr;
314 item_count = total_byte_size / item_byte_size;
315 }
316 else
317 {
318 if (item_count == 0)
319 item_count = 32;
320 }
321
322 DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
323 Error error;
324 size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
325 if (bytes_read == 0)
326 {
327 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
328 result.AppendError(error.AsCString());
329 result.SetStatus(eReturnStatusFailed);
330 return false;
331 }
332
333 if (bytes_read < total_byte_size)
334 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
335
336 result.SetStatus(eReturnStatusSuccessFinishResult);
Greg Clayton395fc332011-02-15 21:59:32 +0000337 DataExtractor data (data_sp,
338 process->GetTarget().GetArchitecture().GetByteOrder(),
339 process->GetTarget().GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +0000340
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000341 StreamFile outfile_stream;
342 Stream *output_stream = NULL;
343
344 if (m_options.m_outfile_filespec)
345 {
346 char path[PATH_MAX];
347 m_options.m_outfile_filespec.GetPath (path, sizeof(path));
348 char mode[16] = { 'w', '\0' };
349 if (m_options.m_append_to_outfile)
350 mode[0] = 'a';
351
Greg Clayton58928562011-02-09 01:08:52 +0000352 if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000353 {
354 if (m_options.m_output_as_binary)
355 {
356 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
357 if (bytes_written > 0)
358 {
359 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
360 bytes_written,
361 m_options.m_append_to_outfile ? "appended" : "written",
362 path);
363 return true;
364 }
365 else
366 {
367 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
368 result.SetStatus(eReturnStatusFailed);
369 return false;
370 }
371 }
372 else
373 {
374 // We are going to write ASCII to the file just point the
375 // output_stream to our outfile_stream...
376 output_stream = &outfile_stream;
377 }
378 }
379 else
380 {
381 result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
382 result.SetStatus(eReturnStatusFailed);
383 return false;
384 }
385 }
386 else
387 {
388 output_stream = &result.GetOutputStream();
389 }
390
391 assert (output_stream);
392 data.Dump (output_stream,
393 0,
394 m_options.m_format,
395 item_byte_size,
396 item_count,
397 num_per_line,
398 addr,
399 0,
400 0);
401 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000402 return true;
403 }
404
405protected:
406 CommandOptions m_options;
407};
408
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000409#define SET1 LLDB_OPT_SET_1
410#define SET2 LLDB_OPT_SET_2
411
Greg Claytonb3448432011-03-24 21:19:54 +0000412OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000413CommandObjectMemoryRead::CommandOptions::g_option_table[] =
414{
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000415{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format that will be used to display the memory. Defaults to bytes with ASCII (--format=Y)."},
416{ SET1 , false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."},
417{ SET1 , false, "num-per-line", 'l', required_argument, NULL, 0, eArgTypeNumberPerLine,"The number of items per line to display."},
418{ SET1 , false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."},
419{ SET1 | SET2, false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename, "Dump memory read results into a file."},
420{ SET1 | SET2, false, "append", 'a', no_argument, NULL, 0, eArgTypeNone, "Append memory read results to 'outfile'."},
421{ SET2, false, "binary", 'b', no_argument, NULL, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
422{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000423};
424
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000425#undef SET1
426#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +0000427
428//----------------------------------------------------------------------
429// Write memory to the inferior process
430//----------------------------------------------------------------------
431class CommandObjectMemoryWrite : public CommandObject
432{
433public:
434
435 class CommandOptions : public Options
436 {
437 public:
Greg Claytonf15996e2011-04-07 22:46:35 +0000438 CommandOptions (CommandInterpreter &interpreter) :
439 Options(interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000440 {
441 ResetOptionValues();
442 }
443
444 virtual
445 ~CommandOptions ()
446 {
447 }
448
449 virtual Error
450 SetOptionValue (int option_idx, const char *option_arg)
451 {
452 Error error;
453 char short_option = (char) m_getopt_table[option_idx].val;
454 switch (short_option)
455 {
456 case 'f':
457 error = Args::StringToFormat (option_arg, m_format);
458 break;
459
460 case 's':
461 m_byte_size = Args::StringToUInt32 (option_arg, 0);
462 if (m_byte_size == 0)
463 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
464 break;
465
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000466 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000467 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000468 if (!m_infile.Exists())
469 {
470 m_infile.Clear();
471 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
472 }
473 break;
474
475 case 'o':
476 {
477 bool success;
478 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
479 if (!success)
480 {
481 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
482 }
483 }
484 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000485
486 default:
487 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
488 break;
489 }
490 return error;
491 }
492
493 void
494 ResetOptionValues ()
495 {
Chris Lattner24943d22010-06-08 16:52:24 +0000496 m_format = eFormatBytes;
497 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000498 m_infile.Clear();
499 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000500 }
501
Greg Claytonb3448432011-03-24 21:19:54 +0000502 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000503 GetDefinitions ()
504 {
505 return g_option_table;
506 }
507
508 // Options table: Required for subclasses of Options.
509
Greg Claytonb3448432011-03-24 21:19:54 +0000510 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000511
512 // Instance variables to hold the values for command options.
513 lldb::Format m_format;
514 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000515 FileSpec m_infile;
516 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000517 };
518
Greg Clayton238c0a12010-09-18 01:14:36 +0000519 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
520 CommandObject (interpreter,
521 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000522 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000523 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
524 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000525 eFlagProcessMustBeLaunched),
526 m_options (interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000527 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000528 CommandArgumentEntry arg1;
529 CommandArgumentEntry arg2;
530 CommandArgumentData addr_arg;
531 CommandArgumentData value_arg;
532
533 // Define the first (and only) variant of this arg.
534 addr_arg.arg_type = eArgTypeAddress;
535 addr_arg.arg_repetition = eArgRepeatPlain;
536
537 // There is only one variant this argument could be; put it into the argument entry.
538 arg1.push_back (addr_arg);
539
540 // Define the first (and only) variant of this arg.
541 value_arg.arg_type = eArgTypeValue;
542 value_arg.arg_repetition = eArgRepeatPlus;
543
544 // There is only one variant this argument could be; put it into the argument entry.
545 arg2.push_back (value_arg);
546
547 // Push the data for the first argument into the m_arguments vector.
548 m_arguments.push_back (arg1);
549 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000550 }
551
552 virtual
553 ~CommandObjectMemoryWrite ()
554 {
555 }
556
557 Options *
558 GetOptions ()
559 {
560 return &m_options;
561 }
562
563 bool
564 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
565 {
566 if (total_byte_size > 8)
567 return false;
568
569 if (total_byte_size == 8)
570 return true;
571
572 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
573 return uval64 <= max;
574 }
575
576 bool
577 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
578 {
579 if (total_byte_size > 8)
580 return false;
581
582 if (total_byte_size == 8)
583 return true;
584
585 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
586 const int64_t min = ~(max);
587 return min <= sval64 && sval64 <= max;
588 }
589
590 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000591 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000592 CommandReturnObject &result)
593 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000594 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000595 if (process == NULL)
596 {
597 result.AppendError("need a process to read memory");
598 result.SetStatus(eReturnStatusFailed);
599 return false;
600 }
601
602 const size_t argc = command.GetArgumentCount();
603
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000604 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000605 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000606 if (argc < 1)
607 {
608 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
609 result.SetStatus(eReturnStatusFailed);
610 return false;
611 }
612 }
613 else if (argc < 2)
614 {
615 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000616 result.SetStatus(eReturnStatusFailed);
617 return false;
618 }
619
Chris Lattner24943d22010-06-08 16:52:24 +0000620 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000621 process->GetTarget().GetArchitecture().GetAddressByteSize(),
622 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000623
Greg Clayton54e7afa2010-07-09 20:39:50 +0000624 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000625
Chris Lattner24943d22010-06-08 16:52:24 +0000626 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
627
628 if (addr == LLDB_INVALID_ADDRESS)
629 {
630 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
631 result.SetStatus(eReturnStatusFailed);
632 return false;
633 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000634
635 if (m_options.m_infile)
636 {
637 size_t length = SIZE_MAX;
638 if (m_options.m_byte_size > 0)
639 length = m_options.m_byte_size;
640 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
641 if (data_sp)
642 {
643 length = data_sp->GetByteSize();
644 if (length > 0)
645 {
646 Error error;
647 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
648
649 if (bytes_written == length)
650 {
651 // All bytes written
652 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
653 result.SetStatus(eReturnStatusSuccessFinishResult);
654 }
655 else if (bytes_written > 0)
656 {
657 // Some byte written
658 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
659 result.SetStatus(eReturnStatusSuccessFinishResult);
660 }
661 else
662 {
663 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
664 result.SetStatus(eReturnStatusFailed);
665 }
666 }
667 }
668 else
669 {
670 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
671 result.SetStatus(eReturnStatusFailed);
672 }
673 return result.Succeeded();
674 }
675 else if (m_options.m_byte_size == 0)
676 {
677 if (m_options.m_format == eFormatPointer)
678 item_byte_size = buffer.GetAddressByteSize();
679 else
680 item_byte_size = 1;
681 }
682
Chris Lattner24943d22010-06-08 16:52:24 +0000683 command.Shift(); // shift off the address argument
684 uint64_t uval64;
685 int64_t sval64;
686 bool success = false;
687 const uint32_t num_value_args = command.GetArgumentCount();
688 uint32_t i;
689 for (i=0; i<num_value_args; ++i)
690 {
691 const char *value_str = command.GetArgumentAtIndex(i);
692
693 switch (m_options.m_format)
694 {
695 case eFormatFloat: // TODO: add support for floats soon
696 case eFormatCharPrintable:
697 case eFormatBytesWithASCII:
698 case eFormatComplex:
699 case eFormatEnum:
700 case eFormatUnicode16:
701 case eFormatUnicode32:
702 case eFormatVectorOfChar:
703 case eFormatVectorOfSInt8:
704 case eFormatVectorOfUInt8:
705 case eFormatVectorOfSInt16:
706 case eFormatVectorOfUInt16:
707 case eFormatVectorOfSInt32:
708 case eFormatVectorOfUInt32:
709 case eFormatVectorOfSInt64:
710 case eFormatVectorOfUInt64:
711 case eFormatVectorOfFloat32:
712 case eFormatVectorOfFloat64:
713 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +0000714 case eFormatOSType:
715 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +0000716 result.AppendError("unsupported format for writing memory");
717 result.SetStatus(eReturnStatusFailed);
718 return false;
719
720 case eFormatDefault:
721 case eFormatBytes:
722 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +0000723 case eFormatPointer:
724
Chris Lattner24943d22010-06-08 16:52:24 +0000725 // Decode hex bytes
726 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
727 if (!success)
728 {
729 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
730 result.SetStatus(eReturnStatusFailed);
731 return false;
732 }
733 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
734 {
735 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
736 result.SetStatus(eReturnStatusFailed);
737 return false;
738 }
739 buffer.PutMaxHex64 (uval64, item_byte_size);
740 break;
741
742 case eFormatBoolean:
743 uval64 = Args::StringToBoolean(value_str, false, &success);
744 if (!success)
745 {
746 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
747 result.SetStatus(eReturnStatusFailed);
748 return false;
749 }
750 buffer.PutMaxHex64 (uval64, item_byte_size);
751 break;
752
753 case eFormatBinary:
754 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
755 if (!success)
756 {
757 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
758 result.SetStatus(eReturnStatusFailed);
759 return false;
760 }
761 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
762 {
763 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
764 result.SetStatus(eReturnStatusFailed);
765 return false;
766 }
767 buffer.PutMaxHex64 (uval64, item_byte_size);
768 break;
769
770 case eFormatChar:
771 case eFormatCString:
772 if (value_str[0])
773 {
774 size_t len = strlen (value_str);
775 // Include the NULL for C strings...
776 if (m_options.m_format == eFormatCString)
777 ++len;
778 Error error;
779 if (process->WriteMemory (addr, value_str, len, error) == len)
780 {
781 addr += len;
782 }
783 else
784 {
785 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
786 result.SetStatus(eReturnStatusFailed);
787 return false;
788 }
789 }
790 break;
791
792 case eFormatDecimal:
793 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
794 if (!success)
795 {
796 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
797 result.SetStatus(eReturnStatusFailed);
798 return false;
799 }
800 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
801 {
802 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
803 result.SetStatus(eReturnStatusFailed);
804 return false;
805 }
806 buffer.PutMaxHex64 (sval64, item_byte_size);
807 break;
808
809 case eFormatUnsigned:
810 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
811 if (!success)
812 {
813 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
814 result.SetStatus(eReturnStatusFailed);
815 return false;
816 }
817 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
818 {
819 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
820 result.SetStatus(eReturnStatusFailed);
821 return false;
822 }
823 buffer.PutMaxHex64 (uval64, item_byte_size);
824 break;
825
826 case eFormatOctal:
827 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
828 if (!success)
829 {
830 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
831 result.SetStatus(eReturnStatusFailed);
832 return false;
833 }
834 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
835 {
836 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
837 result.SetStatus(eReturnStatusFailed);
838 return false;
839 }
840 buffer.PutMaxHex64 (uval64, item_byte_size);
841 break;
842 }
843 }
844
845 if (!buffer.GetString().empty())
846 {
847 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +0000848 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +0000849 return true;
850 else
851 {
852 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
853 result.SetStatus(eReturnStatusFailed);
854 return false;
855 }
856 }
857 return true;
858 }
859
860protected:
861 CommandOptions m_options;
862};
863
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000864#define SET1 LLDB_OPT_SET_1
865#define SET2 LLDB_OPT_SET_2
866
Greg Claytonb3448432011-03-24 21:19:54 +0000867OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000868CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
869{
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000870{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
871{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
872{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
873{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
874{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000875};
876
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000877#undef SET1
878#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +0000879
880//-------------------------------------------------------------------------
881// CommandObjectMemory
882//-------------------------------------------------------------------------
883
Greg Clayton63094e02010-06-23 01:19:29 +0000884CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000885 CommandObjectMultiword (interpreter,
886 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000887 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +0000888 "memory <subcommand> [<subcommand-options>]")
889{
Greg Clayton238c0a12010-09-18 01:14:36 +0000890 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
891 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +0000892}
893
894CommandObjectMemory::~CommandObjectMemory ()
895{
896}