blob: 6a008956b653b6e9e5e7591a9eb643e549c87200 [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"
Greg Clayton49ce8962012-08-29 21:13:06 +000019#include "lldb/Core/Module.h"
Chris Lattner24943d22010-06-08 16:52:24 +000020#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000021#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000022#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000023#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000024#include "lldb/Interpreter/CommandInterpreter.h"
25#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000026#include "lldb/Interpreter/OptionGroupFormat.h"
27#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000028#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton73844aa2012-08-22 17:17:09 +000029#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000030#include "lldb/Symbol/TypeList.h"
Chris Lattner24943d22010-06-08 16:52:24 +000031#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000032#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033
34using namespace lldb;
35using namespace lldb_private;
36
Greg Clayton56bbdaf2011-04-28 20:55:26 +000037static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000038g_option_table[] =
39{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000040 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
41 { 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."},
Sean Callanan06dc17f2012-09-24 22:25:51 +000042 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Sean Callanan8a6f3e92012-04-28 01:27:38 +000043 { LLDB_OPT_SET_4, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
Greg Clayton57b3c6b2011-04-27 22:04:39 +000044};
45
46
47
48class OptionGroupReadMemory : public OptionGroup
49{
50public:
51
52 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000053 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000054 m_output_as_binary (false),
55 m_view_as_type()
56 {
57 }
58
59 virtual
60 ~OptionGroupReadMemory ()
61 {
62 }
63
64
65 virtual uint32_t
66 GetNumDefinitions ()
67 {
68 return sizeof (g_option_table) / sizeof (OptionDefinition);
69 }
70
71 virtual const OptionDefinition*
72 GetDefinitions ()
73 {
74 return g_option_table;
75 }
76
77 virtual Error
78 SetOptionValue (CommandInterpreter &interpreter,
79 uint32_t option_idx,
80 const char *option_arg)
81 {
82 Error error;
83 char short_option = (char) g_option_table[option_idx].short_option;
84
85 switch (short_option)
86 {
87 case 'l':
88 error = m_num_per_line.SetValueFromCString (option_arg);
89 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000090 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000091 break;
Greg Claytona42880a2011-10-25 06:44:01 +000092
Greg Clayton57b3c6b2011-04-27 22:04:39 +000093 case 'b':
94 m_output_as_binary = true;
95 break;
96
97 case 't':
98 error = m_view_as_type.SetValueFromCString (option_arg);
99 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000100
101 case 'r':
102 m_force = true;
103 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000104
105 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000106 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000107 break;
108 }
109 return error;
110 }
111
112 virtual void
113 OptionParsingStarting (CommandInterpreter &interpreter)
114 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000115 m_num_per_line.Clear();
116 m_output_as_binary = false;
117 m_view_as_type.Clear();
118 }
119
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000120 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000121 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000122 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000123 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000124 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
125 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000126 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000127 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000128 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000129
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000130 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000131 {
132 default:
133 break;
134
135 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000136 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000137 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000138 if (!num_per_line_option_set)
139 m_num_per_line = 1;
140 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000141 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000142 break;
143
144 case eFormatCString:
145 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000146
147 case eFormatInstruction:
148 if (count_option_set)
149 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
150 m_num_per_line = 1;
151 break;
152
153 case eFormatAddressInfo:
154 if (!byte_size_option_set)
155 byte_size_value = target->GetArchitecture().GetAddressByteSize();
156 m_num_per_line = 1;
157 if (!count_option_set)
158 format_options.GetCountValue() = 8;
159 break;
160
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000161 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000162 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000163 if (!num_per_line_option_set)
164 m_num_per_line = 4;
165 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000166 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000167 break;
168
169 case eFormatBinary:
170 case eFormatFloat:
171 case eFormatOctal:
172 case eFormatDecimal:
173 case eFormatEnum:
174 case eFormatUnicode16:
175 case eFormatUnicode32:
176 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000177 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000178 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000179 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000180 if (!num_per_line_option_set)
181 m_num_per_line = 1;
182 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000183 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000184 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000185
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000186 case eFormatBytes:
187 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000188 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000189 {
Greg Claytona42880a2011-10-25 06:44:01 +0000190 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000191 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
192 "\tconsider using a different display format or don't specify the byte size",
193 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000194 }
195 else
Greg Claytona42880a2011-10-25 06:44:01 +0000196 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000197 if (!num_per_line_option_set)
198 m_num_per_line = 16;
199 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000200 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000201 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000202 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000203 case eFormatChar:
204 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000205 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000206 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000207 if (!num_per_line_option_set)
208 m_num_per_line = 32;
209 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000210 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000211 break;
212 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000213 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000214 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000215 if (!num_per_line_option_set)
216 m_num_per_line = 1;
217 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000218 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000219 break;
220 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000221 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000222 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000223 if (!num_per_line_option_set)
224 {
Greg Claytona42880a2011-10-25 06:44:01 +0000225 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000226 {
227 case 1:
228 case 2:
229 m_num_per_line = 8;
230 break;
231 case 4:
232 m_num_per_line = 4;
233 break;
234 case 8:
235 m_num_per_line = 2;
236 break;
237 default:
238 m_num_per_line = 1;
239 break;
240 }
241 }
242 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000243 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000244 break;
245
246 case eFormatVectorOfChar:
247 case eFormatVectorOfSInt8:
248 case eFormatVectorOfUInt8:
249 case eFormatVectorOfSInt16:
250 case eFormatVectorOfUInt16:
251 case eFormatVectorOfSInt32:
252 case eFormatVectorOfUInt32:
253 case eFormatVectorOfSInt64:
254 case eFormatVectorOfUInt64:
255 case eFormatVectorOfFloat32:
256 case eFormatVectorOfFloat64:
257 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000258 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000259 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000260 if (!num_per_line_option_set)
261 m_num_per_line = 1;
262 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000263 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000264 break;
265 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000266 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000267 }
268
Greg Clayton902b5be2011-10-26 04:32:38 +0000269 bool
270 AnyOptionWasSet () const
271 {
272 return m_num_per_line.OptionWasSet() ||
273 m_output_as_binary ||
274 m_view_as_type.OptionWasSet();
275 }
276
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000277 OptionValueUInt64 m_num_per_line;
278 bool m_output_as_binary;
279 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000280 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000281};
282
283
284
Chris Lattner24943d22010-06-08 16:52:24 +0000285//----------------------------------------------------------------------
286// Read memory from the inferior process
287//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000288class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000289{
290public:
291
Greg Clayton238c0a12010-09-18 01:14:36 +0000292 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000293 CommandObjectParsed (interpreter,
294 "memory read",
295 "Read from the memory of the process being debugged.",
296 NULL,
297 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000298 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000299 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000300 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000301 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000302 m_varobj_options(),
303 m_next_addr(LLDB_INVALID_ADDRESS),
304 m_prev_byte_size(0),
305 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
306 m_prev_memory_options (),
307 m_prev_outfile_options (),
308 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000309 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000310 CommandArgumentEntry arg1;
311 CommandArgumentEntry arg2;
312 CommandArgumentData start_addr_arg;
313 CommandArgumentData end_addr_arg;
314
315 // Define the first (and only) variant of this arg.
316 start_addr_arg.arg_type = eArgTypeStartAddress;
317 start_addr_arg.arg_repetition = eArgRepeatPlain;
318
319 // There is only one variant this argument could be; put it into the argument entry.
320 arg1.push_back (start_addr_arg);
321
322 // Define the first (and only) variant of this arg.
323 end_addr_arg.arg_type = eArgTypeEndAddress;
324 end_addr_arg.arg_repetition = eArgRepeatOptional;
325
326 // There is only one variant this argument could be; put it into the argument entry.
327 arg2.push_back (end_addr_arg);
328
329 // Push the data for the first argument into the m_arguments vector.
330 m_arguments.push_back (arg1);
331 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000332
Greg Claytona42880a2011-10-25 06:44:01 +0000333 // Add the "--format" and "--count" options to group 1 and 3
334 m_option_group.Append (&m_format_options,
335 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000336 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000337 m_option_group.Append (&m_format_options,
338 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000339 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000340 // Add the "--size" option to group 1 and 2
341 m_option_group.Append (&m_format_options,
342 OptionGroupFormat::OPTION_GROUP_SIZE,
343 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000344 m_option_group.Append (&m_memory_options);
345 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 +0000346 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000347 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000348 }
349
350 virtual
351 ~CommandObjectMemoryRead ()
352 {
353 }
354
355 Options *
356 GetOptions ()
357 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000358 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000359 }
360
Greg Clayton902b5be2011-10-26 04:32:38 +0000361 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
362 {
363 return m_cmd_name.c_str();
364 }
365
Jim Inghamda26bd22012-06-08 21:56:10 +0000366protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000367 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000368 DoExecute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000369 CommandReturnObject &result)
370 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000371 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000372 Target *target = exe_ctx.GetTargetPtr();
373 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000374 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000375 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000376 result.SetStatus(eReturnStatusFailed);
377 return false;
378 }
379 const size_t argc = command.GetArgumentCount();
380
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000381
Greg Clayton902b5be2011-10-26 04:32:38 +0000382 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000383 {
384 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
385 result.SetStatus(eReturnStatusFailed);
386 return false;
387 }
388
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000389 ClangASTType clang_ast_type;
390 Error error;
391
392 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000393 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
394 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000395 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000396 // We are viewing memory as a type
397 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000398 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000399 TypeList type_list;
400 uint32_t reference_count = 0;
401 uint32_t pointer_count = 0;
402 size_t idx;
Sean Callananddb2ece2012-07-10 21:24:26 +0000403
404#define ALL_KEYWORDS \
405 KEYWORD("const") \
406 KEYWORD("volatile") \
407 KEYWORD("restrict") \
408 KEYWORD("struct") \
409 KEYWORD("class") \
410 KEYWORD("union")
411
412#define KEYWORD(s) s,
413 static const char *g_keywords[] =
414 {
415 ALL_KEYWORDS
416 };
417#undef KEYWORD
418
419#define KEYWORD(s) (sizeof(s) - 1),
420 static const int g_keyword_lengths[] =
421 {
422 ALL_KEYWORDS
423 };
424#undef KEYWORD
425
426#undef ALL_KEYWORDS
427
428 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000429 std::string type_str(view_as_type_cstr);
430
431 // Remove all instances of g_keywords that are followed by spaces
432 for (size_t i = 0; i < g_num_keywords; ++i)
433 {
434 const char *keyword = g_keywords[i];
Sean Callananddb2ece2012-07-10 21:24:26 +0000435 int keyword_len = g_keyword_lengths[i];
436
437 idx = 0;
438 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000439 {
440 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callananddb2ece2012-07-10 21:24:26 +0000441 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000442 type_str.erase(idx, keyword_len+1);
Sean Callananddb2ece2012-07-10 21:24:26 +0000443 idx = 0;
444 }
445 else
446 {
447 idx += keyword_len;
448 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000449 }
450 }
451 bool done = type_str.empty();
452 //
453 idx = type_str.find_first_not_of (" \t");
454 if (idx > 0 && idx != std::string::npos)
455 type_str.erase (0, idx);
456 while (!done)
457 {
458 // Strip trailing spaces
459 if (type_str.empty())
460 done = true;
461 else
462 {
463 switch (type_str[type_str.size()-1])
464 {
465 case '*':
466 ++pointer_count;
467 // fall through...
468 case ' ':
469 case '\t':
470 type_str.erase(type_str.size()-1);
471 break;
472
473 case '&':
474 if (reference_count == 0)
475 {
476 reference_count = 1;
477 type_str.erase(type_str.size()-1);
478 }
479 else
480 {
481 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
482 result.SetStatus(eReturnStatusFailed);
483 return false;
484 }
485 break;
486
487 default:
488 done = true;
489 break;
490 }
491 }
492 }
493
494 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000495 StackFrame *frame = exe_ctx.GetFramePtr();
496 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000497 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000498 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000499 if (sc.module_sp)
500 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000501 sc.module_sp->FindTypes (sc,
502 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000503 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000504 1,
505 type_list);
506 }
507 }
508 if (type_list.GetSize() == 0)
509 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000510 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000511 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000512 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000513 1,
514 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000515 }
516
517 if (type_list.GetSize() == 0)
518 {
519 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
520 lookup_type_name.GetCString(),
521 view_as_type_cstr);
522 result.SetStatus(eReturnStatusFailed);
523 return false;
524 }
525
526 TypeSP type_sp (type_list.GetTypeAtIndex(0));
527 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
528
529 while (pointer_count > 0)
530 {
531 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
532 if (pointer_type)
533 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
534 else
535 {
536 result.AppendError ("unable make a pointer type\n");
537 result.SetStatus(eReturnStatusFailed);
538 return false;
539 }
540 --pointer_count;
541 }
542
Greg Claytona42880a2011-10-25 06:44:01 +0000543 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000544
Greg Claytona42880a2011-10-25 06:44:01 +0000545 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000546 {
547 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
548 view_as_type_cstr);
549 result.SetStatus(eReturnStatusFailed);
550 return false;
551 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000552
Greg Claytona42880a2011-10-25 06:44:01 +0000553 if (!m_format_options.GetCountValue().OptionWasSet())
554 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000555 }
556 else
557 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000558 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000559 }
560
561 // Look for invalid combinations of settings
562 if (error.Fail())
563 {
564 result.AppendErrorWithFormat("%s", error.AsCString());
565 result.SetStatus(eReturnStatusFailed);
566 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000567 }
568
Greg Clayton902b5be2011-10-26 04:32:38 +0000569 lldb::addr_t addr;
570 size_t total_byte_size = 0;
571 if (argc == 0)
572 {
573 // Use the last address and byte size and all options as they were
574 // if no options have been set
575 addr = m_next_addr;
576 total_byte_size = m_prev_byte_size;
577 if (!m_format_options.AnyOptionWasSet() &&
578 !m_memory_options.AnyOptionWasSet() &&
579 !m_outfile_options.AnyOptionWasSet() &&
580 !m_varobj_options.AnyOptionWasSet())
581 {
582 m_format_options = m_prev_format_options;
583 m_memory_options = m_prev_memory_options;
584 m_outfile_options = m_prev_outfile_options;
585 m_varobj_options = m_prev_varobj_options;
586 }
587 }
588
Greg Claytona42880a2011-10-25 06:44:01 +0000589 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
590 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000591 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000592
Chris Lattner24943d22010-06-08 16:52:24 +0000593 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000594 {
595 total_byte_size = item_count * item_byte_size;
596 if (total_byte_size == 0)
597 total_byte_size = 32;
598 }
Chris Lattner24943d22010-06-08 16:52:24 +0000599
Greg Clayton902b5be2011-10-26 04:32:38 +0000600 if (argc > 0)
601 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000602
603 if (addr == LLDB_INVALID_ADDRESS)
604 {
605 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
606 result.SetStatus(eReturnStatusFailed);
607 return false;
608 }
609
610 if (argc == 2)
611 {
612 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
613 if (end_addr == LLDB_INVALID_ADDRESS)
614 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000615 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000616 result.SetStatus(eReturnStatusFailed);
617 return false;
618 }
619 else if (end_addr <= addr)
620 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000621 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 +0000622 result.SetStatus(eReturnStatusFailed);
623 return false;
624 }
Greg Claytona42880a2011-10-25 06:44:01 +0000625 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000626 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000627 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 +0000628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
631
632 total_byte_size = end_addr - addr;
633 item_count = total_byte_size / item_byte_size;
634 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000635
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000636 if (total_byte_size > 1024 && !m_memory_options.m_force)
637 {
638 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
639 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
640 return false;
641 }
642
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000643 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000644 size_t bytes_read = 0;
645 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000646 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000647 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000648 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000649 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000650 if (bytes_read == 0)
651 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000652 const char *error_cstr = error.AsCString();
653 if (error_cstr && error_cstr[0])
654 {
655 result.AppendError(error_cstr);
656 }
657 else
658 {
659 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
660 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000661 result.SetStatus(eReturnStatusFailed);
662 return false;
663 }
664
665 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000666 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 +0000667 else
668 {
669 m_next_addr = addr + bytes_read;
670 m_prev_byte_size = bytes_read;
671 m_prev_format_options = m_format_options;
672 m_prev_memory_options = m_memory_options;
673 m_prev_outfile_options = m_outfile_options;
674 m_prev_varobj_options = m_varobj_options;
675 }
Chris Lattner24943d22010-06-08 16:52:24 +0000676 }
677
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000678 StreamFile outfile_stream;
679 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000680 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
681 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000682 {
683 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684 outfile_spec.GetPath (path, sizeof(path));
685
686 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
687 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
688 if (append)
689 open_options |= File::eOpenOptionAppend;
690
691 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000692 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000693 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000694 {
695 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
696 if (bytes_written > 0)
697 {
698 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
699 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000700 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000701 path);
702 return true;
703 }
704 else
705 {
Greg Clayton851e30e2012-09-18 18:04:04 +0000706 result.AppendErrorWithFormat("Failed to write %llu bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000707 result.SetStatus(eReturnStatusFailed);
708 return false;
709 }
710 }
711 else
712 {
713 // We are going to write ASCII to the file just point the
714 // output_stream to our outfile_stream...
715 output_stream = &outfile_stream;
716 }
717 }
718 else
719 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000720 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000721 result.SetStatus(eReturnStatusFailed);
722 return false;
723 }
724 }
725 else
726 {
727 output_stream = &result.GetOutputStream();
728 }
729
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000730
Greg Clayton24a6bd92011-10-27 17:55:14 +0000731 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000732 if (clang_ast_type.GetOpaqueQualType())
733 {
734 for (uint32_t i = 0; i<item_count; ++i)
735 {
736 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000737 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000738 StreamString name_strm;
739 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000740 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000741 name_strm.GetString().c_str(),
742 address,
743 clang_ast_type));
744 if (valobj_sp)
745 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000746 if (format != eFormatDefault)
747 valobj_sp->SetFormat (format);
748
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000749 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000750
Enrico Granata3069c622012-03-01 04:24:26 +0000751 ValueObject::DumpValueObjectOptions options;
752 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
753 .SetMaximumDepth(m_varobj_options.max_depth)
754 .SetShowLocation(m_varobj_options.show_location)
755 .SetShowTypes(m_varobj_options.show_types)
756 .SetUseObjectiveC(m_varobj_options.use_objc)
757 .SetScopeChecked(scope_already_checked)
758 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000759 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000760 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
761 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
762 .SetFormat(format)
763 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000764 ValueObject::DumpValueObject (*output_stream,
765 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000766 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000767 }
768 else
769 {
770 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
771 view_as_type_cstr,
772 name_strm.GetString().c_str());
773 result.SetStatus(eReturnStatusFailed);
774 return false;
775 }
776 }
777 return true;
778 }
779
780 result.SetStatus(eReturnStatusSuccessFinishResult);
781 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000782 target->GetArchitecture().GetByteOrder(),
783 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000784
785
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000786 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000787 uint32_t bytes_dumped = data.Dump (output_stream,
788 0,
789 m_format_options.GetFormat(),
790 item_byte_size,
791 item_count,
792 num_per_line,
793 addr,
794 0,
795 0,
796 exe_scope);
797 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000798 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000799 return true;
800 }
801
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000802 OptionGroupOptions m_option_group;
803 OptionGroupFormat m_format_options;
804 OptionGroupReadMemory m_memory_options;
805 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000806 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000807 lldb::addr_t m_next_addr;
808 lldb::addr_t m_prev_byte_size;
809 OptionGroupFormat m_prev_format_options;
810 OptionGroupReadMemory m_prev_memory_options;
811 OptionGroupOutputFile m_prev_outfile_options;
812 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000813};
814
Greg Claytona42880a2011-10-25 06:44:01 +0000815
816OptionDefinition
817g_memory_write_option_table[] =
818{
819{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
820{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
821};
822
823
Chris Lattner24943d22010-06-08 16:52:24 +0000824//----------------------------------------------------------------------
825// Write memory to the inferior process
826//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000827class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000828{
829public:
830
Greg Claytona42880a2011-10-25 06:44:01 +0000831 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000832 {
833 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000834 OptionGroupWriteMemory () :
835 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000836 {
Chris Lattner24943d22010-06-08 16:52:24 +0000837 }
838
839 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000840 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000841 {
842 }
843
Greg Claytona42880a2011-10-25 06:44:01 +0000844 virtual uint32_t
845 GetNumDefinitions ()
846 {
847 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
848 }
849
850 virtual const OptionDefinition*
851 GetDefinitions ()
852 {
853 return g_memory_write_option_table;
854 }
855
Chris Lattner24943d22010-06-08 16:52:24 +0000856 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000857 SetOptionValue (CommandInterpreter &interpreter,
858 uint32_t option_idx,
859 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000860 {
861 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000862 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
863
Chris Lattner24943d22010-06-08 16:52:24 +0000864 switch (short_option)
865 {
Greg Claytona42880a2011-10-25 06:44:01 +0000866 case 'i':
867 m_infile.SetFile (option_arg, true);
868 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000869 {
Greg Claytona42880a2011-10-25 06:44:01 +0000870 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000871 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000872 }
Greg Claytona42880a2011-10-25 06:44:01 +0000873 break;
874
875 case 'o':
876 {
877 bool success;
878 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
879 if (!success)
880 {
Greg Clayton9c236732011-10-26 00:56:27 +0000881 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000882 }
883 }
884 break;
885
886 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000887 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000888 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000889 }
890 return error;
891 }
Greg Claytona42880a2011-10-25 06:44:01 +0000892
893 virtual void
894 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000895 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000896 m_infile.Clear();
897 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000898 }
899
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000900 FileSpec m_infile;
901 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000902 };
903
Greg Clayton238c0a12010-09-18 01:14:36 +0000904 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000905 CommandObjectParsed (interpreter,
906 "memory write",
907 "Write to the memory of the process being debugged.",
908 NULL,
909 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000910 m_option_group (interpreter),
911 m_format_options (eFormatBytes, 1, UINT64_MAX),
912 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000913 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000914 CommandArgumentEntry arg1;
915 CommandArgumentEntry arg2;
916 CommandArgumentData addr_arg;
917 CommandArgumentData value_arg;
918
919 // Define the first (and only) variant of this arg.
920 addr_arg.arg_type = eArgTypeAddress;
921 addr_arg.arg_repetition = eArgRepeatPlain;
922
923 // There is only one variant this argument could be; put it into the argument entry.
924 arg1.push_back (addr_arg);
925
926 // Define the first (and only) variant of this arg.
927 value_arg.arg_type = eArgTypeValue;
928 value_arg.arg_repetition = eArgRepeatPlus;
929
930 // There is only one variant this argument could be; put it into the argument entry.
931 arg2.push_back (value_arg);
932
933 // Push the data for the first argument into the m_arguments vector.
934 m_arguments.push_back (arg1);
935 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000936
937 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
938 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
939 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
940 m_option_group.Finalize();
941
Chris Lattner24943d22010-06-08 16:52:24 +0000942 }
943
944 virtual
945 ~CommandObjectMemoryWrite ()
946 {
947 }
948
949 Options *
950 GetOptions ()
951 {
Greg Claytona42880a2011-10-25 06:44:01 +0000952 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000953 }
954
955 bool
956 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
957 {
958 if (total_byte_size > 8)
959 return false;
960
961 if (total_byte_size == 8)
962 return true;
963
964 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
965 return uval64 <= max;
966 }
967
968 bool
969 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
970 {
971 if (total_byte_size > 8)
972 return false;
973
974 if (total_byte_size == 8)
975 return true;
976
977 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
978 const int64_t min = ~(max);
979 return min <= sval64 && sval64 <= max;
980 }
981
Jim Inghamda26bd22012-06-08 21:56:10 +0000982protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000983 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000984 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000985 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000986 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000987 if (process == NULL)
988 {
989 result.AppendError("need a process to read memory");
990 result.SetStatus(eReturnStatusFailed);
991 return false;
992 }
993
994 const size_t argc = command.GetArgumentCount();
995
Greg Claytona42880a2011-10-25 06:44:01 +0000996 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000997 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000998 if (argc < 1)
999 {
1000 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1001 result.SetStatus(eReturnStatusFailed);
1002 return false;
1003 }
1004 }
1005 else if (argc < 2)
1006 {
1007 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 +00001008 result.SetStatus(eReturnStatusFailed);
1009 return false;
1010 }
1011
Chris Lattner24943d22010-06-08 16:52:24 +00001012 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001013 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1014 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001015
Greg Claytona42880a2011-10-25 06:44:01 +00001016 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1017 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001018
Chris Lattner24943d22010-06-08 16:52:24 +00001019 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1020
1021 if (addr == LLDB_INVALID_ADDRESS)
1022 {
1023 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1024 result.SetStatus(eReturnStatusFailed);
1025 return false;
1026 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001027
Greg Claytona42880a2011-10-25 06:44:01 +00001028 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001029 {
1030 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001031 if (item_byte_size > 0)
1032 length = item_byte_size;
1033 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001034 if (data_sp)
1035 {
1036 length = data_sp->GetByteSize();
1037 if (length > 0)
1038 {
1039 Error error;
1040 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1041
1042 if (bytes_written == length)
1043 {
1044 // All bytes written
Greg Clayton851e30e2012-09-18 18:04:04 +00001045 result.GetOutputStream().Printf("%llu bytes were written to 0x%llx\n", (uint64_t)bytes_written, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001046 result.SetStatus(eReturnStatusSuccessFinishResult);
1047 }
1048 else if (bytes_written > 0)
1049 {
1050 // Some byte written
Greg Clayton851e30e2012-09-18 18:04:04 +00001051 result.GetOutputStream().Printf("%llu bytes of %llu requested were written to 0x%llx\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001052 result.SetStatus(eReturnStatusSuccessFinishResult);
1053 }
1054 else
1055 {
1056 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1057 result.SetStatus(eReturnStatusFailed);
1058 }
1059 }
1060 }
1061 else
1062 {
1063 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1064 result.SetStatus(eReturnStatusFailed);
1065 }
1066 return result.Succeeded();
1067 }
Greg Claytona42880a2011-10-25 06:44:01 +00001068 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001069 {
Greg Claytona42880a2011-10-25 06:44:01 +00001070 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001071 item_byte_size = buffer.GetAddressByteSize();
1072 else
1073 item_byte_size = 1;
1074 }
1075
Chris Lattner24943d22010-06-08 16:52:24 +00001076 command.Shift(); // shift off the address argument
1077 uint64_t uval64;
1078 int64_t sval64;
1079 bool success = false;
1080 const uint32_t num_value_args = command.GetArgumentCount();
1081 uint32_t i;
1082 for (i=0; i<num_value_args; ++i)
1083 {
1084 const char *value_str = command.GetArgumentAtIndex(i);
1085
Greg Claytona42880a2011-10-25 06:44:01 +00001086 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001087 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001088 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001089 case eFormatFloat: // TODO: add support for floats soon
1090 case eFormatCharPrintable:
1091 case eFormatBytesWithASCII:
1092 case eFormatComplex:
1093 case eFormatEnum:
1094 case eFormatUnicode16:
1095 case eFormatUnicode32:
1096 case eFormatVectorOfChar:
1097 case eFormatVectorOfSInt8:
1098 case eFormatVectorOfUInt8:
1099 case eFormatVectorOfSInt16:
1100 case eFormatVectorOfUInt16:
1101 case eFormatVectorOfSInt32:
1102 case eFormatVectorOfUInt32:
1103 case eFormatVectorOfSInt64:
1104 case eFormatVectorOfUInt64:
1105 case eFormatVectorOfFloat32:
1106 case eFormatVectorOfFloat64:
1107 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001108 case eFormatOSType:
1109 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001110 case eFormatAddressInfo:
1111 case eFormatHexFloat:
1112 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001113 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001114 result.AppendError("unsupported format for writing memory");
1115 result.SetStatus(eReturnStatusFailed);
1116 return false;
1117
1118 case eFormatDefault:
1119 case eFormatBytes:
1120 case eFormatHex:
Enrico Granata535543d2012-08-09 19:33:34 +00001121 case eFormatHexUppercase:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001122 case eFormatPointer:
1123
Chris Lattner24943d22010-06-08 16:52:24 +00001124 // Decode hex bytes
1125 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1126 if (!success)
1127 {
1128 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1129 result.SetStatus(eReturnStatusFailed);
1130 return false;
1131 }
1132 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1133 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001134 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 +00001135 result.SetStatus(eReturnStatusFailed);
1136 return false;
1137 }
1138 buffer.PutMaxHex64 (uval64, item_byte_size);
1139 break;
1140
1141 case eFormatBoolean:
1142 uval64 = Args::StringToBoolean(value_str, false, &success);
1143 if (!success)
1144 {
1145 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1146 result.SetStatus(eReturnStatusFailed);
1147 return false;
1148 }
1149 buffer.PutMaxHex64 (uval64, item_byte_size);
1150 break;
1151
1152 case eFormatBinary:
1153 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1154 if (!success)
1155 {
1156 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1157 result.SetStatus(eReturnStatusFailed);
1158 return false;
1159 }
1160 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1161 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001162 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 +00001163 result.SetStatus(eReturnStatusFailed);
1164 return false;
1165 }
1166 buffer.PutMaxHex64 (uval64, item_byte_size);
1167 break;
1168
Greg Clayton307fa072011-06-17 23:50:44 +00001169 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001170 case eFormatChar:
1171 case eFormatCString:
1172 if (value_str[0])
1173 {
1174 size_t len = strlen (value_str);
1175 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001176 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001177 ++len;
1178 Error error;
1179 if (process->WriteMemory (addr, value_str, len, error) == len)
1180 {
1181 addr += len;
1182 }
1183 else
1184 {
1185 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1186 result.SetStatus(eReturnStatusFailed);
1187 return false;
1188 }
1189 }
1190 break;
1191
1192 case eFormatDecimal:
1193 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1194 if (!success)
1195 {
1196 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1197 result.SetStatus(eReturnStatusFailed);
1198 return false;
1199 }
1200 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1201 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001202 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 +00001203 result.SetStatus(eReturnStatusFailed);
1204 return false;
1205 }
1206 buffer.PutMaxHex64 (sval64, item_byte_size);
1207 break;
1208
1209 case eFormatUnsigned:
1210 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1211 if (!success)
1212 {
1213 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1214 result.SetStatus(eReturnStatusFailed);
1215 return false;
1216 }
1217 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1218 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001219 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 +00001220 result.SetStatus(eReturnStatusFailed);
1221 return false;
1222 }
1223 buffer.PutMaxHex64 (uval64, item_byte_size);
1224 break;
1225
1226 case eFormatOctal:
1227 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1228 if (!success)
1229 {
1230 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1231 result.SetStatus(eReturnStatusFailed);
1232 return false;
1233 }
1234 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1235 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001236 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 +00001237 result.SetStatus(eReturnStatusFailed);
1238 return false;
1239 }
1240 buffer.PutMaxHex64 (uval64, item_byte_size);
1241 break;
1242 }
1243 }
1244
1245 if (!buffer.GetString().empty())
1246 {
1247 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001248 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001249 return true;
1250 else
1251 {
1252 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1253 result.SetStatus(eReturnStatusFailed);
1254 return false;
1255 }
1256 }
1257 return true;
1258 }
1259
Greg Claytona42880a2011-10-25 06:44:01 +00001260 OptionGroupOptions m_option_group;
1261 OptionGroupFormat m_format_options;
1262 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001263};
1264
Chris Lattner24943d22010-06-08 16:52:24 +00001265
1266//-------------------------------------------------------------------------
1267// CommandObjectMemory
1268//-------------------------------------------------------------------------
1269
Greg Clayton63094e02010-06-23 01:19:29 +00001270CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001271 CommandObjectMultiword (interpreter,
1272 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001273 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001274 "memory <subcommand> [<subcommand-options>]")
1275{
Greg Clayton238c0a12010-09-18 01:14:36 +00001276 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1277 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001278}
1279
1280CommandObjectMemory::~CommandObjectMemory ()
1281{
1282}