blob: 61bf1490c62fc8edcab9df81335d060f81ee973d [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;
401 static const char *g_keywords[] = { "const", "volatile", "restrict", "struct", "class", "union"};
402 static size_t g_num_keywords = sizeof(g_keywords)/sizeof(const char *);
403 std::string type_str(view_as_type_cstr);
404
405 // Remove all instances of g_keywords that are followed by spaces
406 for (size_t i = 0; i < g_num_keywords; ++i)
407 {
408 const char *keyword = g_keywords[i];
409 int keyword_len = ::strlen (keyword);
410 while ((idx = type_str.find (keyword)) != std::string::npos)
411 {
412 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
413 type_str.erase(idx, keyword_len+1);
414 }
415 }
416 bool done = type_str.empty();
417 //
418 idx = type_str.find_first_not_of (" \t");
419 if (idx > 0 && idx != std::string::npos)
420 type_str.erase (0, idx);
421 while (!done)
422 {
423 // Strip trailing spaces
424 if (type_str.empty())
425 done = true;
426 else
427 {
428 switch (type_str[type_str.size()-1])
429 {
430 case '*':
431 ++pointer_count;
432 // fall through...
433 case ' ':
434 case '\t':
435 type_str.erase(type_str.size()-1);
436 break;
437
438 case '&':
439 if (reference_count == 0)
440 {
441 reference_count = 1;
442 type_str.erase(type_str.size()-1);
443 }
444 else
445 {
446 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
447 result.SetStatus(eReturnStatusFailed);
448 return false;
449 }
450 break;
451
452 default:
453 done = true;
454 break;
455 }
456 }
457 }
458
459 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000460 StackFrame *frame = exe_ctx.GetFramePtr();
461 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000462 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000463 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000464 if (sc.module_sp)
465 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000466 sc.module_sp->FindTypes (sc,
467 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000468 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000469 1,
470 type_list);
471 }
472 }
473 if (type_list.GetSize() == 0)
474 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000475 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000476 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000477 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000478 1,
479 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000480 }
481
482 if (type_list.GetSize() == 0)
483 {
484 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
485 lookup_type_name.GetCString(),
486 view_as_type_cstr);
487 result.SetStatus(eReturnStatusFailed);
488 return false;
489 }
490
491 TypeSP type_sp (type_list.GetTypeAtIndex(0));
492 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
493
494 while (pointer_count > 0)
495 {
496 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
497 if (pointer_type)
498 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
499 else
500 {
501 result.AppendError ("unable make a pointer type\n");
502 result.SetStatus(eReturnStatusFailed);
503 return false;
504 }
505 --pointer_count;
506 }
507
Greg Claytona42880a2011-10-25 06:44:01 +0000508 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000509
Greg Claytona42880a2011-10-25 06:44:01 +0000510 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000511 {
512 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
513 view_as_type_cstr);
514 result.SetStatus(eReturnStatusFailed);
515 return false;
516 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000517
Greg Claytona42880a2011-10-25 06:44:01 +0000518 if (!m_format_options.GetCountValue().OptionWasSet())
519 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000520 }
521 else
522 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000523 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000524 }
525
526 // Look for invalid combinations of settings
527 if (error.Fail())
528 {
529 result.AppendErrorWithFormat("%s", error.AsCString());
530 result.SetStatus(eReturnStatusFailed);
531 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000532 }
533
Greg Clayton902b5be2011-10-26 04:32:38 +0000534 lldb::addr_t addr;
535 size_t total_byte_size = 0;
536 if (argc == 0)
537 {
538 // Use the last address and byte size and all options as they were
539 // if no options have been set
540 addr = m_next_addr;
541 total_byte_size = m_prev_byte_size;
542 if (!m_format_options.AnyOptionWasSet() &&
543 !m_memory_options.AnyOptionWasSet() &&
544 !m_outfile_options.AnyOptionWasSet() &&
545 !m_varobj_options.AnyOptionWasSet())
546 {
547 m_format_options = m_prev_format_options;
548 m_memory_options = m_prev_memory_options;
549 m_outfile_options = m_prev_outfile_options;
550 m_varobj_options = m_prev_varobj_options;
551 }
552 }
553
Greg Claytona42880a2011-10-25 06:44:01 +0000554 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
555 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000556 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000557
Chris Lattner24943d22010-06-08 16:52:24 +0000558 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000559 {
560 total_byte_size = item_count * item_byte_size;
561 if (total_byte_size == 0)
562 total_byte_size = 32;
563 }
Chris Lattner24943d22010-06-08 16:52:24 +0000564
Greg Clayton902b5be2011-10-26 04:32:38 +0000565 if (argc > 0)
566 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000567
568 if (addr == LLDB_INVALID_ADDRESS)
569 {
570 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
571 result.SetStatus(eReturnStatusFailed);
572 return false;
573 }
574
575 if (argc == 2)
576 {
577 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
578 if (end_addr == LLDB_INVALID_ADDRESS)
579 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000580 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000581 result.SetStatus(eReturnStatusFailed);
582 return false;
583 }
584 else if (end_addr <= addr)
585 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000586 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 +0000587 result.SetStatus(eReturnStatusFailed);
588 return false;
589 }
Greg Claytona42880a2011-10-25 06:44:01 +0000590 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000591 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000592 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 +0000593 result.SetStatus(eReturnStatusFailed);
594 return false;
595 }
596
597 total_byte_size = end_addr - addr;
598 item_count = total_byte_size / item_byte_size;
599 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000600
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000601 if (total_byte_size > 1024 && !m_memory_options.m_force)
602 {
603 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
604 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
605 return false;
606 }
607
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000608 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000609 size_t bytes_read = 0;
610 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000611 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000612 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000613 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000614 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000615 if (bytes_read == 0)
616 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000617 const char *error_cstr = error.AsCString();
618 if (error_cstr && error_cstr[0])
619 {
620 result.AppendError(error_cstr);
621 }
622 else
623 {
624 result.AppendErrorWithFormat("failed to read memory from 0x%llx.\n", addr);
625 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000626 result.SetStatus(eReturnStatusFailed);
627 return false;
628 }
629
630 if (bytes_read < total_byte_size)
Jason Molenda7e5fa7f2011-09-20 21:44:10 +0000631 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 +0000632 else
633 {
634 m_next_addr = addr + bytes_read;
635 m_prev_byte_size = bytes_read;
636 m_prev_format_options = m_format_options;
637 m_prev_memory_options = m_memory_options;
638 m_prev_outfile_options = m_outfile_options;
639 m_prev_varobj_options = m_varobj_options;
640 }
Chris Lattner24943d22010-06-08 16:52:24 +0000641 }
642
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000643 StreamFile outfile_stream;
644 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000645 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
646 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000647 {
648 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000649 outfile_spec.GetPath (path, sizeof(path));
650
651 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
652 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
653 if (append)
654 open_options |= File::eOpenOptionAppend;
655
656 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000657 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000658 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000659 {
660 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
661 if (bytes_written > 0)
662 {
663 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
664 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000665 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000666 path);
667 return true;
668 }
669 else
670 {
671 result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
672 result.SetStatus(eReturnStatusFailed);
673 return false;
674 }
675 }
676 else
677 {
678 // We are going to write ASCII to the file just point the
679 // output_stream to our outfile_stream...
680 output_stream = &outfile_stream;
681 }
682 }
683 else
684 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000685 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000686 result.SetStatus(eReturnStatusFailed);
687 return false;
688 }
689 }
690 else
691 {
692 output_stream = &result.GetOutputStream();
693 }
694
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000695
Greg Clayton24a6bd92011-10-27 17:55:14 +0000696 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000697 if (clang_ast_type.GetOpaqueQualType())
698 {
699 for (uint32_t i = 0; i<item_count; ++i)
700 {
701 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000702 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000703 StreamString name_strm;
704 name_strm.Printf ("0x%llx", item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000705 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000706 name_strm.GetString().c_str(),
707 address,
708 clang_ast_type));
709 if (valobj_sp)
710 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000711 if (format != eFormatDefault)
712 valobj_sp->SetFormat (format);
713
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000714 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000715
Enrico Granata3069c622012-03-01 04:24:26 +0000716 ValueObject::DumpValueObjectOptions options;
717 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
718 .SetMaximumDepth(m_varobj_options.max_depth)
719 .SetShowLocation(m_varobj_options.show_location)
720 .SetShowTypes(m_varobj_options.show_types)
721 .SetUseObjectiveC(m_varobj_options.use_objc)
722 .SetScopeChecked(scope_already_checked)
723 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000724 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000725 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
726 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
727 .SetFormat(format)
728 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000729 ValueObject::DumpValueObject (*output_stream,
730 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000731 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000732 }
733 else
734 {
735 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
736 view_as_type_cstr,
737 name_strm.GetString().c_str());
738 result.SetStatus(eReturnStatusFailed);
739 return false;
740 }
741 }
742 return true;
743 }
744
745 result.SetStatus(eReturnStatusSuccessFinishResult);
746 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000747 target->GetArchitecture().GetByteOrder(),
748 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000749
750
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000751 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000752 uint32_t bytes_dumped = data.Dump (output_stream,
753 0,
754 m_format_options.GetFormat(),
755 item_byte_size,
756 item_count,
757 num_per_line,
758 addr,
759 0,
760 0,
761 exe_scope);
762 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000763 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000764 return true;
765 }
766
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000767 OptionGroupOptions m_option_group;
768 OptionGroupFormat m_format_options;
769 OptionGroupReadMemory m_memory_options;
770 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000771 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000772 lldb::addr_t m_next_addr;
773 lldb::addr_t m_prev_byte_size;
774 OptionGroupFormat m_prev_format_options;
775 OptionGroupReadMemory m_prev_memory_options;
776 OptionGroupOutputFile m_prev_outfile_options;
777 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000778};
779
Greg Claytona42880a2011-10-25 06:44:01 +0000780
781OptionDefinition
782g_memory_write_option_table[] =
783{
784{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
785{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
786};
787
788
Chris Lattner24943d22010-06-08 16:52:24 +0000789//----------------------------------------------------------------------
790// Write memory to the inferior process
791//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000792class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000793{
794public:
795
Greg Claytona42880a2011-10-25 06:44:01 +0000796 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000797 {
798 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000799 OptionGroupWriteMemory () :
800 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000801 {
Chris Lattner24943d22010-06-08 16:52:24 +0000802 }
803
804 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000805 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000806 {
807 }
808
Greg Claytona42880a2011-10-25 06:44:01 +0000809 virtual uint32_t
810 GetNumDefinitions ()
811 {
812 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
813 }
814
815 virtual const OptionDefinition*
816 GetDefinitions ()
817 {
818 return g_memory_write_option_table;
819 }
820
Chris Lattner24943d22010-06-08 16:52:24 +0000821 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000822 SetOptionValue (CommandInterpreter &interpreter,
823 uint32_t option_idx,
824 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000825 {
826 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000827 char short_option = (char) g_memory_write_option_table[option_idx].short_option;
828
Chris Lattner24943d22010-06-08 16:52:24 +0000829 switch (short_option)
830 {
Greg Claytona42880a2011-10-25 06:44:01 +0000831 case 'i':
832 m_infile.SetFile (option_arg, true);
833 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000834 {
Greg Claytona42880a2011-10-25 06:44:01 +0000835 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000836 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000837 }
Greg Claytona42880a2011-10-25 06:44:01 +0000838 break;
839
840 case 'o':
841 {
842 bool success;
843 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
844 if (!success)
845 {
Greg Clayton9c236732011-10-26 00:56:27 +0000846 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000847 }
848 }
849 break;
850
851 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000852 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000853 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000854 }
855 return error;
856 }
Greg Claytona42880a2011-10-25 06:44:01 +0000857
858 virtual void
859 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000860 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000861 m_infile.Clear();
862 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000863 }
864
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000865 FileSpec m_infile;
866 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000867 };
868
Greg Clayton238c0a12010-09-18 01:14:36 +0000869 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000870 CommandObjectParsed (interpreter,
871 "memory write",
872 "Write to the memory of the process being debugged.",
873 NULL,
874 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000875 m_option_group (interpreter),
876 m_format_options (eFormatBytes, 1, UINT64_MAX),
877 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000878 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000879 CommandArgumentEntry arg1;
880 CommandArgumentEntry arg2;
881 CommandArgumentData addr_arg;
882 CommandArgumentData value_arg;
883
884 // Define the first (and only) variant of this arg.
885 addr_arg.arg_type = eArgTypeAddress;
886 addr_arg.arg_repetition = eArgRepeatPlain;
887
888 // There is only one variant this argument could be; put it into the argument entry.
889 arg1.push_back (addr_arg);
890
891 // Define the first (and only) variant of this arg.
892 value_arg.arg_type = eArgTypeValue;
893 value_arg.arg_repetition = eArgRepeatPlus;
894
895 // There is only one variant this argument could be; put it into the argument entry.
896 arg2.push_back (value_arg);
897
898 // Push the data for the first argument into the m_arguments vector.
899 m_arguments.push_back (arg1);
900 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000901
902 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
903 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
904 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
905 m_option_group.Finalize();
906
Chris Lattner24943d22010-06-08 16:52:24 +0000907 }
908
909 virtual
910 ~CommandObjectMemoryWrite ()
911 {
912 }
913
914 Options *
915 GetOptions ()
916 {
Greg Claytona42880a2011-10-25 06:44:01 +0000917 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000918 }
919
920 bool
921 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
922 {
923 if (total_byte_size > 8)
924 return false;
925
926 if (total_byte_size == 8)
927 return true;
928
929 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
930 return uval64 <= max;
931 }
932
933 bool
934 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
935 {
936 if (total_byte_size > 8)
937 return false;
938
939 if (total_byte_size == 8)
940 return true;
941
942 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
943 const int64_t min = ~(max);
944 return min <= sval64 && sval64 <= max;
945 }
946
Jim Inghamda26bd22012-06-08 21:56:10 +0000947protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000948 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000949 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000950 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000951 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000952 if (process == NULL)
953 {
954 result.AppendError("need a process to read memory");
955 result.SetStatus(eReturnStatusFailed);
956 return false;
957 }
958
959 const size_t argc = command.GetArgumentCount();
960
Greg Claytona42880a2011-10-25 06:44:01 +0000961 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +0000962 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000963 if (argc < 1)
964 {
965 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
966 result.SetStatus(eReturnStatusFailed);
967 return false;
968 }
969 }
970 else if (argc < 2)
971 {
972 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 +0000973 result.SetStatus(eReturnStatusFailed);
974 return false;
975 }
976
Chris Lattner24943d22010-06-08 16:52:24 +0000977 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +0000978 process->GetTarget().GetArchitecture().GetAddressByteSize(),
979 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +0000980
Greg Claytona42880a2011-10-25 06:44:01 +0000981 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
982 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +0000983
Chris Lattner24943d22010-06-08 16:52:24 +0000984 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
985
986 if (addr == LLDB_INVALID_ADDRESS)
987 {
988 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
989 result.SetStatus(eReturnStatusFailed);
990 return false;
991 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000992
Greg Claytona42880a2011-10-25 06:44:01 +0000993 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000994 {
995 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +0000996 if (item_byte_size > 0)
997 length = item_byte_size;
998 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000999 if (data_sp)
1000 {
1001 length = data_sp->GetByteSize();
1002 if (length > 0)
1003 {
1004 Error error;
1005 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1006
1007 if (bytes_written == length)
1008 {
1009 // All bytes written
1010 result.GetOutputStream().Printf("%zu bytes were written to 0x%llx\n", bytes_written, addr);
1011 result.SetStatus(eReturnStatusSuccessFinishResult);
1012 }
1013 else if (bytes_written > 0)
1014 {
1015 // Some byte written
1016 result.GetOutputStream().Printf("%zu bytes of %zu requested were written to 0x%llx\n", bytes_written, length, addr);
1017 result.SetStatus(eReturnStatusSuccessFinishResult);
1018 }
1019 else
1020 {
1021 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1022 result.SetStatus(eReturnStatusFailed);
1023 }
1024 }
1025 }
1026 else
1027 {
1028 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1029 result.SetStatus(eReturnStatusFailed);
1030 }
1031 return result.Succeeded();
1032 }
Greg Claytona42880a2011-10-25 06:44:01 +00001033 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001034 {
Greg Claytona42880a2011-10-25 06:44:01 +00001035 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001036 item_byte_size = buffer.GetAddressByteSize();
1037 else
1038 item_byte_size = 1;
1039 }
1040
Chris Lattner24943d22010-06-08 16:52:24 +00001041 command.Shift(); // shift off the address argument
1042 uint64_t uval64;
1043 int64_t sval64;
1044 bool success = false;
1045 const uint32_t num_value_args = command.GetArgumentCount();
1046 uint32_t i;
1047 for (i=0; i<num_value_args; ++i)
1048 {
1049 const char *value_str = command.GetArgumentAtIndex(i);
1050
Greg Claytona42880a2011-10-25 06:44:01 +00001051 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001052 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001053 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001054 case eFormatFloat: // TODO: add support for floats soon
1055 case eFormatCharPrintable:
1056 case eFormatBytesWithASCII:
1057 case eFormatComplex:
1058 case eFormatEnum:
1059 case eFormatUnicode16:
1060 case eFormatUnicode32:
1061 case eFormatVectorOfChar:
1062 case eFormatVectorOfSInt8:
1063 case eFormatVectorOfUInt8:
1064 case eFormatVectorOfSInt16:
1065 case eFormatVectorOfUInt16:
1066 case eFormatVectorOfSInt32:
1067 case eFormatVectorOfUInt32:
1068 case eFormatVectorOfSInt64:
1069 case eFormatVectorOfUInt64:
1070 case eFormatVectorOfFloat32:
1071 case eFormatVectorOfFloat64:
1072 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001073 case eFormatOSType:
1074 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001075 case eFormatAddressInfo:
1076 case eFormatHexFloat:
1077 case eFormatInstruction:
Chris Lattner24943d22010-06-08 16:52:24 +00001078 result.AppendError("unsupported format for writing memory");
1079 result.SetStatus(eReturnStatusFailed);
1080 return false;
1081
1082 case eFormatDefault:
1083 case eFormatBytes:
1084 case eFormatHex:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001085 case eFormatPointer:
1086
Chris Lattner24943d22010-06-08 16:52:24 +00001087 // Decode hex bytes
1088 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1089 if (!success)
1090 {
1091 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1092 result.SetStatus(eReturnStatusFailed);
1093 return false;
1094 }
1095 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1096 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001097 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 +00001098 result.SetStatus(eReturnStatusFailed);
1099 return false;
1100 }
1101 buffer.PutMaxHex64 (uval64, item_byte_size);
1102 break;
1103
1104 case eFormatBoolean:
1105 uval64 = Args::StringToBoolean(value_str, false, &success);
1106 if (!success)
1107 {
1108 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1109 result.SetStatus(eReturnStatusFailed);
1110 return false;
1111 }
1112 buffer.PutMaxHex64 (uval64, item_byte_size);
1113 break;
1114
1115 case eFormatBinary:
1116 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1117 if (!success)
1118 {
1119 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1120 result.SetStatus(eReturnStatusFailed);
1121 return false;
1122 }
1123 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1124 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001125 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 +00001126 result.SetStatus(eReturnStatusFailed);
1127 return false;
1128 }
1129 buffer.PutMaxHex64 (uval64, item_byte_size);
1130 break;
1131
Greg Clayton307fa072011-06-17 23:50:44 +00001132 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001133 case eFormatChar:
1134 case eFormatCString:
1135 if (value_str[0])
1136 {
1137 size_t len = strlen (value_str);
1138 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001139 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001140 ++len;
1141 Error error;
1142 if (process->WriteMemory (addr, value_str, len, error) == len)
1143 {
1144 addr += len;
1145 }
1146 else
1147 {
1148 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1149 result.SetStatus(eReturnStatusFailed);
1150 return false;
1151 }
1152 }
1153 break;
1154
1155 case eFormatDecimal:
1156 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1157 if (!success)
1158 {
1159 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1160 result.SetStatus(eReturnStatusFailed);
1161 return false;
1162 }
1163 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1164 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001165 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 +00001166 result.SetStatus(eReturnStatusFailed);
1167 return false;
1168 }
1169 buffer.PutMaxHex64 (sval64, item_byte_size);
1170 break;
1171
1172 case eFormatUnsigned:
1173 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1174 if (!success)
1175 {
1176 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1177 result.SetStatus(eReturnStatusFailed);
1178 return false;
1179 }
1180 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1181 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001182 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 +00001183 result.SetStatus(eReturnStatusFailed);
1184 return false;
1185 }
1186 buffer.PutMaxHex64 (uval64, item_byte_size);
1187 break;
1188
1189 case eFormatOctal:
1190 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1191 if (!success)
1192 {
1193 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1194 result.SetStatus(eReturnStatusFailed);
1195 return false;
1196 }
1197 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1198 {
Jason Molenda7e5fa7f2011-09-20 21:44:10 +00001199 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 +00001200 result.SetStatus(eReturnStatusFailed);
1201 return false;
1202 }
1203 buffer.PutMaxHex64 (uval64, item_byte_size);
1204 break;
1205 }
1206 }
1207
1208 if (!buffer.GetString().empty())
1209 {
1210 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001211 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001212 return true;
1213 else
1214 {
1215 result.AppendErrorWithFormat ("Memory write to 0x%llx failed: %s.\n", addr, error.AsCString());
1216 result.SetStatus(eReturnStatusFailed);
1217 return false;
1218 }
1219 }
1220 return true;
1221 }
1222
Greg Claytona42880a2011-10-25 06:44:01 +00001223 OptionGroupOptions m_option_group;
1224 OptionGroupFormat m_format_options;
1225 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001226};
1227
Chris Lattner24943d22010-06-08 16:52:24 +00001228
1229//-------------------------------------------------------------------------
1230// CommandObjectMemory
1231//-------------------------------------------------------------------------
1232
Greg Clayton63094e02010-06-23 01:19:29 +00001233CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001234 CommandObjectMultiword (interpreter,
1235 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001236 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001237 "memory <subcommand> [<subcommand-options>]")
1238{
Greg Clayton238c0a12010-09-18 01:14:36 +00001239 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1240 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001241}
1242
1243CommandObjectMemory::~CommandObjectMemory ()
1244{
1245}