blob: 71522308389d1801442be2d8e78960f8ba63c6a2 [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."},
Sean Callanan8a6f3e92012-04-28 01:27:38 +000040 { LLDB_OPT_SET_3, true , "view-as" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
41 { 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 +000042};
43
44
45
46class OptionGroupReadMemory : public OptionGroup
47{
48public:
49
50 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000051 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000052 m_output_as_binary (false),
53 m_view_as_type()
54 {
55 }
56
57 virtual
58 ~OptionGroupReadMemory ()
59 {
60 }
61
62
63 virtual uint32_t
64 GetNumDefinitions ()
65 {
66 return sizeof (g_option_table) / sizeof (OptionDefinition);
67 }
68
69 virtual const OptionDefinition*
70 GetDefinitions ()
71 {
72 return g_option_table;
73 }
74
75 virtual Error
76 SetOptionValue (CommandInterpreter &interpreter,
77 uint32_t option_idx,
78 const char *option_arg)
79 {
80 Error error;
81 char short_option = (char) g_option_table[option_idx].short_option;
82
83 switch (short_option)
84 {
85 case 'l':
86 error = m_num_per_line.SetValueFromCString (option_arg);
87 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000088 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000089 break;
Greg Claytona42880a2011-10-25 06:44:01 +000090
Greg Clayton57b3c6b2011-04-27 22:04:39 +000091 case 'b':
92 m_output_as_binary = true;
93 break;
94
95 case 't':
96 error = m_view_as_type.SetValueFromCString (option_arg);
97 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +000098
99 case 'r':
100 m_force = true;
101 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000102
103 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000104 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000105 break;
106 }
107 return error;
108 }
109
110 virtual void
111 OptionParsingStarting (CommandInterpreter &interpreter)
112 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000113 m_num_per_line.Clear();
114 m_output_as_binary = false;
115 m_view_as_type.Clear();
116 }
117
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000118 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000119 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000120 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000121 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000122 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
123 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000124 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000125 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000126 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000127
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000128 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000129 {
130 default:
131 break;
132
133 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000134 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000135 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000136 if (!num_per_line_option_set)
137 m_num_per_line = 1;
138 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000139 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000140 break;
141
142 case eFormatCString:
143 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000144
145 case eFormatInstruction:
146 if (count_option_set)
147 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize() * format_options.GetCountValue().GetCurrentValue();
148 m_num_per_line = 1;
149 break;
150
151 case eFormatAddressInfo:
152 if (!byte_size_option_set)
153 byte_size_value = target->GetArchitecture().GetAddressByteSize();
154 m_num_per_line = 1;
155 if (!count_option_set)
156 format_options.GetCountValue() = 8;
157 break;
158
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000159 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000160 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000161 if (!num_per_line_option_set)
162 m_num_per_line = 4;
163 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000164 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000165 break;
166
167 case eFormatBinary:
168 case eFormatFloat:
169 case eFormatOctal:
170 case eFormatDecimal:
171 case eFormatEnum:
172 case eFormatUnicode16:
173 case eFormatUnicode32:
174 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000175 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000176 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000177 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000178 if (!num_per_line_option_set)
179 m_num_per_line = 1;
180 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000181 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000182 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000183
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000184 case eFormatBytes:
185 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000186 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000187 {
Greg Claytona42880a2011-10-25 06:44:01 +0000188 if (byte_size_value > 1)
Johnny Chenbf9ba592012-03-06 01:17:59 +0000189 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %llu\n"
190 "\tconsider using a different display format or don't specify the byte size",
191 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000192 }
193 else
Greg Claytona42880a2011-10-25 06:44:01 +0000194 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000195 if (!num_per_line_option_set)
196 m_num_per_line = 16;
197 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000198 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000199 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000200 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000201 case eFormatChar:
202 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000203 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000204 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000205 if (!num_per_line_option_set)
206 m_num_per_line = 32;
207 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000208 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000209 break;
210 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000211 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000212 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000213 if (!num_per_line_option_set)
214 m_num_per_line = 1;
215 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000216 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000217 break;
218 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000220 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000221 if (!num_per_line_option_set)
222 {
Greg Claytona42880a2011-10-25 06:44:01 +0000223 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000224 {
225 case 1:
226 case 2:
227 m_num_per_line = 8;
228 break;
229 case 4:
230 m_num_per_line = 4;
231 break;
232 case 8:
233 m_num_per_line = 2;
234 break;
235 default:
236 m_num_per_line = 1;
237 break;
238 }
239 }
240 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000241 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000242 break;
243
244 case eFormatVectorOfChar:
245 case eFormatVectorOfSInt8:
246 case eFormatVectorOfUInt8:
247 case eFormatVectorOfSInt16:
248 case eFormatVectorOfUInt16:
249 case eFormatVectorOfSInt32:
250 case eFormatVectorOfUInt32:
251 case eFormatVectorOfSInt64:
252 case eFormatVectorOfUInt64:
253 case eFormatVectorOfFloat32:
254 case eFormatVectorOfFloat64:
255 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000256 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000257 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000258 if (!num_per_line_option_set)
259 m_num_per_line = 1;
260 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000261 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000262 break;
263 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000264 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000265 }
266
Greg Clayton902b5be2011-10-26 04:32:38 +0000267 bool
268 AnyOptionWasSet () const
269 {
270 return m_num_per_line.OptionWasSet() ||
271 m_output_as_binary ||
272 m_view_as_type.OptionWasSet();
273 }
274
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000275 OptionValueUInt64 m_num_per_line;
276 bool m_output_as_binary;
277 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000278 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000279};
280
281
282
Chris Lattner24943d22010-06-08 16:52:24 +0000283//----------------------------------------------------------------------
284// Read memory from the inferior process
285//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000286class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000287{
288public:
289
Greg Clayton238c0a12010-09-18 01:14:36 +0000290 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000291 CommandObjectParsed (interpreter,
292 "memory read",
293 "Read from the memory of the process being debugged.",
294 NULL,
295 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000296 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000297 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000298 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000299 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000300 m_varobj_options(),
301 m_next_addr(LLDB_INVALID_ADDRESS),
302 m_prev_byte_size(0),
303 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
304 m_prev_memory_options (),
305 m_prev_outfile_options (),
306 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000307 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000308 CommandArgumentEntry arg1;
309 CommandArgumentEntry arg2;
310 CommandArgumentData start_addr_arg;
311 CommandArgumentData end_addr_arg;
312
313 // Define the first (and only) variant of this arg.
314 start_addr_arg.arg_type = eArgTypeStartAddress;
315 start_addr_arg.arg_repetition = eArgRepeatPlain;
316
317 // There is only one variant this argument could be; put it into the argument entry.
318 arg1.push_back (start_addr_arg);
319
320 // Define the first (and only) variant of this arg.
321 end_addr_arg.arg_type = eArgTypeEndAddress;
322 end_addr_arg.arg_repetition = eArgRepeatOptional;
323
324 // There is only one variant this argument could be; put it into the argument entry.
325 arg2.push_back (end_addr_arg);
326
327 // Push the data for the first argument into the m_arguments vector.
328 m_arguments.push_back (arg1);
329 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000330
Greg Claytona42880a2011-10-25 06:44:01 +0000331 // Add the "--format" and "--count" options to group 1 and 3
332 m_option_group.Append (&m_format_options,
333 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000334 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000335 m_option_group.Append (&m_format_options,
336 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000337 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000338 // Add the "--size" option to group 1 and 2
339 m_option_group.Append (&m_format_options,
340 OptionGroupFormat::OPTION_GROUP_SIZE,
341 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000342 m_option_group.Append (&m_memory_options);
343 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 +0000344 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000345 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000346 }
347
348 virtual
349 ~CommandObjectMemoryRead ()
350 {
351 }
352
353 Options *
354 GetOptions ()
355 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000356 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000357 }
358
Greg Clayton902b5be2011-10-26 04:32:38 +0000359 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
360 {
361 return m_cmd_name.c_str();
362 }
363
Jim Inghamda26bd22012-06-08 21:56:10 +0000364protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000365 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000366 DoExecute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000367 CommandReturnObject &result)
368 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000369 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000370 Target *target = exe_ctx.GetTargetPtr();
371 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000372 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000373 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000374 result.SetStatus(eReturnStatusFailed);
375 return false;
376 }
377 const size_t argc = command.GetArgumentCount();
378
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000379
Greg Clayton902b5be2011-10-26 04:32:38 +0000380 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000381 {
382 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
383 result.SetStatus(eReturnStatusFailed);
384 return false;
385 }
386
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000387 ClangASTType clang_ast_type;
388 Error error;
389
390 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000391 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
392 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000393 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000394 // We are viewing memory as a type
395 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000396 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000397 TypeList type_list;
398 uint32_t reference_count = 0;
399 uint32_t pointer_count = 0;
400 size_t idx;
Sean Callananddb2ece2012-07-10 21:24:26 +0000401
402#define ALL_KEYWORDS \
403 KEYWORD("const") \
404 KEYWORD("volatile") \
405 KEYWORD("restrict") \
406 KEYWORD("struct") \
407 KEYWORD("class") \
408 KEYWORD("union")
409
410#define KEYWORD(s) s,
411 static const char *g_keywords[] =
412 {
413 ALL_KEYWORDS
414 };
415#undef KEYWORD
416
417#define KEYWORD(s) (sizeof(s) - 1),
418 static const int g_keyword_lengths[] =
419 {
420 ALL_KEYWORDS
421 };
422#undef KEYWORD
423
424#undef ALL_KEYWORDS
425
426 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000427 std::string type_str(view_as_type_cstr);
428
429 // Remove all instances of g_keywords that are followed by spaces
430 for (size_t i = 0; i < g_num_keywords; ++i)
431 {
432 const char *keyword = g_keywords[i];
Sean Callananddb2ece2012-07-10 21:24:26 +0000433 int keyword_len = g_keyword_lengths[i];
434
435 idx = 0;
436 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000437 {
438 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callananddb2ece2012-07-10 21:24:26 +0000439 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000440 type_str.erase(idx, keyword_len+1);
Sean Callananddb2ece2012-07-10 21:24:26 +0000441 idx = 0;
442 }
443 else
444 {
445 idx += keyword_len;
446 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000447 }
448 }
449 bool done = type_str.empty();
450 //
451 idx = type_str.find_first_not_of (" \t");
452 if (idx > 0 && idx != std::string::npos)
453 type_str.erase (0, idx);
454 while (!done)
455 {
456 // Strip trailing spaces
457 if (type_str.empty())
458 done = true;
459 else
460 {
461 switch (type_str[type_str.size()-1])
462 {
463 case '*':
464 ++pointer_count;
465 // fall through...
466 case ' ':
467 case '\t':
468 type_str.erase(type_str.size()-1);
469 break;
470
471 case '&':
472 if (reference_count == 0)
473 {
474 reference_count = 1;
475 type_str.erase(type_str.size()-1);
476 }
477 else
478 {
479 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
480 result.SetStatus(eReturnStatusFailed);
481 return false;
482 }
483 break;
484
485 default:
486 done = true;
487 break;
488 }
489 }
490 }
491
492 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000493 StackFrame *frame = exe_ctx.GetFramePtr();
494 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000495 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000496 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000497 if (sc.module_sp)
498 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000499 sc.module_sp->FindTypes (sc,
500 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000501 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000502 1,
503 type_list);
504 }
505 }
506 if (type_list.GetSize() == 0)
507 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000508 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000509 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000510 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000511 1,
512 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000513 }
514
515 if (type_list.GetSize() == 0)
516 {
517 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
518 lookup_type_name.GetCString(),
519 view_as_type_cstr);
520 result.SetStatus(eReturnStatusFailed);
521 return false;
522 }
523
524 TypeSP type_sp (type_list.GetTypeAtIndex(0));
525 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
526
527 while (pointer_count > 0)
528 {
529 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
530 if (pointer_type)
531 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
532 else
533 {
534 result.AppendError ("unable make a pointer type\n");
535 result.SetStatus(eReturnStatusFailed);
536 return false;
537 }
538 --pointer_count;
539 }
540
Greg Claytona42880a2011-10-25 06:44:01 +0000541 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000542
Greg Claytona42880a2011-10-25 06:44:01 +0000543 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000544 {
545 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
546 view_as_type_cstr);
547 result.SetStatus(eReturnStatusFailed);
548 return false;
549 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000550
Greg Claytona42880a2011-10-25 06:44:01 +0000551 if (!m_format_options.GetCountValue().OptionWasSet())
552 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000553 }
554 else
555 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000556 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000557 }
558
559 // Look for invalid combinations of settings
560 if (error.Fail())
561 {
562 result.AppendErrorWithFormat("%s", error.AsCString());
563 result.SetStatus(eReturnStatusFailed);
564 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000565 }
566
Greg Clayton902b5be2011-10-26 04:32:38 +0000567 lldb::addr_t addr;
568 size_t total_byte_size = 0;
569 if (argc == 0)
570 {
571 // Use the last address and byte size and all options as they were
572 // if no options have been set
573 addr = m_next_addr;
574 total_byte_size = m_prev_byte_size;
575 if (!m_format_options.AnyOptionWasSet() &&
576 !m_memory_options.AnyOptionWasSet() &&
577 !m_outfile_options.AnyOptionWasSet() &&
578 !m_varobj_options.AnyOptionWasSet())
579 {
580 m_format_options = m_prev_format_options;
581 m_memory_options = m_prev_memory_options;
582 m_outfile_options = m_prev_outfile_options;
583 m_varobj_options = m_prev_varobj_options;
584 }
585 }
586
Greg Claytona42880a2011-10-25 06:44:01 +0000587 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
588 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000589 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000590
Chris Lattner24943d22010-06-08 16:52:24 +0000591 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000592 {
593 total_byte_size = item_count * item_byte_size;
594 if (total_byte_size == 0)
595 total_byte_size = 32;
596 }
Chris Lattner24943d22010-06-08 16:52:24 +0000597
Greg Clayton902b5be2011-10-26 04:32:38 +0000598 if (argc > 0)
599 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000600
601 if (addr == LLDB_INVALID_ADDRESS)
602 {
603 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
604 result.SetStatus(eReturnStatusFailed);
605 return false;
606 }
607
608 if (argc == 2)
609 {
610 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
611 if (end_addr == LLDB_INVALID_ADDRESS)
612 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000613 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000614 result.SetStatus(eReturnStatusFailed);
615 return false;
616 }
617 else if (end_addr <= addr)
618 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000619 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 +0000620 result.SetStatus(eReturnStatusFailed);
621 return false;
622 }
Greg Claytona42880a2011-10-25 06:44:01 +0000623 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000624 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000625 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 +0000626 result.SetStatus(eReturnStatusFailed);
627 return false;
628 }
629
630 total_byte_size = end_addr - addr;
631 item_count = total_byte_size / item_byte_size;
632 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000633
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000634 if (total_byte_size > 1024 && !m_memory_options.m_force)
635 {
636 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
637 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
638 return false;
639 }
640
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000641 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000642 size_t bytes_read = 0;
643 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000644 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000645 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000646 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000647 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000648 if (bytes_read == 0)
649 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000650 const char *error_cstr = error.AsCString();
651 if (error_cstr && error_cstr[0])
652 {
653 result.AppendError(error_cstr);
654 }
655 else
656 {
657 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
658 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000659 result.SetStatus(eReturnStatusFailed);
660 return false;
661 }
662
663 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000664 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 +0000665 else
666 {
667 m_next_addr = addr + bytes_read;
668 m_prev_byte_size = bytes_read;
669 m_prev_format_options = m_format_options;
670 m_prev_memory_options = m_memory_options;
671 m_prev_outfile_options = m_outfile_options;
672 m_prev_varobj_options = m_varobj_options;
673 }
Chris Lattner24943d22010-06-08 16:52:24 +0000674 }
675
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000676 StreamFile outfile_stream;
677 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000678 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
679 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000680 {
681 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000682 outfile_spec.GetPath (path, sizeof(path));
683
684 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
685 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
686 if (append)
687 open_options |= File::eOpenOptionAppend;
688
689 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000690 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000691 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000692 {
693 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
694 if (bytes_written > 0)
695 {
696 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
697 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000698 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000699 path);
700 return true;
701 }
702 else
703 {
704 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
705 result.SetStatus(eReturnStatusFailed);
706 return false;
707 }
708 }
709 else
710 {
711 // We are going to write ASCII to the file just point the
712 // output_stream to our outfile_stream...
713 output_stream = &outfile_stream;
714 }
715 }
716 else
717 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000718 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000719 result.SetStatus(eReturnStatusFailed);
720 return false;
721 }
722 }
723 else
724 {
725 output_stream = &result.GetOutputStream();
726 }
727
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000728
Greg Clayton24a6bd92011-10-27 17:55:14 +0000729 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000730 if (clang_ast_type.GetOpaqueQualType())
731 {
732 for (uint32_t i = 0; i<item_count; ++i)
733 {
734 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000735 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000736 StreamString name_strm;
737 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000738 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000739 name_strm.GetString().c_str(),
740 address,
741 clang_ast_type));
742 if (valobj_sp)
743 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000744 if (format != eFormatDefault)
745 valobj_sp->SetFormat (format);
746
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000747 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000748
Enrico Granata3069c622012-03-01 04:24:26 +0000749 ValueObject::DumpValueObjectOptions options;
750 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
751 .SetMaximumDepth(m_varobj_options.max_depth)
752 .SetShowLocation(m_varobj_options.show_location)
753 .SetShowTypes(m_varobj_options.show_types)
754 .SetUseObjectiveC(m_varobj_options.use_objc)
755 .SetScopeChecked(scope_already_checked)
756 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000757 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000758 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
759 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
760 .SetFormat(format)
761 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000762 ValueObject::DumpValueObject (*output_stream,
763 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000764 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000765 }
766 else
767 {
768 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
769 view_as_type_cstr,
770 name_strm.GetString().c_str());
771 result.SetStatus(eReturnStatusFailed);
772 return false;
773 }
774 }
775 return true;
776 }
777
778 result.SetStatus(eReturnStatusSuccessFinishResult);
779 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000780 target->GetArchitecture().GetByteOrder(),
781 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000782
783
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000784 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000785 uint32_t bytes_dumped = data.Dump (output_stream,
786 0,
787 m_format_options.GetFormat(),
788 item_byte_size,
789 item_count,
790 num_per_line,
791 addr,
792 0,
793 0,
794 exe_scope);
795 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000796 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000797 return true;
798 }
799
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000800 OptionGroupOptions m_option_group;
801 OptionGroupFormat m_format_options;
802 OptionGroupReadMemory m_memory_options;
803 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000804 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000805 lldb::addr_t m_next_addr;
806 lldb::addr_t m_prev_byte_size;
807 OptionGroupFormat m_prev_format_options;
808 OptionGroupReadMemory m_prev_memory_options;
809 OptionGroupOutputFile m_prev_outfile_options;
810 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000811};
812
Greg Claytona42880a2011-10-25 06:44:01 +0000813
814OptionDefinition
815g_memory_write_option_table[] =
816{
817{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
818{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
819};
820
821
Chris Lattner24943d22010-06-08 16:52:24 +0000822//----------------------------------------------------------------------
823// Write memory to the inferior process
824//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000825class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000826{
827public:
828
Greg Claytona42880a2011-10-25 06:44:01 +0000829 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000830 {
831 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000832 OptionGroupWriteMemory () :
833 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000834 {
Chris Lattner24943d22010-06-08 16:52:24 +0000835 }
836
837 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000838 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000839 {
840 }
841
Greg Claytona42880a2011-10-25 06:44:01 +0000842 virtual uint32_t
843 GetNumDefinitions ()
844 {
845 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
846 }
847
848 virtual const OptionDefinition*
849 GetDefinitions ()
850 {
851 return g_memory_write_option_table;
852 }
853
Chris Lattner24943d22010-06-08 16:52:24 +0000854 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000855 SetOptionValue (CommandInterpreter &interpreter,
856 uint32_t option_idx,
857 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000858 {
859 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000860 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
861
Chris Lattner24943d22010-06-08 16:52:24 +0000862 switch (short_option)
863 {
Greg Claytona42880a2011-10-25 06:44:01 +0000864 case 'i':
865 m_infile.SetFile (option_arg, true);
866 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000867 {
Greg Claytona42880a2011-10-25 06:44:01 +0000868 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000869 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000870 }
Greg Claytona42880a2011-10-25 06:44:01 +0000871 break;
872
873 case 'o':
874 {
875 bool success;
876 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
877 if (!success)
878 {
Greg Clayton9c236732011-10-26 00:56:27 +0000879 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000880 }
881 }
882 break;
883
884 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000885 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000886 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000887 }
888 return error;
889 }
Greg Claytona42880a2011-10-25 06:44:01 +0000890
891 virtual void
892 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000893 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000894 m_infile.Clear();
895 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000896 }
897
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000898 FileSpec m_infile;
899 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000900 };
901
Greg Clayton238c0a12010-09-18 01:14:36 +0000902 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000903 CommandObjectParsed (interpreter,
904 "memory write",
905 "Write to the memory of the process being debugged.",
906 NULL,
907 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000908 m_option_group (interpreter),
909 m_format_options (eFormatBytes, 1, UINT64_MAX),
910 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000911 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000912 CommandArgumentEntry arg1;
913 CommandArgumentEntry arg2;
914 CommandArgumentData addr_arg;
915 CommandArgumentData value_arg;
916
917 // Define the first (and only) variant of this arg.
918 addr_arg.arg_type = eArgTypeAddress;
919 addr_arg.arg_repetition = eArgRepeatPlain;
920
921 // There is only one variant this argument could be; put it into the argument entry.
922 arg1.push_back (addr_arg);
923
924 // Define the first (and only) variant of this arg.
925 value_arg.arg_type = eArgTypeValue;
926 value_arg.arg_repetition = eArgRepeatPlus;
927
928 // There is only one variant this argument could be; put it into the argument entry.
929 arg2.push_back (value_arg);
930
931 // Push the data for the first argument into the m_arguments vector.
932 m_arguments.push_back (arg1);
933 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000934
935 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
936 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
937 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
938 m_option_group.Finalize();
939
Chris Lattner24943d22010-06-08 16:52:24 +0000940 }
941
942 virtual
943 ~CommandObjectMemoryWrite ()
944 {
945 }
946
947 Options *
948 GetOptions ()
949 {
Greg Claytona42880a2011-10-25 06:44:01 +0000950 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000951 }
952
953 bool
954 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
955 {
956 if (total_byte_size > 8)
957 return false;
958
959 if (total_byte_size == 8)
960 return true;
961
962 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
963 return uval64 <= max;
964 }
965
966 bool
967 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
968 {
969 if (total_byte_size > 8)
970 return false;
971
972 if (total_byte_size == 8)
973 return true;
974
975 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
976 const int64_t min = ~(max);
977 return min <= sval64 && sval64 <= max;
978 }
979
Jim Inghamda26bd22012-06-08 21:56:10 +0000980protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000981 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000982 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000983 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000984 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000985 if (process == NULL)
986 {
987 result.AppendError("need a process to read memory");
988 result.SetStatus(eReturnStatusFailed);
989 return false;
990 }
991
992 const size_t argc = command.GetArgumentCount();
993
Greg Claytona42880a2011-10-25 06:44:01 +0000994 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000995 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000996 if (argc < 1)
997 {
998 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
999 result.SetStatus(eReturnStatusFailed);
1000 return false;
1001 }
1002 }
1003 else if (argc < 2)
1004 {
1005 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 +00001006 result.SetStatus(eReturnStatusFailed);
1007 return false;
1008 }
1009
Chris Lattner24943d22010-06-08 16:52:24 +00001010 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001011 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1012 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001013
Greg Claytona42880a2011-10-25 06:44:01 +00001014 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1015 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001016
Chris Lattner24943d22010-06-08 16:52:24 +00001017 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1018
1019 if (addr == LLDB_INVALID_ADDRESS)
1020 {
1021 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1022 result.SetStatus(eReturnStatusFailed);
1023 return false;
1024 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001025
Greg Claytona42880a2011-10-25 06:44:01 +00001026 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001027 {
1028 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001029 if (item_byte_size > 0)
1030 length = item_byte_size;
1031 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001032 if (data_sp)
1033 {
1034 length = data_sp->GetByteSize();
1035 if (length > 0)
1036 {
1037 Error error;
1038 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1039
1040 if (bytes_written == length)
1041 {
1042 // All bytes written
1043 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1044 result.SetStatus(eReturnStatusSuccessFinishResult);
1045 }
1046 else if (bytes_written > 0)
1047 {
1048 // Some byte written
1049 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1050 result.SetStatus(eReturnStatusSuccessFinishResult);
1051 }
1052 else
1053 {
1054 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1055 result.SetStatus(eReturnStatusFailed);
1056 }
1057 }
1058 }
1059 else
1060 {
1061 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1062 result.SetStatus(eReturnStatusFailed);
1063 }
1064 return result.Succeeded();
1065 }
Greg Claytona42880a2011-10-25 06:44:01 +00001066 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001067 {
Greg Claytona42880a2011-10-25 06:44:01 +00001068 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001069 item_byte_size = buffer.GetAddressByteSize();
1070 else
1071 item_byte_size = 1;
1072 }
1073
Chris Lattner24943d22010-06-08 16:52:24 +00001074 command.Shift(); // shift off the address argument
1075 uint64_t uval64;
1076 int64_t sval64;
1077 bool success = false;
1078 const uint32_t num_value_args = command.GetArgumentCount();
1079 uint32_t i;
1080 for (i=0; i<num_value_args; ++i)
1081 {
1082 const char *value_str = command.GetArgumentAtIndex(i);
1083
Greg Claytona42880a2011-10-25 06:44:01 +00001084 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001085 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001086 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001087 case eFormatFloat: // TODO: add support for floats soon
1088 case eFormatCharPrintable:
1089 case eFormatBytesWithASCII:
1090 case eFormatComplex:
1091 case eFormatEnum:
1092 case eFormatUnicode16:
1093 case eFormatUnicode32:
1094 case eFormatVectorOfChar:
1095 case eFormatVectorOfSInt8:
1096 case eFormatVectorOfUInt8:
1097 case eFormatVectorOfSInt16:
1098 case eFormatVectorOfUInt16:
1099 case eFormatVectorOfSInt32:
1100 case eFormatVectorOfUInt32:
1101 case eFormatVectorOfSInt64:
1102 case eFormatVectorOfUInt64:
1103 case eFormatVectorOfFloat32:
1104 case eFormatVectorOfFloat64:
1105 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001106 case eFormatOSType:
1107 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001108 case eFormatAddressInfo:
1109 case eFormatHexFloat:
1110 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001111 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001112 result.AppendError("unsupported format for writing memory");
1113 result.SetStatus(eReturnStatusFailed);
1114 return false;
1115
1116 case eFormatDefault:
1117 case eFormatBytes:
1118 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001119 case eFormatPointer:
1120
Chris Lattner24943d22010-06-08 16:52:24 +00001121 // Decode hex bytes
1122 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1123 if (!success)
1124 {
1125 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1126 result.SetStatus(eReturnStatusFailed);
1127 return false;
1128 }
1129 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1130 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001131 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 +00001132 result.SetStatus(eReturnStatusFailed);
1133 return false;
1134 }
1135 buffer.PutMaxHex64 (uval64, item_byte_size);
1136 break;
1137
1138 case eFormatBoolean:
1139 uval64 = Args::StringToBoolean(value_str, false, &success);
1140 if (!success)
1141 {
1142 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1143 result.SetStatus(eReturnStatusFailed);
1144 return false;
1145 }
1146 buffer.PutMaxHex64 (uval64, item_byte_size);
1147 break;
1148
1149 case eFormatBinary:
1150 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1151 if (!success)
1152 {
1153 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1154 result.SetStatus(eReturnStatusFailed);
1155 return false;
1156 }
1157 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1158 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001159 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 +00001160 result.SetStatus(eReturnStatusFailed);
1161 return false;
1162 }
1163 buffer.PutMaxHex64 (uval64, item_byte_size);
1164 break;
1165
Greg Clayton307fa072011-06-17 23:50:44 +00001166 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001167 case eFormatChar:
1168 case eFormatCString:
1169 if (value_str[0])
1170 {
1171 size_t len = strlen (value_str);
1172 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001173 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001174 ++len;
1175 Error error;
1176 if (process->WriteMemory (addr, value_str, len, error) == len)
1177 {
1178 addr += len;
1179 }
1180 else
1181 {
1182 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1183 result.SetStatus(eReturnStatusFailed);
1184 return false;
1185 }
1186 }
1187 break;
1188
1189 case eFormatDecimal:
1190 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1191 if (!success)
1192 {
1193 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1198 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001199 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 +00001200 result.SetStatus(eReturnStatusFailed);
1201 return false;
1202 }
1203 buffer.PutMaxHex64 (sval64, item_byte_size);
1204 break;
1205
1206 case eFormatUnsigned:
1207 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1208 if (!success)
1209 {
1210 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1211 result.SetStatus(eReturnStatusFailed);
1212 return false;
1213 }
1214 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1215 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001216 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 +00001217 result.SetStatus(eReturnStatusFailed);
1218 return false;
1219 }
1220 buffer.PutMaxHex64 (uval64, item_byte_size);
1221 break;
1222
1223 case eFormatOctal:
1224 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1225 if (!success)
1226 {
1227 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1228 result.SetStatus(eReturnStatusFailed);
1229 return false;
1230 }
1231 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1232 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001233 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 +00001234 result.SetStatus(eReturnStatusFailed);
1235 return false;
1236 }
1237 buffer.PutMaxHex64 (uval64, item_byte_size);
1238 break;
1239 }
1240 }
1241
1242 if (!buffer.GetString().empty())
1243 {
1244 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001245 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001246 return true;
1247 else
1248 {
1249 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1250 result.SetStatus(eReturnStatusFailed);
1251 return false;
1252 }
1253 }
1254 return true;
1255 }
1256
Greg Claytona42880a2011-10-25 06:44:01 +00001257 OptionGroupOptions m_option_group;
1258 OptionGroupFormat m_format_options;
1259 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001260};
1261
Chris Lattner24943d22010-06-08 16:52:24 +00001262
1263//-------------------------------------------------------------------------
1264// CommandObjectMemory
1265//-------------------------------------------------------------------------
1266
Greg Clayton63094e02010-06-23 01:19:29 +00001267CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001268 CommandObjectMultiword (interpreter,
1269 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001270 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001271 "memory <subcommand> [<subcommand-options>]")
1272{
Greg Clayton238c0a12010-09-18 01:14:36 +00001273 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1274 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001275}
1276
1277CommandObjectMemory::~CommandObjectMemory ()
1278{
1279}