blob: 6da176dbf873a7bffe1ba8bdb936ec8df7eebf42 [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 Clayton57b3c6b2011-04-27 22:04:39 +000020#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000021#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000023#include "lldb/Interpreter/CommandInterpreter.h"
24#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000025#include "lldb/Interpreter/OptionGroupFormat.h"
26#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000027#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Sean Callanan3e80cd92011-10-12 02:08:07 +000028#include "lldb/Symbol/ClangNamespaceDecl.h"
Chris Lattner24943d22010-06-08 16:52:24 +000029#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000030#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031
32using namespace lldb;
33using namespace lldb_private;
34
Greg Clayton56bbdaf2011-04-28 20:55:26 +000035static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000036g_option_table[] =
37{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
39 { LLDB_OPT_SET_2, 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."},
40 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41};
42
43
44
45class OptionGroupReadMemory : public OptionGroup
46{
47public:
48
49 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000050 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000051 m_output_as_binary (false),
52 m_view_as_type()
53 {
54 }
55
56 virtual
57 ~OptionGroupReadMemory ()
58 {
59 }
60
61
62 virtual uint32_t
63 GetNumDefinitions ()
64 {
65 return sizeof (g_option_table) / sizeof (OptionDefinition);
66 }
67
68 virtual const OptionDefinition*
69 GetDefinitions ()
70 {
71 return g_option_table;
72 }
73
74 virtual Error
75 SetOptionValue (CommandInterpreter &interpreter,
76 uint32_t option_idx,
77 const char *option_arg)
78 {
79 Error error;
80 char short_option = (char) g_option_table[option_idx].short_option;
81
82 switch (short_option)
83 {
84 case 'l':
85 error = m_num_per_line.SetValueFromCString (option_arg);
86 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000087 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000088 break;
Greg Claytona42880a2011-10-25 06:44:01 +000089
Greg Clayton57b3c6b2011-04-27 22:04:39 +000090 case 'b':
91 m_output_as_binary = true;
92 break;
93
94 case 't':
95 error = m_view_as_type.SetValueFromCString (option_arg);
96 break;
97
98 default:
Greg Clayton9c236732011-10-26 00:56:27 +000099 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000100 break;
101 }
102 return error;
103 }
104
105 virtual void
106 OptionParsingStarting (CommandInterpreter &interpreter)
107 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000108 m_num_per_line.Clear();
109 m_output_as_binary = false;
110 m_view_as_type.Clear();
111 }
112
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000113 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000114 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000115 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000116 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000117 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
118 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000119 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000120 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000121 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000122
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000123 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000124 {
125 default:
126 break;
127
128 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000130 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131 if (!num_per_line_option_set)
132 m_num_per_line = 1;
133 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000134 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 break;
136
137 case eFormatCString:
138 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000139
140 case eFormatInstruction:
141 if (count_option_set)
142 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
143 m_num_per_line = 1;
144 break;
145
146 case eFormatAddressInfo:
147 if (!byte_size_option_set)
148 byte_size_value = target->GetArchitecture().GetAddressByteSize();
149 m_num_per_line = 1;
150 if (!count_option_set)
151 format_options.GetCountValue() = 8;
152 break;
153
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000154 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000155 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000156 if (!num_per_line_option_set)
157 m_num_per_line = 4;
158 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000159 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000160 break;
161
162 case eFormatBinary:
163 case eFormatFloat:
164 case eFormatOctal:
165 case eFormatDecimal:
166 case eFormatEnum:
167 case eFormatUnicode16:
168 case eFormatUnicode32:
169 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000170 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000171 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000172 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000173 if (!num_per_line_option_set)
174 m_num_per_line = 1;
175 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000176 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000177 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000178
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000179 case eFormatBytes:
180 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000181 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000182 {
Greg Claytona42880a2011-10-25 06:44:01 +0000183 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000184 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
185 "\tconsider using a different display format or don't specify the byte size",
186 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000187 }
188 else
Greg Claytona42880a2011-10-25 06:44:01 +0000189 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000190 if (!num_per_line_option_set)
191 m_num_per_line = 16;
192 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000193 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000194 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000195 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000196 case eFormatChar:
197 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000198 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000199 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000200 if (!num_per_line_option_set)
201 m_num_per_line = 32;
202 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000203 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000204 break;
205 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000206 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000207 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 1;
210 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000211 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000212 break;
213 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000214 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000215 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000216 if (!num_per_line_option_set)
217 {
Greg Claytona42880a2011-10-25 06:44:01 +0000218 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 {
220 case 1:
221 case 2:
222 m_num_per_line = 8;
223 break;
224 case 4:
225 m_num_per_line = 4;
226 break;
227 case 8:
228 m_num_per_line = 2;
229 break;
230 default:
231 m_num_per_line = 1;
232 break;
233 }
234 }
235 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000236 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000237 break;
238
239 case eFormatVectorOfChar:
240 case eFormatVectorOfSInt8:
241 case eFormatVectorOfUInt8:
242 case eFormatVectorOfSInt16:
243 case eFormatVectorOfUInt16:
244 case eFormatVectorOfSInt32:
245 case eFormatVectorOfUInt32:
246 case eFormatVectorOfSInt64:
247 case eFormatVectorOfUInt64:
248 case eFormatVectorOfFloat32:
249 case eFormatVectorOfFloat64:
250 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000251 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000252 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000253 if (!num_per_line_option_set)
254 m_num_per_line = 1;
255 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000256 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000257 break;
258 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000259 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000260 }
261
Greg Clayton902b5be2011-10-26 04:32:38 +0000262 bool
263 AnyOptionWasSet () const
264 {
265 return m_num_per_line.OptionWasSet() ||
266 m_output_as_binary ||
267 m_view_as_type.OptionWasSet();
268 }
269
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000270 OptionValueUInt64 m_num_per_line;
271 bool m_output_as_binary;
272 OptionValueString m_view_as_type;
273};
274
275
276
Chris Lattner24943d22010-06-08 16:52:24 +0000277//----------------------------------------------------------------------
278// Read memory from the inferior process
279//----------------------------------------------------------------------
280class CommandObjectMemoryRead : public CommandObject
281{
282public:
283
Greg Clayton238c0a12010-09-18 01:14:36 +0000284 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
285 CommandObject (interpreter,
286 "memory read",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000287 "Read from the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000288 NULL,
Jim Ingham8cc3f692011-07-09 00:55:34 +0000289 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000290 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000291 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000292 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000293 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000294 m_varobj_options(),
295 m_next_addr(LLDB_INVALID_ADDRESS),
296 m_prev_byte_size(0),
297 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
298 m_prev_memory_options (),
299 m_prev_outfile_options (),
300 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000302 CommandArgumentEntry arg1;
303 CommandArgumentEntry arg2;
304 CommandArgumentData start_addr_arg;
305 CommandArgumentData end_addr_arg;
306
307 // Define the first (and only) variant of this arg.
308 start_addr_arg.arg_type = eArgTypeStartAddress;
309 start_addr_arg.arg_repetition = eArgRepeatPlain;
310
311 // There is only one variant this argument could be; put it into the argument entry.
312 arg1.push_back (start_addr_arg);
313
314 // Define the first (and only) variant of this arg.
315 end_addr_arg.arg_type = eArgTypeEndAddress;
316 end_addr_arg.arg_repetition = eArgRepeatOptional;
317
318 // There is only one variant this argument could be; put it into the argument entry.
319 arg2.push_back (end_addr_arg);
320
321 // Push the data for the first argument into the m_arguments vector.
322 m_arguments.push_back (arg1);
323 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000324
Greg Claytona42880a2011-10-25 06:44:01 +0000325 // Add the "--format" and "--count" options to group 1 and 3
326 m_option_group.Append (&m_format_options,
327 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000328 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000329 m_option_group.Append (&m_format_options,
330 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000331 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000332 // Add the "--size" option to group 1 and 2
333 m_option_group.Append (&m_format_options,
334 OptionGroupFormat::OPTION_GROUP_SIZE,
335 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000336 m_option_group.Append (&m_memory_options);
337 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000338 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000339 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000340 }
341
342 virtual
343 ~CommandObjectMemoryRead ()
344 {
345 }
346
347 Options *
348 GetOptions ()
349 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000350 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000351 }
352
Greg Clayton902b5be2011-10-26 04:32:38 +0000353 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
354 {
355 return m_cmd_name.c_str();
356 }
357
Chris Lattner24943d22010-06-08 16:52:24 +0000358 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000359 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000360 CommandReturnObject &result)
361 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000362 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000363 Target *target = exe_ctx.GetTargetPtr();
364 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000365 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000366 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000367 result.SetStatus(eReturnStatusFailed);
368 return false;
369 }
370 const size_t argc = command.GetArgumentCount();
371
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000372
Greg Clayton902b5be2011-10-26 04:32:38 +0000373 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000374 {
375 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
376 result.SetStatus(eReturnStatusFailed);
377 return false;
378 }
379
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000380 ClangASTType clang_ast_type;
381 Error error;
382
383 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000384 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
385 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000386 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000387 // We are viewing memory as a type
388 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000389 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000390 TypeList type_list;
391 uint32_t reference_count = 0;
392 uint32_t pointer_count = 0;
393 size_t idx;
394 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
395 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
396 std::string type_str(view_as_type_cstr);
397
398 // Remove all instances of g_keywords that are followed by spaces
399 for (size_t i = 0; i < g_num_keywords; ++i)
400 {
401 const char *keyword = g_keywords[i];
402 int keyword_len = ::strlen (keyword);
403 while ((idx = type_str.find (keyword)) != std::string::npos)
404 {
405 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
406 type_str.erase(idx, keyword_len+1);
407 }
408 }
409 bool done = type_str.empty();
410 //
411 idx = type_str.find_first_not_of (" \t");
412 if (idx > 0 && idx != std::string::npos)
413 type_str.erase (0, idx);
414 while (!done)
415 {
416 // Strip trailing spaces
417 if (type_str.empty())
418 done = true;
419 else
420 {
421 switch (type_str[type_str.size()-1])
422 {
423 case '*':
424 ++pointer_count;
425 // fall through...
426 case ' ':
427 case '\t':
428 type_str.erase(type_str.size()-1);
429 break;
430
431 case '&':
432 if (reference_count == 0)
433 {
434 reference_count = 1;
435 type_str.erase(type_str.size()-1);
436 }
437 else
438 {
439 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
440 result.SetStatus(eReturnStatusFailed);
441 return false;
442 }
443 break;
444
445 default:
446 done = true;
447 break;
448 }
449 }
450 }
451
452 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000453 StackFrame *frame = exe_ctx.GetFramePtr();
454 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000455 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000456 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000457 if (sc.module_sp)
458 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000459 sc.module_sp->FindTypes (sc,
460 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000461 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000462 1,
463 type_list);
464 }
465 }
466 if (type_list.GetSize() == 0)
467 {
Greg Claytondc0a38c2012-03-26 23:03:23 +0000468 target->GetImages().FindTypes2 (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000469 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000470 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000471 1,
472 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000473 }
474
475 if (type_list.GetSize() == 0)
476 {
477 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
478 lookup_type_name.GetCString(),
479 view_as_type_cstr);
480 result.SetStatus(eReturnStatusFailed);
481 return false;
482 }
483
484 TypeSP type_sp (type_list.GetTypeAtIndex(0));
485 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
486
487 while (pointer_count > 0)
488 {
489 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
490 if (pointer_type)
491 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
492 else
493 {
494 result.AppendError ("unable make a pointer type\n");
495 result.SetStatus(eReturnStatusFailed);
496 return false;
497 }
498 --pointer_count;
499 }
500
Greg Claytona42880a2011-10-25 06:44:01 +0000501 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000502
Greg Claytona42880a2011-10-25 06:44:01 +0000503 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000504 {
505 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
506 view_as_type_cstr);
507 result.SetStatus(eReturnStatusFailed);
508 return false;
509 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000510
Greg Claytona42880a2011-10-25 06:44:01 +0000511 if (!m_format_options.GetCountValue().OptionWasSet())
512 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000513 }
514 else
515 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000516 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000517 }
518
519 // Look for invalid combinations of settings
520 if (error.Fail())
521 {
522 result.AppendErrorWithFormat("%s", error.AsCString());
523 result.SetStatus(eReturnStatusFailed);
524 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000525 }
526
Greg Clayton902b5be2011-10-26 04:32:38 +0000527 lldb::addr_t addr;
528 size_t total_byte_size = 0;
529 if (argc == 0)
530 {
531 // Use the last address and byte size and all options as they were
532 // if no options have been set
533 addr = m_next_addr;
534 total_byte_size = m_prev_byte_size;
535 if (!m_format_options.AnyOptionWasSet() &&
536 !m_memory_options.AnyOptionWasSet() &&
537 !m_outfile_options.AnyOptionWasSet() &&
538 !m_varobj_options.AnyOptionWasSet())
539 {
540 m_format_options = m_prev_format_options;
541 m_memory_options = m_prev_memory_options;
542 m_outfile_options = m_prev_outfile_options;
543 m_varobj_options = m_prev_varobj_options;
544 }
545 }
546
Greg Claytona42880a2011-10-25 06:44:01 +0000547 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
548 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000549 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000550
Chris Lattner24943d22010-06-08 16:52:24 +0000551 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000552 {
553 total_byte_size = item_count * item_byte_size;
554 if (total_byte_size == 0)
555 total_byte_size = 32;
556 }
Chris Lattner24943d22010-06-08 16:52:24 +0000557
Greg Clayton902b5be2011-10-26 04:32:38 +0000558 if (argc > 0)
559 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000560
561 if (addr == LLDB_INVALID_ADDRESS)
562 {
563 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
564 result.SetStatus(eReturnStatusFailed);
565 return false;
566 }
567
568 if (argc == 2)
569 {
570 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
571 if (end_addr == LLDB_INVALID_ADDRESS)
572 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000573 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000574 result.SetStatus(eReturnStatusFailed);
575 return false;
576 }
577 else if (end_addr <= addr)
578 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000579 result.AppendErrorWithFormat("end address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
Greg Claytona42880a2011-10-25 06:44:01 +0000583 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000584 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000585 result.AppendErrorWithFormat("specify either the end address (0x%llx) or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000586 result.SetStatus(eReturnStatusFailed);
587 return false;
588 }
589
590 total_byte_size = end_addr - addr;
591 item_count = total_byte_size / item_byte_size;
592 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000593
594 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000595 size_t bytes_read = 0;
596 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000597 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000598 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000599 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000600 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000601 if (bytes_read == 0)
602 {
603 result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
604 result.AppendError(error.AsCString());
605 result.SetStatus(eReturnStatusFailed);
606 return false;
607 }
608
609 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000610 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000611 else
612 {
613 m_next_addr = addr + bytes_read;
614 m_prev_byte_size = bytes_read;
615 m_prev_format_options = m_format_options;
616 m_prev_memory_options = m_memory_options;
617 m_prev_outfile_options = m_outfile_options;
618 m_prev_varobj_options = m_varobj_options;
619 }
Chris Lattner24943d22010-06-08 16:52:24 +0000620 }
621
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000622 StreamFile outfile_stream;
623 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000624 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
625 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000626 {
627 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000628 outfile_spec.GetPath (path, sizeof(path));
629
630 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
631 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
632 if (append)
633 open_options |= File::eOpenOptionAppend;
634
635 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000636 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000637 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000638 {
639 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
640 if (bytes_written > 0)
641 {
642 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
643 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000644 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000645 path);
646 return true;
647 }
648 else
649 {
650 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
651 result.SetStatus(eReturnStatusFailed);
652 return false;
653 }
654 }
655 else
656 {
657 // We are going to write ASCII to the file just point the
658 // output_stream to our outfile_stream...
659 output_stream = &outfile_stream;
660 }
661 }
662 else
663 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000664 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000665 result.SetStatus(eReturnStatusFailed);
666 return false;
667 }
668 }
669 else
670 {
671 output_stream = &result.GetOutputStream();
672 }
673
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000674
Greg Clayton24a6bd92011-10-27 17:55:14 +0000675 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000676 if (clang_ast_type.GetOpaqueQualType())
677 {
678 for (uint32_t i = 0; i<item_count; ++i)
679 {
680 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000681 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000682 StreamString name_strm;
683 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000684 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000685 name_strm.GetString().c_str(),
686 address,
687 clang_ast_type));
688 if (valobj_sp)
689 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000690 if (format != eFormatDefault)
691 valobj_sp->SetFormat (format);
692
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000693 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000694
Enrico Granata3069c622012-03-01 04:24:26 +0000695 ValueObject::DumpValueObjectOptions options;
696 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
697 .SetMaximumDepth(m_varobj_options.max_depth)
698 .SetShowLocation(m_varobj_options.show_location)
699 .SetShowTypes(m_varobj_options.show_types)
700 .SetUseObjectiveC(m_varobj_options.use_objc)
701 .SetScopeChecked(scope_already_checked)
702 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000703 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000704 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
705 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
706 .SetFormat(format)
707 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000708 ValueObject::DumpValueObject (*output_stream,
709 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000710 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000711 }
712 else
713 {
714 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
715 view_as_type_cstr,
716 name_strm.GetString().c_str());
717 result.SetStatus(eReturnStatusFailed);
718 return false;
719 }
720 }
721 return true;
722 }
723
724 result.SetStatus(eReturnStatusSuccessFinishResult);
725 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000726 target->GetArchitecture().GetByteOrder(),
727 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000728
729
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000730 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000731 uint32_t bytes_dumped = data.Dump (output_stream,
732 0,
733 m_format_options.GetFormat(),
734 item_byte_size,
735 item_count,
736 num_per_line,
737 addr,
738 0,
739 0,
740 exe_scope);
741 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000742 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000743 return true;
744 }
745
746protected:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000747 OptionGroupOptions m_option_group;
748 OptionGroupFormat m_format_options;
749 OptionGroupReadMemory m_memory_options;
750 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000751 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000752 lldb::addr_t m_next_addr;
753 lldb::addr_t m_prev_byte_size;
754 OptionGroupFormat m_prev_format_options;
755 OptionGroupReadMemory m_prev_memory_options;
756 OptionGroupOutputFile m_prev_outfile_options;
757 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000758};
759
Greg Claytona42880a2011-10-25 06:44:01 +0000760
761OptionDefinition
762g_memory_write_option_table[] =
763{
764{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
765{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
766};
767
768
Chris Lattner24943d22010-06-08 16:52:24 +0000769//----------------------------------------------------------------------
770// Write memory to the inferior process
771//----------------------------------------------------------------------
772class CommandObjectMemoryWrite : public CommandObject
773{
774public:
775
Greg Claytona42880a2011-10-25 06:44:01 +0000776 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000777 {
778 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000779 OptionGroupWriteMemory () :
780 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000781 {
Chris Lattner24943d22010-06-08 16:52:24 +0000782 }
783
784 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000785 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000786 {
787 }
788
Greg Claytona42880a2011-10-25 06:44:01 +0000789 virtual uint32_t
790 GetNumDefinitions ()
791 {
792 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
793 }
794
795 virtual const OptionDefinition*
796 GetDefinitions ()
797 {
798 return g_memory_write_option_table;
799 }
800
Chris Lattner24943d22010-06-08 16:52:24 +0000801 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000802 SetOptionValue (CommandInterpreter &interpreter,
803 uint32_t option_idx,
804 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000805 {
806 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000807 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
808
Chris Lattner24943d22010-06-08 16:52:24 +0000809 switch (short_option)
810 {
Greg Claytona42880a2011-10-25 06:44:01 +0000811 case 'i':
812 m_infile.SetFile (option_arg, true);
813 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000814 {
Greg Claytona42880a2011-10-25 06:44:01 +0000815 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000816 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000817 }
Greg Claytona42880a2011-10-25 06:44:01 +0000818 break;
819
820 case 'o':
821 {
822 bool success;
823 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
824 if (!success)
825 {
Greg Clayton9c236732011-10-26 00:56:27 +0000826 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000827 }
828 }
829 break;
830
831 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000832 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000833 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000834 }
835 return error;
836 }
Greg Claytona42880a2011-10-25 06:44:01 +0000837
838 virtual void
839 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000840 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000841 m_infile.Clear();
842 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000843 }
844
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000845 FileSpec m_infile;
846 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000847 };
848
Greg Clayton238c0a12010-09-18 01:14:36 +0000849 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
850 CommandObject (interpreter,
851 "memory write",
Caroline Ticeabb507a2010-09-08 21:06:11 +0000852 "Write to the memory of the process being debugged.",
Caroline Tice43b014a2010-10-04 22:28:36 +0000853 //"memory write [<cmd-options>] <addr> [value1 value2 ...]",
854 NULL,
Greg Claytonf15996e2011-04-07 22:46:35 +0000855 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000856 m_option_group (interpreter),
857 m_format_options (eFormatBytes, 1, UINT64_MAX),
858 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000859 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000860 CommandArgumentEntry arg1;
861 CommandArgumentEntry arg2;
862 CommandArgumentData addr_arg;
863 CommandArgumentData value_arg;
864
865 // Define the first (and only) variant of this arg.
866 addr_arg.arg_type = eArgTypeAddress;
867 addr_arg.arg_repetition = eArgRepeatPlain;
868
869 // There is only one variant this argument could be; put it into the argument entry.
870 arg1.push_back (addr_arg);
871
872 // Define the first (and only) variant of this arg.
873 value_arg.arg_type = eArgTypeValue;
874 value_arg.arg_repetition = eArgRepeatPlus;
875
876 // There is only one variant this argument could be; put it into the argument entry.
877 arg2.push_back (value_arg);
878
879 // Push the data for the first argument into the m_arguments vector.
880 m_arguments.push_back (arg1);
881 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000882
883 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
884 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
885 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
886 m_option_group.Finalize();
887
Chris Lattner24943d22010-06-08 16:52:24 +0000888 }
889
890 virtual
891 ~CommandObjectMemoryWrite ()
892 {
893 }
894
895 Options *
896 GetOptions ()
897 {
Greg Claytona42880a2011-10-25 06:44:01 +0000898 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000899 }
900
901 bool
902 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
903 {
904 if (total_byte_size > 8)
905 return false;
906
907 if (total_byte_size == 8)
908 return true;
909
910 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
911 return uval64 <= max;
912 }
913
914 bool
915 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
916 {
917 if (total_byte_size > 8)
918 return false;
919
920 if (total_byte_size == 8)
921 return true;
922
923 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
924 const int64_t min = ~(max);
925 return min <= sval64 && sval64 <= max;
926 }
927
928 virtual bool
Greg Clayton238c0a12010-09-18 01:14:36 +0000929 Execute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000930 CommandReturnObject &result)
931 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000932 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000933 if (process == NULL)
934 {
935 result.AppendError("need a process to read memory");
936 result.SetStatus(eReturnStatusFailed);
937 return false;
938 }
939
940 const size_t argc = command.GetArgumentCount();
941
Greg Claytona42880a2011-10-25 06:44:01 +0000942 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000943 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000944 if (argc < 1)
945 {
946 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
947 result.SetStatus(eReturnStatusFailed);
948 return false;
949 }
950 }
951 else if (argc < 2)
952 {
953 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 +0000954 result.SetStatus(eReturnStatusFailed);
955 return false;
956 }
957
Chris Lattner24943d22010-06-08 16:52:24 +0000958 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000959 process->GetTarget().GetArchitecture().GetAddressByteSize(),
960 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000961
Greg Claytona42880a2011-10-25 06:44:01 +0000962 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
963 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000964
Chris Lattner24943d22010-06-08 16:52:24 +0000965 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
966
967 if (addr == LLDB_INVALID_ADDRESS)
968 {
969 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
970 result.SetStatus(eReturnStatusFailed);
971 return false;
972 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000973
Greg Claytona42880a2011-10-25 06:44:01 +0000974 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000975 {
976 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000977 if (item_byte_size > 0)
978 length = item_byte_size;
979 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000980 if (data_sp)
981 {
982 length = data_sp->GetByteSize();
983 if (length > 0)
984 {
985 Error error;
986 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
987
988 if (bytes_written == length)
989 {
990 // All bytes written
991 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
992 result.SetStatus(eReturnStatusSuccessFinishResult);
993 }
994 else if (bytes_written > 0)
995 {
996 // Some byte written
997 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
998 result.SetStatus(eReturnStatusSuccessFinishResult);
999 }
1000 else
1001 {
1002 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1003 result.SetStatus(eReturnStatusFailed);
1004 }
1005 }
1006 }
1007 else
1008 {
1009 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1010 result.SetStatus(eReturnStatusFailed);
1011 }
1012 return result.Succeeded();
1013 }
Greg Claytona42880a2011-10-25 06:44:01 +00001014 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001015 {
Greg Claytona42880a2011-10-25 06:44:01 +00001016 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001017 item_byte_size = buffer.GetAddressByteSize();
1018 else
1019 item_byte_size = 1;
1020 }
1021
Chris Lattner24943d22010-06-08 16:52:24 +00001022 command.Shift(); // shift off the address argument
1023 uint64_t uval64;
1024 int64_t sval64;
1025 bool success = false;
1026 const uint32_t num_value_args = command.GetArgumentCount();
1027 uint32_t i;
1028 for (i=0; i<num_value_args; ++i)
1029 {
1030 const char *value_str = command.GetArgumentAtIndex(i);
1031
Greg Claytona42880a2011-10-25 06:44:01 +00001032 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001033 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001034 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001035 case eFormatFloat: // TODO: add support for floats soon
1036 case eFormatCharPrintable:
1037 case eFormatBytesWithASCII:
1038 case eFormatComplex:
1039 case eFormatEnum:
1040 case eFormatUnicode16:
1041 case eFormatUnicode32:
1042 case eFormatVectorOfChar:
1043 case eFormatVectorOfSInt8:
1044 case eFormatVectorOfUInt8:
1045 case eFormatVectorOfSInt16:
1046 case eFormatVectorOfUInt16:
1047 case eFormatVectorOfSInt32:
1048 case eFormatVectorOfUInt32:
1049 case eFormatVectorOfSInt64:
1050 case eFormatVectorOfUInt64:
1051 case eFormatVectorOfFloat32:
1052 case eFormatVectorOfFloat64:
1053 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001054 case eFormatOSType:
1055 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001056 case eFormatAddressInfo:
1057 case eFormatHexFloat:
1058 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001059 result.AppendError("unsupported format for writing memory");
1060 result.SetStatus(eReturnStatusFailed);
1061 return false;
1062
1063 case eFormatDefault:
1064 case eFormatBytes:
1065 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001066 case eFormatPointer:
1067
Chris Lattner24943d22010-06-08 16:52:24 +00001068 // Decode hex bytes
1069 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1070 if (!success)
1071 {
1072 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1073 result.SetStatus(eReturnStatusFailed);
1074 return false;
1075 }
1076 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1077 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001078 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001079 result.SetStatus(eReturnStatusFailed);
1080 return false;
1081 }
1082 buffer.PutMaxHex64 (uval64, item_byte_size);
1083 break;
1084
1085 case eFormatBoolean:
1086 uval64 = Args::StringToBoolean(value_str, false, &success);
1087 if (!success)
1088 {
1089 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1090 result.SetStatus(eReturnStatusFailed);
1091 return false;
1092 }
1093 buffer.PutMaxHex64 (uval64, item_byte_size);
1094 break;
1095
1096 case eFormatBinary:
1097 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1098 if (!success)
1099 {
1100 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1101 result.SetStatus(eReturnStatusFailed);
1102 return false;
1103 }
1104 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1105 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001106 result.AppendErrorWithFormat ("Value 0x%llx is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001107 result.SetStatus(eReturnStatusFailed);
1108 return false;
1109 }
1110 buffer.PutMaxHex64 (uval64, item_byte_size);
1111 break;
1112
Greg Clayton307fa072011-06-17 23:50:44 +00001113 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001114 case eFormatChar:
1115 case eFormatCString:
1116 if (value_str[0])
1117 {
1118 size_t len = strlen (value_str);
1119 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001120 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001121 ++len;
1122 Error error;
1123 if (process->WriteMemory (addr, value_str, len, error) == len)
1124 {
1125 addr += len;
1126 }
1127 else
1128 {
1129 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1130 result.SetStatus(eReturnStatusFailed);
1131 return false;
1132 }
1133 }
1134 break;
1135
1136 case eFormatDecimal:
1137 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1138 if (!success)
1139 {
1140 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1141 result.SetStatus(eReturnStatusFailed);
1142 return false;
1143 }
1144 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1145 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001146 result.AppendErrorWithFormat ("Value %lli is too large or small to fit in a %lu byte signed integer value.\n", sval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001147 result.SetStatus(eReturnStatusFailed);
1148 return false;
1149 }
1150 buffer.PutMaxHex64 (sval64, item_byte_size);
1151 break;
1152
1153 case eFormatUnsigned:
1154 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1155 if (!success)
1156 {
1157 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1158 result.SetStatus(eReturnStatusFailed);
1159 return false;
1160 }
1161 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1162 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001163 result.AppendErrorWithFormat ("Value %llu is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001164 result.SetStatus(eReturnStatusFailed);
1165 return false;
1166 }
1167 buffer.PutMaxHex64 (uval64, item_byte_size);
1168 break;
1169
1170 case eFormatOctal:
1171 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1172 if (!success)
1173 {
1174 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1175 result.SetStatus(eReturnStatusFailed);
1176 return false;
1177 }
1178 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1179 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001180 result.AppendErrorWithFormat ("Value %llo is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001181 result.SetStatus(eReturnStatusFailed);
1182 return false;
1183 }
1184 buffer.PutMaxHex64 (uval64, item_byte_size);
1185 break;
1186 }
1187 }
1188
1189 if (!buffer.GetString().empty())
1190 {
1191 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001192 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001193 return true;
1194 else
1195 {
1196 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1197 result.SetStatus(eReturnStatusFailed);
1198 return false;
1199 }
1200 }
1201 return true;
1202 }
1203
1204protected:
Greg Claytona42880a2011-10-25 06:44:01 +00001205
1206 OptionGroupOptions m_option_group;
1207 OptionGroupFormat m_format_options;
1208 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001209};
1210
Chris Lattner24943d22010-06-08 16:52:24 +00001211
1212//-------------------------------------------------------------------------
1213// CommandObjectMemory
1214//-------------------------------------------------------------------------
1215
Greg Clayton63094e02010-06-23 01:19:29 +00001216CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001217 CommandObjectMultiword (interpreter,
1218 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001219 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001220 "memory <subcommand> [<subcommand-options>]")
1221{
Greg Clayton238c0a12010-09-18 01:14:36 +00001222 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1223 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001224}
1225
1226CommandObjectMemory::~CommandObjectMemory ()
1227{
1228}