blob: f63848c0a65d5da9e92ea04055c733c3a4efb850 [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
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,
Chris Lattner24943d22010-06-08 16:52:24 +0000201 eFlagProcessMustBeLaunched)
202 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000203 CommandArgumentEntry arg1;
204 CommandArgumentEntry arg2;
205 CommandArgumentData start_addr_arg;
206 CommandArgumentData end_addr_arg;
207
208 // Define the first (and only) variant of this arg.
209 start_addr_arg.arg_type = eArgTypeStartAddress;
210 start_addr_arg.arg_repetition = eArgRepeatPlain;
211
212 // There is only one variant this argument could be; put it into the argument entry.
213 arg1.push_back (start_addr_arg);
214
215 // Define the first (and only) variant of this arg.
216 end_addr_arg.arg_type = eArgTypeEndAddress;
217 end_addr_arg.arg_repetition = eArgRepeatOptional;
218
219 // There is only one variant this argument could be; put it into the argument entry.
220 arg2.push_back (end_addr_arg);
221
222 // Push the data for the first argument into the m_arguments vector.
223 m_arguments.push_back (arg1);
224 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000225 }
226
227 virtual
228 ~CommandObjectMemoryRead ()
229 {
230 }
231
232 Options *
233 GetOptions ()
234 {
235 return &m_options;
236 }
237
238 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000239 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000240 CommandReturnObject &result)
241 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000242 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000243 if (process == NULL)
244 {
245 result.AppendError("need a process to read memory");
246 result.SetStatus(eReturnStatusFailed);
247 return false;
248 }
249 const size_t argc = command.GetArgumentCount();
250
251 if (argc == 0 || argc > 2)
252 {
253 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
254 result.SetStatus(eReturnStatusFailed);
255 return false;
256 }
257
258 size_t item_byte_size = m_options.m_byte_size;
259 if (item_byte_size == 0)
260 {
261 if (m_options.m_format == eFormatPointer)
Greg Clayton395fc332011-02-15 21:59:32 +0000262 item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
Chris Lattner24943d22010-06-08 16:52:24 +0000263 else
264 item_byte_size = 1;
265 }
266
267 size_t item_count = m_options.m_count;
268
269 size_t num_per_line = m_options.m_num_per_line;
270 if (num_per_line == 0)
271 {
272 num_per_line = (16/item_byte_size);
273 if (num_per_line == 0)
274 num_per_line = 1;
275 }
276
277 size_t total_byte_size = m_options.m_count * item_byte_size;
278 if (total_byte_size == 0)
279 total_byte_size = 32;
280
281 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
282
283 if (addr == LLDB_INVALID_ADDRESS)
284 {
285 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
286 result.SetStatus(eReturnStatusFailed);
287 return false;
288 }
289
290 if (argc == 2)
291 {
292 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
293 if (end_addr == LLDB_INVALID_ADDRESS)
294 {
295 result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
296 result.SetStatus(eReturnStatusFailed);
297 return false;
298 }
299 else if (end_addr <= addr)
300 {
301 result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
302 result.SetStatus(eReturnStatusFailed);
303 return false;
304 }
305 else if (item_count != 0)
306 {
307 result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
308 result.SetStatus(eReturnStatusFailed);
309 return false;
310 }
311
312 total_byte_size = end_addr - addr;
313 item_count = total_byte_size / item_byte_size;
314 }
315 else
316 {
317 if (item_count == 0)
318 item_count = 32;
319 }
320
321 DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
322 Error error;
323 size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
324 if (bytes_read == 0)
325 {
326 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
327 result.AppendError(error.AsCString());
328 result.SetStatus(eReturnStatusFailed);
329 return false;
330 }
331
332 if (bytes_read < total_byte_size)
333 result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
334
335 result.SetStatus(eReturnStatusSuccessFinishResult);
Greg Clayton395fc332011-02-15 21:59:32 +0000336 DataExtractor data (data_sp,
337 process->GetTarget().GetArchitecture().GetByteOrder(),
338 process->GetTarget().GetArchitecture().GetAddressByteSize());
Chris Lattner24943d22010-06-08 16:52:24 +0000339
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000340 StreamFile outfile_stream;
341 Stream *output_stream = NULL;
342
343 if (m_options.m_outfile_filespec)
344 {
345 char path[PATH_MAX];
346 m_options.m_outfile_filespec.GetPath (path, sizeof(path));
347 char mode[16] = { 'w', '\0' };
348 if (m_options.m_append_to_outfile)
349 mode[0] = 'a';
350
Greg Clayton58928562011-02-09 01:08:52 +0000351 if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000352 {
353 if (m_options.m_output_as_binary)
354 {
355 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
356 if (bytes_written > 0)
357 {
358 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
359 bytes_written,
360 m_options.m_append_to_outfile ? "appended" : "written",
361 path);
362 return true;
363 }
364 else
365 {
366 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
367 result.SetStatus(eReturnStatusFailed);
368 return false;
369 }
370 }
371 else
372 {
373 // We are going to write ASCII to the file just point the
374 // output_stream to our outfile_stream...
375 output_stream = &outfile_stream;
376 }
377 }
378 else
379 {
380 result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
381 result.SetStatus(eReturnStatusFailed);
382 return false;
383 }
384 }
385 else
386 {
387 output_stream = &result.GetOutputStream();
388 }
389
390 assert (output_stream);
391 data.Dump (output_stream,
392 0,
393 m_options.m_format,
394 item_byte_size,
395 item_count,
396 num_per_line,
397 addr,
398 0,
399 0);
400 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000401 return true;
402 }
403
404protected:
405 CommandOptions m_options;
406};
407
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000408#define SET1 LLDB_OPT_SET_1
409#define SET2 LLDB_OPT_SET_2
410
Greg Claytonb3448432011-03-24 21:19:54 +0000411OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000412CommandObjectMemoryRead::CommandOptions::g_option_table[] =
413{
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000414{ 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)."},
415{ SET1 , false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes to use when displaying with the selected format."},
416{ SET1 , false, "num-per-line", 'l', required_argument, NULL, 0, eArgTypeNumberPerLine,"The number of items per line to display."},
417{ SET1 , false, "count", 'c', required_argument, NULL, 0, eArgTypeCount, "The number of total items to display."},
418{ SET1 | SET2, false, "outfile", 'o', required_argument, NULL, 0, eArgTypeFilename, "Dump memory read results into a file."},
419{ SET1 | SET2, false, "append", 'a', no_argument, NULL, 0, eArgTypeNone, "Append memory read results to 'outfile'."},
420{ 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."},
421{ 0, false, NULL, 0, 0, NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000422};
423
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000424#undef SET1
425#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +0000426
427//----------------------------------------------------------------------
428// Write memory to the inferior process
429//----------------------------------------------------------------------
430class CommandObjectMemoryWrite : public CommandObject
431{
432public:
433
434 class CommandOptions : public Options
435 {
436 public:
437 CommandOptions () :
438 Options()
439 {
440 ResetOptionValues();
441 }
442
443 virtual
444 ~CommandOptions ()
445 {
446 }
447
448 virtual Error
449 SetOptionValue (int option_idx, const char *option_arg)
450 {
451 Error error;
452 char short_option = (char) m_getopt_table[option_idx].val;
453 switch (short_option)
454 {
455 case 'f':
456 error = Args::StringToFormat (option_arg, m_format);
457 break;
458
459 case 's':
460 m_byte_size = Args::StringToUInt32 (option_arg, 0);
461 if (m_byte_size == 0)
462 error.SetErrorStringWithFormat("Invalid value for --size option '%s'. Must be positive integer value.\n", option_arg);
463 break;
464
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000465 case 'i':
Greg Clayton537a7a82010-10-20 20:54:39 +0000466 m_infile.SetFile (option_arg, true);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000467 if (!m_infile.Exists())
468 {
469 m_infile.Clear();
470 error.SetErrorStringWithFormat("Input file does not exist: '%s'\n", option_arg);
471 }
472 break;
473
474 case 'o':
475 {
476 bool success;
477 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
478 if (!success)
479 {
480 error.SetErrorStringWithFormat("Invalid offset string '%s'\n", option_arg);
481 }
482 }
483 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000484
485 default:
486 error.SetErrorStringWithFormat("Unrecognized short option '%c'\n", short_option);
487 break;
488 }
489 return error;
490 }
491
492 void
493 ResetOptionValues ()
494 {
Chris Lattner24943d22010-06-08 16:52:24 +0000495 m_format = eFormatBytes;
496 m_byte_size = 1;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000497 m_infile.Clear();
498 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000499 }
500
Greg Claytonb3448432011-03-24 21:19:54 +0000501 const OptionDefinition*
Chris Lattner24943d22010-06-08 16:52:24 +0000502 GetDefinitions ()
503 {
504 return g_option_table;
505 }
506
507 // Options table: Required for subclasses of Options.
508
Greg Claytonb3448432011-03-24 21:19:54 +0000509 static OptionDefinition g_option_table[];
Chris Lattner24943d22010-06-08 16:52:24 +0000510
511 // Instance variables to hold the values for command options.
512 lldb::Format m_format;
513 uint32_t m_byte_size;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000514 FileSpec m_infile;
515 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000516 };
517
Greg Clayton238c0a12010-09-18 01:14:36 +0000518 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
519 CommandObject (interpreter,
520 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000521 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000522 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
523 NULL,
Chris Lattner24943d22010-06-08 16:52:24 +0000524 eFlagProcessMustBeLaunched)
525 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000526 CommandArgumentEntry arg1;
527 CommandArgumentEntry arg2;
528 CommandArgumentData addr_arg;
529 CommandArgumentData value_arg;
530
531 // Define the first (and only) variant of this arg.
532 addr_arg.arg_type = eArgTypeAddress;
533 addr_arg.arg_repetition = eArgRepeatPlain;
534
535 // There is only one variant this argument could be; put it into the argument entry.
536 arg1.push_back (addr_arg);
537
538 // Define the first (and only) variant of this arg.
539 value_arg.arg_type = eArgTypeValue;
540 value_arg.arg_repetition = eArgRepeatPlus;
541
542 // There is only one variant this argument could be; put it into the argument entry.
543 arg2.push_back (value_arg);
544
545 // Push the data for the first argument into the m_arguments vector.
546 m_arguments.push_back (arg1);
547 m_arguments.push_back (arg2);
Chris Lattner24943d22010-06-08 16:52:24 +0000548 }
549
550 virtual
551 ~CommandObjectMemoryWrite ()
552 {
553 }
554
555 Options *
556 GetOptions ()
557 {
558 return &m_options;
559 }
560
561 bool
562 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
563 {
564 if (total_byte_size > 8)
565 return false;
566
567 if (total_byte_size == 8)
568 return true;
569
570 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
571 return uval64 <= max;
572 }
573
574 bool
575 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
576 {
577 if (total_byte_size > 8)
578 return false;
579
580 if (total_byte_size == 8)
581 return true;
582
583 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
584 const int64_t min = ~(max);
585 return min <= sval64 && sval64 <= max;
586 }
587
588 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000589 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000590 CommandReturnObject &result)
591 {
Greg Clayton238c0a12010-09-18 01:14:36 +0000592 Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
Chris Lattner24943d22010-06-08 16:52:24 +0000593 if (process == NULL)
594 {
595 result.AppendError("need a process to read memory");
596 result.SetStatus(eReturnStatusFailed);
597 return false;
598 }
599
600 const size_t argc = command.GetArgumentCount();
601
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000602 if (m_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000603 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000604 if (argc < 1)
605 {
606 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
607 result.SetStatus(eReturnStatusFailed);
608 return false;
609 }
610 }
611 else if (argc < 2)
612 {
613 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 +0000614 result.SetStatus(eReturnStatusFailed);
615 return false;
616 }
617
Chris Lattner24943d22010-06-08 16:52:24 +0000618 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000619 process->GetTarget().GetArchitecture().GetAddressByteSize(),
620 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000621
Greg Clayton54e7afa2010-07-09 20:39:50 +0000622 size_t item_byte_size = m_options.m_byte_size;
Greg Clayton54e7afa2010-07-09 20:39:50 +0000623
Chris Lattner24943d22010-06-08 16:52:24 +0000624 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
625
626 if (addr == LLDB_INVALID_ADDRESS)
627 {
628 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
629 result.SetStatus(eReturnStatusFailed);
630 return false;
631 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000632
633 if (m_options.m_infile)
634 {
635 size_t length = SIZE_MAX;
636 if (m_options.m_byte_size > 0)
637 length = m_options.m_byte_size;
638 lldb::DataBufferSP data_sp (m_options.m_infile.ReadFileContents (m_options.m_infile_offset, length));
639 if (data_sp)
640 {
641 length = data_sp->GetByteSize();
642 if (length > 0)
643 {
644 Error error;
645 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
646
647 if (bytes_written == length)
648 {
649 // All bytes written
650 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
651 result.SetStatus(eReturnStatusSuccessFinishResult);
652 }
653 else if (bytes_written > 0)
654 {
655 // Some byte written
656 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
657 result.SetStatus(eReturnStatusSuccessFinishResult);
658 }
659 else
660 {
661 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
662 result.SetStatus(eReturnStatusFailed);
663 }
664 }
665 }
666 else
667 {
668 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
669 result.SetStatus(eReturnStatusFailed);
670 }
671 return result.Succeeded();
672 }
673 else if (m_options.m_byte_size == 0)
674 {
675 if (m_options.m_format == eFormatPointer)
676 item_byte_size = buffer.GetAddressByteSize();
677 else
678 item_byte_size = 1;
679 }
680
Chris Lattner24943d22010-06-08 16:52:24 +0000681 command.Shift(); // shift off the address argument
682 uint64_t uval64;
683 int64_t sval64;
684 bool success = false;
685 const uint32_t num_value_args = command.GetArgumentCount();
686 uint32_t i;
687 for (i=0; i<num_value_args; ++i)
688 {
689 const char *value_str = command.GetArgumentAtIndex(i);
690
691 switch (m_options.m_format)
692 {
693 case eFormatFloat: // TODO: add support for floats soon
694 case eFormatCharPrintable:
695 case eFormatBytesWithASCII:
696 case eFormatComplex:
697 case eFormatEnum:
698 case eFormatUnicode16:
699 case eFormatUnicode32:
700 case eFormatVectorOfChar:
701 case eFormatVectorOfSInt8:
702 case eFormatVectorOfUInt8:
703 case eFormatVectorOfSInt16:
704 case eFormatVectorOfUInt16:
705 case eFormatVectorOfSInt32:
706 case eFormatVectorOfUInt32:
707 case eFormatVectorOfSInt64:
708 case eFormatVectorOfUInt64:
709 case eFormatVectorOfFloat32:
710 case eFormatVectorOfFloat64:
711 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +0000712 case eFormatOSType:
713 case eFormatComplexInteger:
Chris Lattner24943d22010-06-08 16:52:24 +0000714 result.AppendError("unsupported format for writing memory");
715 result.SetStatus(eReturnStatusFailed);
716 return false;
717
718 case eFormatDefault:
719 case eFormatBytes:
720 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +0000721 case eFormatPointer:
722
Chris Lattner24943d22010-06-08 16:52:24 +0000723 // Decode hex bytes
724 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
725 if (!success)
726 {
727 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
728 result.SetStatus(eReturnStatusFailed);
729 return false;
730 }
731 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
732 {
733 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
734 result.SetStatus(eReturnStatusFailed);
735 return false;
736 }
737 buffer.PutMaxHex64 (uval64, item_byte_size);
738 break;
739
740 case eFormatBoolean:
741 uval64 = Args::StringToBoolean(value_str, false, &success);
742 if (!success)
743 {
744 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
745 result.SetStatus(eReturnStatusFailed);
746 return false;
747 }
748 buffer.PutMaxHex64 (uval64, item_byte_size);
749 break;
750
751 case eFormatBinary:
752 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
753 if (!success)
754 {
755 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
756 result.SetStatus(eReturnStatusFailed);
757 return false;
758 }
759 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
760 {
761 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
762 result.SetStatus(eReturnStatusFailed);
763 return false;
764 }
765 buffer.PutMaxHex64 (uval64, item_byte_size);
766 break;
767
768 case eFormatChar:
769 case eFormatCString:
770 if (value_str[0])
771 {
772 size_t len = strlen (value_str);
773 // Include the NULL for C strings...
774 if (m_options.m_format == eFormatCString)
775 ++len;
776 Error error;
777 if (process->WriteMemory (addr, value_str, len, error) == len)
778 {
779 addr += len;
780 }
781 else
782 {
783 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
784 result.SetStatus(eReturnStatusFailed);
785 return false;
786 }
787 }
788 break;
789
790 case eFormatDecimal:
791 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
792 if (!success)
793 {
794 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
795 result.SetStatus(eReturnStatusFailed);
796 return false;
797 }
798 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
799 {
800 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %u byte signed integer value.\n", sval64, item_byte_size);
801 result.SetStatus(eReturnStatusFailed);
802 return false;
803 }
804 buffer.PutMaxHex64 (sval64, item_byte_size);
805 break;
806
807 case eFormatUnsigned:
808 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
809 if (!success)
810 {
811 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
812 result.SetStatus(eReturnStatusFailed);
813 return false;
814 }
815 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
816 {
817 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
818 result.SetStatus(eReturnStatusFailed);
819 return false;
820 }
821 buffer.PutMaxHex64 (uval64, item_byte_size);
822 break;
823
824 case eFormatOctal:
825 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
826 if (!success)
827 {
828 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
829 result.SetStatus(eReturnStatusFailed);
830 return false;
831 }
832 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
833 {
834 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %u byte unsigned integer value.\n", uval64, item_byte_size);
835 result.SetStatus(eReturnStatusFailed);
836 return false;
837 }
838 buffer.PutMaxHex64 (uval64, item_byte_size);
839 break;
840 }
841 }
842
843 if (!buffer.GetString().empty())
844 {
845 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +0000846 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +0000847 return true;
848 else
849 {
850 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
851 result.SetStatus(eReturnStatusFailed);
852 return false;
853 }
854 }
855 return true;
856 }
857
858protected:
859 CommandOptions m_options;
860};
861
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000862#define SET1 LLDB_OPT_SET_1
863#define SET2 LLDB_OPT_SET_2
864
Greg Claytonb3448432011-03-24 21:19:54 +0000865OptionDefinition
Chris Lattner24943d22010-06-08 16:52:24 +0000866CommandObjectMemoryWrite::CommandOptions::g_option_table[] =
867{
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000868{ SET1 , false, "format", 'f', required_argument, NULL, 0, eArgTypeFormat, "The format value types that will be decoded and written to memory."},
869{ SET1 | SET2, false, "size", 's', required_argument, NULL, 0, eArgTypeByteSize, "The size in bytes of the values to write to memory."},
870{ SET2, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
871{ SET2, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
872{ 0 , false, NULL , 0 , 0 , NULL, 0, eArgTypeNone, NULL }
Chris Lattner24943d22010-06-08 16:52:24 +0000873};
874
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000875#undef SET1
876#undef SET2
Chris Lattner24943d22010-06-08 16:52:24 +0000877
878//-------------------------------------------------------------------------
879// CommandObjectMemory
880//-------------------------------------------------------------------------
881
Greg Clayton63094e02010-06-23 01:19:29 +0000882CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +0000883 CommandObjectMultiword (interpreter,
884 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +0000885 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +0000886 "memory <subcommand> [<subcommand-options>]")
887{
Greg Clayton238c0a12010-09-18 01:14:36 +0000888 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
889 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +0000890}
891
892CommandObjectMemory::~CommandObjectMemory ()
893{
894}