blob: 09c2e4859cbfc083fd13343a93cf9905a73336e7 [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
Daniel Malead891f9b2012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner24943d22010-06-08 16:52:24 +000012#include "CommandObjectMemory.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
Chris Lattner24943d22010-06-08 16:52:24 +000018#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
Greg Clayton63094e02010-06-23 01:19:29 +000020#include "lldb/Core/Debugger.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000021#include "lldb/Core/Module.h"
Chris Lattner24943d22010-06-08 16:52:24 +000022#include "lldb/Core/StreamString.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000023#include "lldb/Core/ValueObjectMemory.h"
Greg Clayton63094e02010-06-23 01:19:29 +000024#include "lldb/Interpreter/Args.h"
Chris Lattner24943d22010-06-08 16:52:24 +000025#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton63094e02010-06-23 01:19:29 +000026#include "lldb/Interpreter/CommandInterpreter.h"
27#include "lldb/Interpreter/Options.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000028#include "lldb/Interpreter/OptionGroupFormat.h"
29#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton56bbdaf2011-04-28 20:55:26 +000030#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton73844aa2012-08-22 17:17:09 +000031#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton49ce8962012-08-29 21:13:06 +000032#include "lldb/Symbol/TypeList.h"
Chris Lattner24943d22010-06-08 16:52:24 +000033#include "lldb/Target/Process.h"
Greg Clayton57b3c6b2011-04-27 22:04:39 +000034#include "lldb/Target/StackFrame.h"
Chris Lattner24943d22010-06-08 16:52:24 +000035
36using namespace lldb;
37using namespace lldb_private;
38
Greg Clayton56bbdaf2011-04-28 20:55:26 +000039static OptionDefinition
Greg Clayton57b3c6b2011-04-27 22:04:39 +000040g_option_table[] =
41{
Greg Clayton57b3c6b2011-04-27 22:04:39 +000042 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', required_argument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
43 { LLDB_OPT_SET_2, false, "binary" ,'b', no_argument , NULL, 0, eArgTypeNone ,"If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that uses the format, size, count and number per line settings."},
Sean Callanan06dc17f2012-09-24 22:25:51 +000044 { LLDB_OPT_SET_3, true , "type" ,'t', required_argument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton827baf62012-11-02 21:14:58 +000045 { LLDB_OPT_SET_1|
46 LLDB_OPT_SET_2|
47 LLDB_OPT_SET_3, false, "force" ,'r', no_argument, NULL, 0, eArgTypeNone ,"Necessary if reading over 1024 bytes of memory."},
Greg Clayton57b3c6b2011-04-27 22:04:39 +000048};
49
50
51
52class OptionGroupReadMemory : public OptionGroup
53{
54public:
55
56 OptionGroupReadMemory () :
Greg Clayton56bbdaf2011-04-28 20:55:26 +000057 m_num_per_line (1,1),
Greg Clayton57b3c6b2011-04-27 22:04:39 +000058 m_output_as_binary (false),
59 m_view_as_type()
60 {
61 }
62
63 virtual
64 ~OptionGroupReadMemory ()
65 {
66 }
67
68
69 virtual uint32_t
70 GetNumDefinitions ()
71 {
72 return sizeof (g_option_table) / sizeof (OptionDefinition);
73 }
74
75 virtual const OptionDefinition*
76 GetDefinitions ()
77 {
78 return g_option_table;
79 }
80
81 virtual Error
82 SetOptionValue (CommandInterpreter &interpreter,
83 uint32_t option_idx,
84 const char *option_arg)
85 {
86 Error error;
Greg Clayton6475c422012-12-04 00:32:51 +000087 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton57b3c6b2011-04-27 22:04:39 +000088
89 switch (short_option)
90 {
91 case 'l':
92 error = m_num_per_line.SetValueFromCString (option_arg);
93 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton9c236732011-10-26 00:56:27 +000094 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton57b3c6b2011-04-27 22:04:39 +000095 break;
Greg Claytona42880a2011-10-25 06:44:01 +000096
Greg Clayton57b3c6b2011-04-27 22:04:39 +000097 case 'b':
98 m_output_as_binary = true;
99 break;
100
101 case 't':
102 error = m_view_as_type.SetValueFromCString (option_arg);
103 break;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000104
105 case 'r':
106 m_force = true;
107 break;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000108
109 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000110 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000111 break;
112 }
113 return error;
114 }
115
116 virtual void
117 OptionParsingStarting (CommandInterpreter &interpreter)
118 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000119 m_num_per_line.Clear();
120 m_output_as_binary = false;
121 m_view_as_type.Clear();
122 }
123
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000124 Error
Greg Claytona42880a2011-10-25 06:44:01 +0000125 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000126 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000127 Error error;
Greg Claytona42880a2011-10-25 06:44:01 +0000128 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
129 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton9c236732011-10-26 00:56:27 +0000130 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000131 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Claytona42880a2011-10-25 06:44:01 +0000132 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000133
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000134 switch (format_options.GetFormat())
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000135 {
136 default:
137 break;
138
139 case eFormatBoolean:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000140 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000141 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000142 if (!num_per_line_option_set)
143 m_num_per_line = 1;
144 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000145 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000146 break;
147
148 case eFormatCString:
149 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000150
151 case eFormatInstruction:
152 if (count_option_set)
Jim Inghamab885832012-11-07 01:52:04 +0000153 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton24a6bd92011-10-27 17:55:14 +0000154 m_num_per_line = 1;
155 break;
156
157 case eFormatAddressInfo:
158 if (!byte_size_option_set)
159 byte_size_value = target->GetArchitecture().GetAddressByteSize();
160 m_num_per_line = 1;
161 if (!count_option_set)
162 format_options.GetCountValue() = 8;
163 break;
164
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000165 case eFormatPointer:
Greg Claytona42880a2011-10-25 06:44:01 +0000166 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000167 if (!num_per_line_option_set)
168 m_num_per_line = 4;
169 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000170 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000171 break;
172
173 case eFormatBinary:
174 case eFormatFloat:
175 case eFormatOctal:
176 case eFormatDecimal:
177 case eFormatEnum:
178 case eFormatUnicode16:
179 case eFormatUnicode32:
180 case eFormatUnsigned:
Greg Clayton24a6bd92011-10-27 17:55:14 +0000181 case eFormatHexFloat:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000182 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000183 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000184 if (!num_per_line_option_set)
185 m_num_per_line = 1;
186 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000187 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000188 break;
Greg Clayton24a6bd92011-10-27 17:55:14 +0000189
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000190 case eFormatBytes:
191 case eFormatBytesWithASCII:
Greg Clayton9c236732011-10-26 00:56:27 +0000192 if (byte_size_option_set)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000193 {
Greg Claytona42880a2011-10-25 06:44:01 +0000194 if (byte_size_value > 1)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000195 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenbf9ba592012-03-06 01:17:59 +0000196 "\tconsider using a different display format or don't specify the byte size",
197 byte_size_value.GetCurrentValue());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000198 }
199 else
Greg Claytona42880a2011-10-25 06:44:01 +0000200 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000201 if (!num_per_line_option_set)
202 m_num_per_line = 16;
203 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000204 format_options.GetCountValue() = 32;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000205 break;
Greg Clayton307fa072011-06-17 23:50:44 +0000206 case eFormatCharArray:
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000207 case eFormatChar:
208 case eFormatCharPrintable:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000209 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000210 byte_size_value = 1;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000211 if (!num_per_line_option_set)
212 m_num_per_line = 32;
213 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000214 format_options.GetCountValue() = 64;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000215 break;
216 case eFormatComplex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000217 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000218 byte_size_value = 8;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000219 if (!num_per_line_option_set)
220 m_num_per_line = 1;
221 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000222 format_options.GetCountValue() = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000223 break;
224 case eFormatHex:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000225 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000226 byte_size_value = 4;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000227 if (!num_per_line_option_set)
228 {
Greg Claytona42880a2011-10-25 06:44:01 +0000229 switch (byte_size_value)
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000230 {
231 case 1:
232 case 2:
233 m_num_per_line = 8;
234 break;
235 case 4:
236 m_num_per_line = 4;
237 break;
238 case 8:
239 m_num_per_line = 2;
240 break;
241 default:
242 m_num_per_line = 1;
243 break;
244 }
245 }
246 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000247 count_value = 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000248 break;
249
250 case eFormatVectorOfChar:
251 case eFormatVectorOfSInt8:
252 case eFormatVectorOfUInt8:
253 case eFormatVectorOfSInt16:
254 case eFormatVectorOfUInt16:
255 case eFormatVectorOfSInt32:
256 case eFormatVectorOfUInt32:
257 case eFormatVectorOfSInt64:
258 case eFormatVectorOfUInt64:
259 case eFormatVectorOfFloat32:
260 case eFormatVectorOfFloat64:
261 case eFormatVectorOfUInt128:
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000262 if (!byte_size_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000263 byte_size_value = 128;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000264 if (!num_per_line_option_set)
265 m_num_per_line = 1;
266 if (!count_option_set)
Greg Claytona42880a2011-10-25 06:44:01 +0000267 count_value = 4;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000268 break;
269 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000270 return error;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000271 }
272
Greg Clayton902b5be2011-10-26 04:32:38 +0000273 bool
274 AnyOptionWasSet () const
275 {
276 return m_num_per_line.OptionWasSet() ||
277 m_output_as_binary ||
278 m_view_as_type.OptionWasSet();
279 }
280
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000281 OptionValueUInt64 m_num_per_line;
282 bool m_output_as_binary;
283 OptionValueString m_view_as_type;
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000284 bool m_force;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000285};
286
287
288
Chris Lattner24943d22010-06-08 16:52:24 +0000289//----------------------------------------------------------------------
290// Read memory from the inferior process
291//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000292class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000293{
294public:
295
Greg Clayton238c0a12010-09-18 01:14:36 +0000296 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000297 CommandObjectParsed (interpreter,
298 "memory read",
299 "Read from the memory of the process being debugged.",
300 NULL,
301 eFlagProcessMustBePaused),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000302 m_option_group (interpreter),
Greg Claytona42880a2011-10-25 06:44:01 +0000303 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000304 m_memory_options (),
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000305 m_outfile_options (),
Greg Clayton902b5be2011-10-26 04:32:38 +0000306 m_varobj_options(),
307 m_next_addr(LLDB_INVALID_ADDRESS),
308 m_prev_byte_size(0),
309 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
310 m_prev_memory_options (),
311 m_prev_outfile_options (),
312 m_prev_varobj_options()
Chris Lattner24943d22010-06-08 16:52:24 +0000313 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000314 CommandArgumentEntry arg1;
315 CommandArgumentEntry arg2;
316 CommandArgumentData start_addr_arg;
317 CommandArgumentData end_addr_arg;
318
319 // Define the first (and only) variant of this arg.
320 start_addr_arg.arg_type = eArgTypeStartAddress;
321 start_addr_arg.arg_repetition = eArgRepeatPlain;
322
323 // There is only one variant this argument could be; put it into the argument entry.
324 arg1.push_back (start_addr_arg);
325
326 // Define the first (and only) variant of this arg.
327 end_addr_arg.arg_type = eArgTypeEndAddress;
328 end_addr_arg.arg_repetition = eArgRepeatOptional;
329
330 // There is only one variant this argument could be; put it into the argument entry.
331 arg2.push_back (end_addr_arg);
332
333 // Push the data for the first argument into the m_arguments vector.
334 m_arguments.push_back (arg1);
335 m_arguments.push_back (arg2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000336
Greg Claytona42880a2011-10-25 06:44:01 +0000337 // Add the "--format" and "--count" options to group 1 and 3
338 m_option_group.Append (&m_format_options,
339 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000340 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000341 m_option_group.Append (&m_format_options,
342 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton31feaa82011-11-22 18:07:35 +0000343 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Claytona42880a2011-10-25 06:44:01 +0000344 // Add the "--size" option to group 1 and 2
345 m_option_group.Append (&m_format_options,
346 OptionGroupFormat::OPTION_GROUP_SIZE,
347 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000348 m_option_group.Append (&m_memory_options);
349 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 +0000350 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000351 m_option_group.Finalize();
Chris Lattner24943d22010-06-08 16:52:24 +0000352 }
353
354 virtual
355 ~CommandObjectMemoryRead ()
356 {
357 }
358
359 Options *
360 GetOptions ()
361 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000362 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000363 }
364
Greg Clayton902b5be2011-10-26 04:32:38 +0000365 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
366 {
367 return m_cmd_name.c_str();
368 }
369
Jim Inghamda26bd22012-06-08 21:56:10 +0000370protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000371 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000372 DoExecute (Args& command,
Chris Lattner24943d22010-06-08 16:52:24 +0000373 CommandReturnObject &result)
374 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000375 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000376 Target *target = exe_ctx.GetTargetPtr();
377 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000378 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000379 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000380 result.SetStatus(eReturnStatusFailed);
381 return false;
382 }
383 const size_t argc = command.GetArgumentCount();
384
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000385
Greg Clayton902b5be2011-10-26 04:32:38 +0000386 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000387 {
388 result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
389 result.SetStatus(eReturnStatusFailed);
390 return false;
391 }
392
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000393 ClangASTType clang_ast_type;
394 Error error;
395
396 Format format = m_format_options.GetFormat();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000397 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
398 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner24943d22010-06-08 16:52:24 +0000399 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000400 // We are viewing memory as a type
401 SymbolContext sc;
Greg Claytondc0a38c2012-03-26 23:03:23 +0000402 const bool exact_match = false;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000403 TypeList type_list;
404 uint32_t reference_count = 0;
405 uint32_t pointer_count = 0;
406 size_t idx;
Sean Callananddb2ece2012-07-10 21:24:26 +0000407
408#define ALL_KEYWORDS \
409 KEYWORD("const") \
410 KEYWORD("volatile") \
411 KEYWORD("restrict") \
412 KEYWORD("struct") \
413 KEYWORD("class") \
414 KEYWORD("union")
415
416#define KEYWORD(s) s,
417 static const char *g_keywords[] =
418 {
419 ALL_KEYWORDS
420 };
421#undef KEYWORD
422
423#define KEYWORD(s) (sizeof(s) - 1),
424 static const int g_keyword_lengths[] =
425 {
426 ALL_KEYWORDS
427 };
428#undef KEYWORD
429
430#undef ALL_KEYWORDS
431
432 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000433 std::string type_str(view_as_type_cstr);
434
435 // Remove all instances of g_keywords that are followed by spaces
436 for (size_t i = 0; i < g_num_keywords; ++i)
437 {
438 const char *keyword = g_keywords[i];
Sean Callananddb2ece2012-07-10 21:24:26 +0000439 int keyword_len = g_keyword_lengths[i];
440
441 idx = 0;
442 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000443 {
444 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callananddb2ece2012-07-10 21:24:26 +0000445 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000446 type_str.erase(idx, keyword_len+1);
Sean Callananddb2ece2012-07-10 21:24:26 +0000447 idx = 0;
448 }
449 else
450 {
451 idx += keyword_len;
452 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000453 }
454 }
455 bool done = type_str.empty();
456 //
457 idx = type_str.find_first_not_of (" \t");
458 if (idx > 0 && idx != std::string::npos)
459 type_str.erase (0, idx);
460 while (!done)
461 {
462 // Strip trailing spaces
463 if (type_str.empty())
464 done = true;
465 else
466 {
467 switch (type_str[type_str.size()-1])
468 {
469 case '*':
470 ++pointer_count;
471 // fall through...
472 case ' ':
473 case '\t':
474 type_str.erase(type_str.size()-1);
475 break;
476
477 case '&':
478 if (reference_count == 0)
479 {
480 reference_count = 1;
481 type_str.erase(type_str.size()-1);
482 }
483 else
484 {
485 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
486 result.SetStatus(eReturnStatusFailed);
487 return false;
488 }
489 break;
490
491 default:
492 done = true;
493 break;
494 }
495 }
496 }
497
498 ConstString lookup_type_name(type_str.c_str());
Greg Clayton567e7f32011-09-22 04:58:26 +0000499 StackFrame *frame = exe_ctx.GetFramePtr();
500 if (frame)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000501 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000502 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000503 if (sc.module_sp)
504 {
Sean Callanan3e80cd92011-10-12 02:08:07 +0000505 sc.module_sp->FindTypes (sc,
506 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000507 exact_match,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000508 1,
509 type_list);
510 }
511 }
512 if (type_list.GetSize() == 0)
513 {
Greg Clayton9f95fb62012-04-06 17:41:13 +0000514 target->GetImages().FindTypes (sc,
Greg Clayton567e7f32011-09-22 04:58:26 +0000515 lookup_type_name,
Greg Claytondc0a38c2012-03-26 23:03:23 +0000516 exact_match,
Greg Clayton567e7f32011-09-22 04:58:26 +0000517 1,
518 type_list);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000519 }
520
521 if (type_list.GetSize() == 0)
522 {
523 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
524 lookup_type_name.GetCString(),
525 view_as_type_cstr);
526 result.SetStatus(eReturnStatusFailed);
527 return false;
528 }
529
530 TypeSP type_sp (type_list.GetTypeAtIndex(0));
531 clang_ast_type.SetClangType (type_sp->GetClangAST(), type_sp->GetClangFullType());
532
533 while (pointer_count > 0)
534 {
535 clang_type_t pointer_type = ClangASTContext::CreatePointerType (clang_ast_type.GetASTContext(), clang_ast_type.GetOpaqueQualType());
536 if (pointer_type)
537 clang_ast_type.SetClangType (clang_ast_type.GetASTContext(), pointer_type);
538 else
539 {
540 result.AppendError ("unable make a pointer type\n");
541 result.SetStatus(eReturnStatusFailed);
542 return false;
543 }
544 --pointer_count;
545 }
546
Greg Claytona42880a2011-10-25 06:44:01 +0000547 m_format_options.GetByteSizeValue() = (clang_ast_type.GetClangTypeBitWidth () + 7) / 8;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000548
Greg Claytona42880a2011-10-25 06:44:01 +0000549 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000550 {
551 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
552 view_as_type_cstr);
553 result.SetStatus(eReturnStatusFailed);
554 return false;
555 }
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000556
Greg Claytona42880a2011-10-25 06:44:01 +0000557 if (!m_format_options.GetCountValue().OptionWasSet())
558 m_format_options.GetCountValue() = 1;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000559 }
560 else
561 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000562 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000563 }
564
565 // Look for invalid combinations of settings
566 if (error.Fail())
567 {
568 result.AppendErrorWithFormat("%s", error.AsCString());
569 result.SetStatus(eReturnStatusFailed);
570 return false;
Chris Lattner24943d22010-06-08 16:52:24 +0000571 }
572
Greg Clayton902b5be2011-10-26 04:32:38 +0000573 lldb::addr_t addr;
574 size_t total_byte_size = 0;
575 if (argc == 0)
576 {
577 // Use the last address and byte size and all options as they were
578 // if no options have been set
579 addr = m_next_addr;
580 total_byte_size = m_prev_byte_size;
581 if (!m_format_options.AnyOptionWasSet() &&
582 !m_memory_options.AnyOptionWasSet() &&
583 !m_outfile_options.AnyOptionWasSet() &&
584 !m_varobj_options.AnyOptionWasSet())
585 {
586 m_format_options = m_prev_format_options;
587 m_memory_options = m_prev_memory_options;
588 m_outfile_options = m_prev_outfile_options;
589 m_varobj_options = m_prev_varobj_options;
590 }
591 }
592
Greg Claytona42880a2011-10-25 06:44:01 +0000593 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
594 const size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000595 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner24943d22010-06-08 16:52:24 +0000596
Chris Lattner24943d22010-06-08 16:52:24 +0000597 if (total_byte_size == 0)
Greg Clayton902b5be2011-10-26 04:32:38 +0000598 {
599 total_byte_size = item_count * item_byte_size;
600 if (total_byte_size == 0)
601 total_byte_size = 32;
602 }
Chris Lattner24943d22010-06-08 16:52:24 +0000603
Greg Clayton902b5be2011-10-26 04:32:38 +0000604 if (argc > 0)
605 addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000606
607 if (addr == LLDB_INVALID_ADDRESS)
608 {
609 result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
610 result.SetStatus(eReturnStatusFailed);
611 return false;
612 }
613
614 if (argc == 2)
615 {
616 lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
617 if (end_addr == LLDB_INVALID_ADDRESS)
618 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000619 result.AppendErrorWithFormat("invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
Chris Lattner24943d22010-06-08 16:52:24 +0000620 result.SetStatus(eReturnStatusFailed);
621 return false;
622 }
623 else if (end_addr <= addr)
624 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000625 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner24943d22010-06-08 16:52:24 +0000626 result.SetStatus(eReturnStatusFailed);
627 return false;
628 }
Greg Claytona42880a2011-10-25 06:44:01 +0000629 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000630 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000631 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %lu), not both.\n", end_addr, item_count);
Chris Lattner24943d22010-06-08 16:52:24 +0000632 result.SetStatus(eReturnStatusFailed);
633 return false;
634 }
635
636 total_byte_size = end_addr - addr;
637 item_count = total_byte_size / item_byte_size;
638 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000639
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000640 if (total_byte_size > 1024 && !m_memory_options.m_force)
641 {
642 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
643 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
644 return false;
645 }
646
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000647 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000648 size_t bytes_read = 0;
649 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000650 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000651 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000652 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000653 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000654 if (bytes_read == 0)
655 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000656 const char *error_cstr = error.AsCString();
657 if (error_cstr && error_cstr[0])
658 {
659 result.AppendError(error_cstr);
660 }
661 else
662 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000663 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton04e6ada2012-05-25 17:05:55 +0000664 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000665 result.SetStatus(eReturnStatusFailed);
666 return false;
667 }
668
669 if (bytes_read < total_byte_size)
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000670 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000671 else
672 {
673 m_next_addr = addr + bytes_read;
674 m_prev_byte_size = bytes_read;
675 m_prev_format_options = m_format_options;
676 m_prev_memory_options = m_memory_options;
677 m_prev_outfile_options = m_outfile_options;
678 m_prev_varobj_options = m_varobj_options;
679 }
Chris Lattner24943d22010-06-08 16:52:24 +0000680 }
681
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000682 StreamFile outfile_stream;
683 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000684 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
685 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000686 {
687 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000688 outfile_spec.GetPath (path, sizeof(path));
689
690 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
691 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
692 if (append)
693 open_options |= File::eOpenOptionAppend;
694
695 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000696 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000697 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000698 {
699 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
700 if (bytes_written > 0)
701 {
702 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
703 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000704 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000705 path);
706 return true;
707 }
708 else
709 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000710 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000711 result.SetStatus(eReturnStatusFailed);
712 return false;
713 }
714 }
715 else
716 {
717 // We are going to write ASCII to the file just point the
718 // output_stream to our outfile_stream...
719 output_stream = &outfile_stream;
720 }
721 }
722 else
723 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000724 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000725 result.SetStatus(eReturnStatusFailed);
726 return false;
727 }
728 }
729 else
730 {
731 output_stream = &result.GetOutputStream();
732 }
733
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000734
Greg Clayton24a6bd92011-10-27 17:55:14 +0000735 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000736 if (clang_ast_type.GetOpaqueQualType())
737 {
738 for (uint32_t i = 0; i<item_count; ++i)
739 {
740 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000741 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000742 StreamString name_strm;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000743 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000744 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000745 name_strm.GetString().c_str(),
746 address,
747 clang_ast_type));
748 if (valobj_sp)
749 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000750 if (format != eFormatDefault)
751 valobj_sp->SetFormat (format);
752
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000753 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000754
Enrico Granata3069c622012-03-01 04:24:26 +0000755 ValueObject::DumpValueObjectOptions options;
756 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
757 .SetMaximumDepth(m_varobj_options.max_depth)
758 .SetShowLocation(m_varobj_options.show_location)
759 .SetShowTypes(m_varobj_options.show_types)
760 .SetUseObjectiveC(m_varobj_options.use_objc)
761 .SetScopeChecked(scope_already_checked)
762 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000763 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000764 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
765 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
766 .SetFormat(format)
767 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000768 ValueObject::DumpValueObject (*output_stream,
769 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000770 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000771 }
772 else
773 {
774 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
775 view_as_type_cstr,
776 name_strm.GetString().c_str());
777 result.SetStatus(eReturnStatusFailed);
778 return false;
779 }
780 }
781 return true;
782 }
783
784 result.SetStatus(eReturnStatusSuccessFinishResult);
785 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000786 target->GetArchitecture().GetByteOrder(),
787 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000788
789
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000790 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000791 uint32_t bytes_dumped = data.Dump (output_stream,
792 0,
793 m_format_options.GetFormat(),
794 item_byte_size,
795 item_count,
796 num_per_line,
797 addr,
798 0,
799 0,
800 exe_scope);
801 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000802 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000803 return true;
804 }
805
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000806 OptionGroupOptions m_option_group;
807 OptionGroupFormat m_format_options;
808 OptionGroupReadMemory m_memory_options;
809 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000810 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000811 lldb::addr_t m_next_addr;
812 lldb::addr_t m_prev_byte_size;
813 OptionGroupFormat m_prev_format_options;
814 OptionGroupReadMemory m_prev_memory_options;
815 OptionGroupOutputFile m_prev_outfile_options;
816 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000817};
818
Greg Claytona42880a2011-10-25 06:44:01 +0000819
820OptionDefinition
821g_memory_write_option_table[] =
822{
823{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
824{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
825};
826
827
Chris Lattner24943d22010-06-08 16:52:24 +0000828//----------------------------------------------------------------------
829// Write memory to the inferior process
830//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000831class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000832{
833public:
834
Greg Claytona42880a2011-10-25 06:44:01 +0000835 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000836 {
837 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000838 OptionGroupWriteMemory () :
839 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000840 {
Chris Lattner24943d22010-06-08 16:52:24 +0000841 }
842
843 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000844 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000845 {
846 }
847
Greg Claytona42880a2011-10-25 06:44:01 +0000848 virtual uint32_t
849 GetNumDefinitions ()
850 {
851 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
852 }
853
854 virtual const OptionDefinition*
855 GetDefinitions ()
856 {
857 return g_memory_write_option_table;
858 }
859
Chris Lattner24943d22010-06-08 16:52:24 +0000860 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000861 SetOptionValue (CommandInterpreter &interpreter,
862 uint32_t option_idx,
863 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000864 {
865 Error error;
Greg Clayton6475c422012-12-04 00:32:51 +0000866 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Claytona42880a2011-10-25 06:44:01 +0000867
Chris Lattner24943d22010-06-08 16:52:24 +0000868 switch (short_option)
869 {
Greg Claytona42880a2011-10-25 06:44:01 +0000870 case 'i':
871 m_infile.SetFile (option_arg, true);
872 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000873 {
Greg Claytona42880a2011-10-25 06:44:01 +0000874 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000875 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000876 }
Greg Claytona42880a2011-10-25 06:44:01 +0000877 break;
878
879 case 'o':
880 {
881 bool success;
882 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
883 if (!success)
884 {
Greg Clayton9c236732011-10-26 00:56:27 +0000885 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000886 }
887 }
888 break;
889
890 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000891 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000892 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000893 }
894 return error;
895 }
Greg Claytona42880a2011-10-25 06:44:01 +0000896
897 virtual void
898 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000899 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000900 m_infile.Clear();
901 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000902 }
903
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000904 FileSpec m_infile;
905 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000906 };
907
Greg Clayton238c0a12010-09-18 01:14:36 +0000908 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000909 CommandObjectParsed (interpreter,
910 "memory write",
911 "Write to the memory of the process being debugged.",
912 NULL,
913 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000914 m_option_group (interpreter),
915 m_format_options (eFormatBytes, 1, UINT64_MAX),
916 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000917 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000918 CommandArgumentEntry arg1;
919 CommandArgumentEntry arg2;
920 CommandArgumentData addr_arg;
921 CommandArgumentData value_arg;
922
923 // Define the first (and only) variant of this arg.
924 addr_arg.arg_type = eArgTypeAddress;
925 addr_arg.arg_repetition = eArgRepeatPlain;
926
927 // There is only one variant this argument could be; put it into the argument entry.
928 arg1.push_back (addr_arg);
929
930 // Define the first (and only) variant of this arg.
931 value_arg.arg_type = eArgTypeValue;
932 value_arg.arg_repetition = eArgRepeatPlus;
933
934 // There is only one variant this argument could be; put it into the argument entry.
935 arg2.push_back (value_arg);
936
937 // Push the data for the first argument into the m_arguments vector.
938 m_arguments.push_back (arg1);
939 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000940
941 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
942 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
943 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
944 m_option_group.Finalize();
945
Chris Lattner24943d22010-06-08 16:52:24 +0000946 }
947
948 virtual
949 ~CommandObjectMemoryWrite ()
950 {
951 }
952
953 Options *
954 GetOptions ()
955 {
Greg Claytona42880a2011-10-25 06:44:01 +0000956 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000957 }
958
959 bool
960 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
961 {
962 if (total_byte_size > 8)
963 return false;
964
965 if (total_byte_size == 8)
966 return true;
967
968 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
969 return uval64 <= max;
970 }
971
972 bool
973 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
974 {
975 if (total_byte_size > 8)
976 return false;
977
978 if (total_byte_size == 8)
979 return true;
980
981 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
982 const int64_t min = ~(max);
983 return min <= sval64 && sval64 <= max;
984 }
985
Jim Inghamda26bd22012-06-08 21:56:10 +0000986protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000987 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000988 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000989 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000990 Process *process = m_interpreter.GetExecutionContext().GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000991 if (process == NULL)
992 {
993 result.AppendError("need a process to read memory");
994 result.SetStatus(eReturnStatusFailed);
995 return false;
996 }
997
998 const size_t argc = command.GetArgumentCount();
999
Greg Claytona42880a2011-10-25 06:44:01 +00001000 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +00001001 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001002 if (argc < 1)
1003 {
1004 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1005 result.SetStatus(eReturnStatusFailed);
1006 return false;
1007 }
1008 }
1009 else if (argc < 2)
1010 {
1011 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 +00001012 result.SetStatus(eReturnStatusFailed);
1013 return false;
1014 }
1015
Chris Lattner24943d22010-06-08 16:52:24 +00001016 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001017 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1018 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001019
Greg Claytona42880a2011-10-25 06:44:01 +00001020 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1021 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001022
Chris Lattner24943d22010-06-08 16:52:24 +00001023 lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);
1024
1025 if (addr == LLDB_INVALID_ADDRESS)
1026 {
1027 result.AppendErrorWithFormat("Invalid address string '%s'.\n", command.GetArgumentAtIndex(0));
1028 result.SetStatus(eReturnStatusFailed);
1029 return false;
1030 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001031
Greg Claytona42880a2011-10-25 06:44:01 +00001032 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001033 {
1034 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001035 if (item_byte_size > 0)
1036 length = item_byte_size;
1037 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001038 if (data_sp)
1039 {
1040 length = data_sp->GetByteSize();
1041 if (length > 0)
1042 {
1043 Error error;
1044 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1045
1046 if (bytes_written == length)
1047 {
1048 // All bytes written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001049 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001050 result.SetStatus(eReturnStatusSuccessFinishResult);
1051 }
1052 else if (bytes_written > 0)
1053 {
1054 // Some byte written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001055 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001056 result.SetStatus(eReturnStatusSuccessFinishResult);
1057 }
1058 else
1059 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001060 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001061 result.SetStatus(eReturnStatusFailed);
1062 }
1063 }
1064 }
1065 else
1066 {
1067 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1068 result.SetStatus(eReturnStatusFailed);
1069 }
1070 return result.Succeeded();
1071 }
Greg Claytona42880a2011-10-25 06:44:01 +00001072 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001073 {
Greg Claytona42880a2011-10-25 06:44:01 +00001074 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001075 item_byte_size = buffer.GetAddressByteSize();
1076 else
1077 item_byte_size = 1;
1078 }
1079
Chris Lattner24943d22010-06-08 16:52:24 +00001080 command.Shift(); // shift off the address argument
1081 uint64_t uval64;
1082 int64_t sval64;
1083 bool success = false;
1084 const uint32_t num_value_args = command.GetArgumentCount();
1085 uint32_t i;
1086 for (i=0; i<num_value_args; ++i)
1087 {
1088 const char *value_str = command.GetArgumentAtIndex(i);
1089
Greg Claytona42880a2011-10-25 06:44:01 +00001090 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001091 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001092 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001093 case eFormatFloat: // TODO: add support for floats soon
1094 case eFormatCharPrintable:
1095 case eFormatBytesWithASCII:
1096 case eFormatComplex:
1097 case eFormatEnum:
1098 case eFormatUnicode16:
1099 case eFormatUnicode32:
1100 case eFormatVectorOfChar:
1101 case eFormatVectorOfSInt8:
1102 case eFormatVectorOfUInt8:
1103 case eFormatVectorOfSInt16:
1104 case eFormatVectorOfUInt16:
1105 case eFormatVectorOfSInt32:
1106 case eFormatVectorOfUInt32:
1107 case eFormatVectorOfSInt64:
1108 case eFormatVectorOfUInt64:
1109 case eFormatVectorOfFloat32:
1110 case eFormatVectorOfFloat64:
1111 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001112 case eFormatOSType:
1113 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001114 case eFormatAddressInfo:
1115 case eFormatHexFloat:
1116 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001117 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001118 result.AppendError("unsupported format for writing memory");
1119 result.SetStatus(eReturnStatusFailed);
1120 return false;
1121
1122 case eFormatDefault:
1123 case eFormatBytes:
1124 case eFormatHex:
Enrico Granata535543d2012-08-09 19:33:34 +00001125 case eFormatHexUppercase:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001126 case eFormatPointer:
1127
Chris Lattner24943d22010-06-08 16:52:24 +00001128 // Decode hex bytes
1129 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1130 if (!success)
1131 {
1132 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1133 result.SetStatus(eReturnStatusFailed);
1134 return false;
1135 }
1136 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1137 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001138 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001139 result.SetStatus(eReturnStatusFailed);
1140 return false;
1141 }
1142 buffer.PutMaxHex64 (uval64, item_byte_size);
1143 break;
1144
1145 case eFormatBoolean:
1146 uval64 = Args::StringToBoolean(value_str, false, &success);
1147 if (!success)
1148 {
1149 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1150 result.SetStatus(eReturnStatusFailed);
1151 return false;
1152 }
1153 buffer.PutMaxHex64 (uval64, item_byte_size);
1154 break;
1155
1156 case eFormatBinary:
1157 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1158 if (!success)
1159 {
1160 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1161 result.SetStatus(eReturnStatusFailed);
1162 return false;
1163 }
1164 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1165 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001166 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001167 result.SetStatus(eReturnStatusFailed);
1168 return false;
1169 }
1170 buffer.PutMaxHex64 (uval64, item_byte_size);
1171 break;
1172
Greg Clayton307fa072011-06-17 23:50:44 +00001173 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001174 case eFormatChar:
1175 case eFormatCString:
1176 if (value_str[0])
1177 {
1178 size_t len = strlen (value_str);
1179 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001180 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001181 ++len;
1182 Error error;
1183 if (process->WriteMemory (addr, value_str, len, error) == len)
1184 {
1185 addr += len;
1186 }
1187 else
1188 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001189 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001190 result.SetStatus(eReturnStatusFailed);
1191 return false;
1192 }
1193 }
1194 break;
1195
1196 case eFormatDecimal:
1197 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1198 if (!success)
1199 {
1200 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1201 result.SetStatus(eReturnStatusFailed);
1202 return false;
1203 }
1204 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1205 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001206 result.AppendErrorWithFormat ("Value %" PRIi64 " 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 +00001207 result.SetStatus(eReturnStatusFailed);
1208 return false;
1209 }
1210 buffer.PutMaxHex64 (sval64, item_byte_size);
1211 break;
1212
1213 case eFormatUnsigned:
1214 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1215 if (!success)
1216 {
1217 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1218 result.SetStatus(eReturnStatusFailed);
1219 return false;
1220 }
1221 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1222 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001223 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001224 result.SetStatus(eReturnStatusFailed);
1225 return false;
1226 }
1227 buffer.PutMaxHex64 (uval64, item_byte_size);
1228 break;
1229
1230 case eFormatOctal:
1231 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1232 if (!success)
1233 {
1234 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1235 result.SetStatus(eReturnStatusFailed);
1236 return false;
1237 }
1238 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1239 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001240 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %lu byte unsigned integer value.\n", uval64, item_byte_size);
Chris Lattner24943d22010-06-08 16:52:24 +00001241 result.SetStatus(eReturnStatusFailed);
1242 return false;
1243 }
1244 buffer.PutMaxHex64 (uval64, item_byte_size);
1245 break;
1246 }
1247 }
1248
1249 if (!buffer.GetString().empty())
1250 {
1251 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001252 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001253 return true;
1254 else
1255 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001256 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001257 result.SetStatus(eReturnStatusFailed);
1258 return false;
1259 }
1260 }
1261 return true;
1262 }
1263
Greg Claytona42880a2011-10-25 06:44:01 +00001264 OptionGroupOptions m_option_group;
1265 OptionGroupFormat m_format_options;
1266 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001267};
1268
Chris Lattner24943d22010-06-08 16:52:24 +00001269
1270//-------------------------------------------------------------------------
1271// CommandObjectMemory
1272//-------------------------------------------------------------------------
1273
Greg Clayton63094e02010-06-23 01:19:29 +00001274CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001275 CommandObjectMultiword (interpreter,
1276 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001277 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001278 "memory <subcommand> [<subcommand-options>]")
1279{
Greg Clayton238c0a12010-09-18 01:14:36 +00001280 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1281 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001282}
1283
1284CommandObjectMemory::~CommandObjectMemory ()
1285{
1286}