blob: 9de5af4bbf6d84c9e4ce8e882dfcf866ec95d519 [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
Greg Clayton49d888d2012-12-06 22:49:16 +0000372 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000373 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000374 ExecutionContext exe_ctx (m_interpreter.GetExecutionContext());
Greg Clayton567e7f32011-09-22 04:58:26 +0000375 Target *target = exe_ctx.GetTargetPtr();
376 if (target == NULL)
Chris Lattner24943d22010-06-08 16:52:24 +0000377 {
Jim Ingham8cc3f692011-07-09 00:55:34 +0000378 result.AppendError("need at least a target to read memory");
Chris Lattner24943d22010-06-08 16:52:24 +0000379 result.SetStatus(eReturnStatusFailed);
380 return false;
381 }
382 const size_t argc = command.GetArgumentCount();
383
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000384
Greg Clayton902b5be2011-10-26 04:32:38 +0000385 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner24943d22010-06-08 16:52:24 +0000386 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000387 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
388 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.");
Chris Lattner24943d22010-06-08 16:52:24 +0000389 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 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000568 result.AppendError(error.AsCString());
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000569 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)
Greg Clayton49d888d2012-12-06 22:49:16 +0000605 addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner24943d22010-06-08 16:52:24 +0000606
607 if (addr == LLDB_INVALID_ADDRESS)
608 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000609 result.AppendError("invalid start address expression.");
610 result.AppendError(error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +0000611 result.SetStatus(eReturnStatusFailed);
612 return false;
613 }
614
615 if (argc == 2)
616 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000617 lldb::addr_t end_addr = Args::StringToAddress(&exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner24943d22010-06-08 16:52:24 +0000618 if (end_addr == LLDB_INVALID_ADDRESS)
619 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000620 result.AppendError("invalid end address expression.");
621 result.AppendError(error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +0000622 result.SetStatus(eReturnStatusFailed);
623 return false;
624 }
625 else if (end_addr <= addr)
626 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000627 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 +0000628 result.SetStatus(eReturnStatusFailed);
629 return false;
630 }
Greg Claytona42880a2011-10-25 06:44:01 +0000631 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner24943d22010-06-08 16:52:24 +0000632 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000633 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 +0000634 result.SetStatus(eReturnStatusFailed);
635 return false;
636 }
637
638 total_byte_size = end_addr - addr;
639 item_count = total_byte_size / item_byte_size;
640 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000641
Sean Callanan8a6f3e92012-04-28 01:27:38 +0000642 if (total_byte_size > 1024 && !m_memory_options.m_force)
643 {
644 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over 1Kbyte of data.\n");
645 result.AppendErrorWithFormat("Please use --force to override this restriction.\n");
646 return false;
647 }
648
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000649 DataBufferSP data_sp;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000650 size_t bytes_read = 0;
651 if (!clang_ast_type.GetOpaqueQualType())
Chris Lattner24943d22010-06-08 16:52:24 +0000652 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000653 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton3508c382012-02-24 01:59:29 +0000654 Address address(addr, NULL);
Greg Clayton567e7f32011-09-22 04:58:26 +0000655 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000656 if (bytes_read == 0)
657 {
Greg Clayton04e6ada2012-05-25 17:05:55 +0000658 const char *error_cstr = error.AsCString();
659 if (error_cstr && error_cstr[0])
660 {
661 result.AppendError(error_cstr);
662 }
663 else
664 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000665 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton04e6ada2012-05-25 17:05:55 +0000666 }
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000667 result.SetStatus(eReturnStatusFailed);
668 return false;
669 }
670
671 if (bytes_read < total_byte_size)
Greg Clayton49d888d2012-12-06 22:49:16 +0000672 result.AppendWarningWithFormat("Not all bytes (%lu/%lu) were able to be read from 0x%" PRIx64 ".", bytes_read, total_byte_size, addr);
Greg Clayton902b5be2011-10-26 04:32:38 +0000673 else
674 {
675 m_next_addr = addr + bytes_read;
676 m_prev_byte_size = bytes_read;
677 m_prev_format_options = m_format_options;
678 m_prev_memory_options = m_memory_options;
679 m_prev_outfile_options = m_outfile_options;
680 m_prev_varobj_options = m_varobj_options;
681 }
Chris Lattner24943d22010-06-08 16:52:24 +0000682 }
683
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000684 StreamFile outfile_stream;
685 Stream *output_stream = NULL;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000686 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
687 if (outfile_spec)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000688 {
689 char path[PATH_MAX];
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000690 outfile_spec.GetPath (path, sizeof(path));
691
692 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
693 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
694 if (append)
695 open_options |= File::eOpenOptionAppend;
696
697 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000698 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000699 if (m_memory_options.m_output_as_binary)
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000700 {
701 int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
702 if (bytes_written > 0)
703 {
704 result.GetOutputStream().Printf ("%i bytes %s to '%s'\n",
705 bytes_written,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000706 append ? "appended" : "written",
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000707 path);
708 return true;
709 }
710 else
711 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000712 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000713 result.SetStatus(eReturnStatusFailed);
714 return false;
715 }
716 }
717 else
718 {
719 // We are going to write ASCII to the file just point the
720 // output_stream to our outfile_stream...
721 output_stream = &outfile_stream;
722 }
723 }
724 else
725 {
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000726 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000727 result.SetStatus(eReturnStatusFailed);
728 return false;
729 }
730 }
731 else
732 {
733 output_stream = &result.GetOutputStream();
734 }
735
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000736
Greg Clayton24a6bd92011-10-27 17:55:14 +0000737 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000738 if (clang_ast_type.GetOpaqueQualType())
739 {
740 for (uint32_t i = 0; i<item_count; ++i)
741 {
742 addr_t item_addr = addr + (i * item_byte_size);
Greg Clayton3508c382012-02-24 01:59:29 +0000743 Address address (item_addr);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000744 StreamString name_strm;
Daniel Malea5f35a4b2012-11-29 21:49:15 +0000745 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton24a6bd92011-10-27 17:55:14 +0000746 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000747 name_strm.GetString().c_str(),
748 address,
749 clang_ast_type));
750 if (valobj_sp)
751 {
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000752 if (format != eFormatDefault)
753 valobj_sp->SetFormat (format);
754
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000755 bool scope_already_checked = true;
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000756
Enrico Granata3069c622012-03-01 04:24:26 +0000757 ValueObject::DumpValueObjectOptions options;
758 options.SetMaximumPointerDepth(m_varobj_options.ptr_depth)
759 .SetMaximumDepth(m_varobj_options.max_depth)
760 .SetShowLocation(m_varobj_options.show_location)
761 .SetShowTypes(m_varobj_options.show_types)
762 .SetUseObjectiveC(m_varobj_options.use_objc)
763 .SetScopeChecked(scope_already_checked)
764 .SetFlatOutput(m_varobj_options.flat_output)
Enrico Granatacf09f882012-03-19 22:58:49 +0000765 .SetUseSyntheticValue(m_varobj_options.be_raw ? false : m_varobj_options.use_synth)
Enrico Granata3069c622012-03-01 04:24:26 +0000766 .SetOmitSummaryDepth(m_varobj_options.be_raw ? UINT32_MAX : m_varobj_options.no_summary_depth)
767 .SetIgnoreCap(m_varobj_options.be_raw ? true : m_varobj_options.ignore_cap)
768 .SetFormat(format)
769 .SetSummary();
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000770 ValueObject::DumpValueObject (*output_stream,
771 valobj_sp.get(),
Enrico Granata3069c622012-03-01 04:24:26 +0000772 options);
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000773 }
774 else
775 {
776 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
777 view_as_type_cstr,
778 name_strm.GetString().c_str());
779 result.SetStatus(eReturnStatusFailed);
780 return false;
781 }
782 }
783 return true;
784 }
785
786 result.SetStatus(eReturnStatusSuccessFinishResult);
787 DataExtractor data (data_sp,
Greg Clayton567e7f32011-09-22 04:58:26 +0000788 target->GetArchitecture().GetByteOrder(),
789 target->GetArchitecture().GetAddressByteSize());
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000790
791
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000792 assert (output_stream);
Greg Clayton746979d2011-10-28 23:44:55 +0000793 uint32_t bytes_dumped = data.Dump (output_stream,
794 0,
795 m_format_options.GetFormat(),
796 item_byte_size,
797 item_count,
798 num_per_line,
799 addr,
800 0,
801 0,
802 exe_scope);
803 m_next_addr = addr + bytes_dumped;
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000804 output_stream->EOL();
Chris Lattner24943d22010-06-08 16:52:24 +0000805 return true;
806 }
807
Greg Clayton57b3c6b2011-04-27 22:04:39 +0000808 OptionGroupOptions m_option_group;
809 OptionGroupFormat m_format_options;
810 OptionGroupReadMemory m_memory_options;
811 OptionGroupOutputFile m_outfile_options;
Greg Clayton56bbdaf2011-04-28 20:55:26 +0000812 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton902b5be2011-10-26 04:32:38 +0000813 lldb::addr_t m_next_addr;
814 lldb::addr_t m_prev_byte_size;
815 OptionGroupFormat m_prev_format_options;
816 OptionGroupReadMemory m_prev_memory_options;
817 OptionGroupOutputFile m_prev_outfile_options;
818 OptionGroupValueObjectDisplay m_prev_varobj_options;
Chris Lattner24943d22010-06-08 16:52:24 +0000819};
820
Greg Claytona42880a2011-10-25 06:44:01 +0000821
822OptionDefinition
823g_memory_write_option_table[] =
824{
825{ LLDB_OPT_SET_1, true, "infile", 'i', required_argument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
826{ LLDB_OPT_SET_1, false, "offset", 'o', required_argument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
827};
828
829
Chris Lattner24943d22010-06-08 16:52:24 +0000830//----------------------------------------------------------------------
831// Write memory to the inferior process
832//----------------------------------------------------------------------
Jim Inghamda26bd22012-06-08 21:56:10 +0000833class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner24943d22010-06-08 16:52:24 +0000834{
835public:
836
Greg Claytona42880a2011-10-25 06:44:01 +0000837 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner24943d22010-06-08 16:52:24 +0000838 {
839 public:
Greg Claytona42880a2011-10-25 06:44:01 +0000840 OptionGroupWriteMemory () :
841 OptionGroup()
Chris Lattner24943d22010-06-08 16:52:24 +0000842 {
Chris Lattner24943d22010-06-08 16:52:24 +0000843 }
844
845 virtual
Greg Claytona42880a2011-10-25 06:44:01 +0000846 ~OptionGroupWriteMemory ()
Chris Lattner24943d22010-06-08 16:52:24 +0000847 {
848 }
849
Greg Claytona42880a2011-10-25 06:44:01 +0000850 virtual uint32_t
851 GetNumDefinitions ()
852 {
853 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
854 }
855
856 virtual const OptionDefinition*
857 GetDefinitions ()
858 {
859 return g_memory_write_option_table;
860 }
861
Chris Lattner24943d22010-06-08 16:52:24 +0000862 virtual Error
Greg Claytona42880a2011-10-25 06:44:01 +0000863 SetOptionValue (CommandInterpreter &interpreter,
864 uint32_t option_idx,
865 const char *option_arg)
Chris Lattner24943d22010-06-08 16:52:24 +0000866 {
867 Error error;
Greg Clayton6475c422012-12-04 00:32:51 +0000868 const int short_option = g_memory_write_option_table[option_idx].short_option;
Greg Claytona42880a2011-10-25 06:44:01 +0000869
Chris Lattner24943d22010-06-08 16:52:24 +0000870 switch (short_option)
871 {
Greg Claytona42880a2011-10-25 06:44:01 +0000872 case 'i':
873 m_infile.SetFile (option_arg, true);
874 if (!m_infile.Exists())
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000875 {
Greg Claytona42880a2011-10-25 06:44:01 +0000876 m_infile.Clear();
Greg Clayton9c236732011-10-26 00:56:27 +0000877 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000878 }
Greg Claytona42880a2011-10-25 06:44:01 +0000879 break;
880
881 case 'o':
882 {
883 bool success;
884 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
885 if (!success)
886 {
Greg Clayton9c236732011-10-26 00:56:27 +0000887 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Claytona42880a2011-10-25 06:44:01 +0000888 }
889 }
890 break;
891
892 default:
Greg Clayton9c236732011-10-26 00:56:27 +0000893 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Claytona42880a2011-10-25 06:44:01 +0000894 break;
Chris Lattner24943d22010-06-08 16:52:24 +0000895 }
896 return error;
897 }
Greg Claytona42880a2011-10-25 06:44:01 +0000898
899 virtual void
900 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner24943d22010-06-08 16:52:24 +0000901 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000902 m_infile.Clear();
903 m_infile_offset = 0;
Chris Lattner24943d22010-06-08 16:52:24 +0000904 }
905
Greg Claytone9f5fbd2010-10-10 20:52:20 +0000906 FileSpec m_infile;
907 off_t m_infile_offset;
Chris Lattner24943d22010-06-08 16:52:24 +0000908 };
909
Greg Clayton238c0a12010-09-18 01:14:36 +0000910 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Inghamda26bd22012-06-08 21:56:10 +0000911 CommandObjectParsed (interpreter,
912 "memory write",
913 "Write to the memory of the process being debugged.",
914 NULL,
915 eFlagProcessMustBeLaunched),
Greg Claytona42880a2011-10-25 06:44:01 +0000916 m_option_group (interpreter),
917 m_format_options (eFormatBytes, 1, UINT64_MAX),
918 m_memory_options ()
Chris Lattner24943d22010-06-08 16:52:24 +0000919 {
Caroline Tice43b014a2010-10-04 22:28:36 +0000920 CommandArgumentEntry arg1;
921 CommandArgumentEntry arg2;
922 CommandArgumentData addr_arg;
923 CommandArgumentData value_arg;
924
925 // Define the first (and only) variant of this arg.
926 addr_arg.arg_type = eArgTypeAddress;
927 addr_arg.arg_repetition = eArgRepeatPlain;
928
929 // There is only one variant this argument could be; put it into the argument entry.
930 arg1.push_back (addr_arg);
931
932 // Define the first (and only) variant of this arg.
933 value_arg.arg_type = eArgTypeValue;
934 value_arg.arg_repetition = eArgRepeatPlus;
935
936 // There is only one variant this argument could be; put it into the argument entry.
937 arg2.push_back (value_arg);
938
939 // Push the data for the first argument into the m_arguments vector.
940 m_arguments.push_back (arg1);
941 m_arguments.push_back (arg2);
Greg Claytona42880a2011-10-25 06:44:01 +0000942
943 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
944 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
945 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
946 m_option_group.Finalize();
947
Chris Lattner24943d22010-06-08 16:52:24 +0000948 }
949
950 virtual
951 ~CommandObjectMemoryWrite ()
952 {
953 }
954
955 Options *
956 GetOptions ()
957 {
Greg Claytona42880a2011-10-25 06:44:01 +0000958 return &m_option_group;
Chris Lattner24943d22010-06-08 16:52:24 +0000959 }
960
961 bool
962 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
963 {
964 if (total_byte_size > 8)
965 return false;
966
967 if (total_byte_size == 8)
968 return true;
969
970 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
971 return uval64 <= max;
972 }
973
974 bool
975 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
976 {
977 if (total_byte_size > 8)
978 return false;
979
980 if (total_byte_size == 8)
981 return true;
982
983 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
984 const int64_t min = ~(max);
985 return min <= sval64 && sval64 <= max;
986 }
987
Jim Inghamda26bd22012-06-08 21:56:10 +0000988protected:
Chris Lattner24943d22010-06-08 16:52:24 +0000989 virtual bool
Jim Inghamda26bd22012-06-08 21:56:10 +0000990 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner24943d22010-06-08 16:52:24 +0000991 {
Greg Clayton49d888d2012-12-06 22:49:16 +0000992 ExecutionContext exe_ctx(m_interpreter.GetExecutionContext());
993 Process *process = exe_ctx.GetProcessPtr();
Chris Lattner24943d22010-06-08 16:52:24 +0000994 if (process == NULL)
995 {
996 result.AppendError("need a process to read memory");
997 result.SetStatus(eReturnStatusFailed);
998 return false;
999 }
1000
1001 const size_t argc = command.GetArgumentCount();
1002
Greg Claytona42880a2011-10-25 06:44:01 +00001003 if (m_memory_options.m_infile)
Chris Lattner24943d22010-06-08 16:52:24 +00001004 {
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001005 if (argc < 1)
1006 {
1007 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1008 result.SetStatus(eReturnStatusFailed);
1009 return false;
1010 }
1011 }
1012 else if (argc < 2)
1013 {
1014 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 +00001015 result.SetStatus(eReturnStatusFailed);
1016 return false;
1017 }
1018
Chris Lattner24943d22010-06-08 16:52:24 +00001019 StreamString buffer (Stream::eBinary,
Greg Clayton395fc332011-02-15 21:59:32 +00001020 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1021 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner24943d22010-06-08 16:52:24 +00001022
Greg Claytona42880a2011-10-25 06:44:01 +00001023 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1024 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Clayton54e7afa2010-07-09 20:39:50 +00001025
Greg Clayton49d888d2012-12-06 22:49:16 +00001026 Error error;
1027 lldb::addr_t addr = Args::StringToAddress (&exe_ctx,
1028 command.GetArgumentAtIndex(0),
1029 LLDB_INVALID_ADDRESS,
1030 &error);
Chris Lattner24943d22010-06-08 16:52:24 +00001031
1032 if (addr == LLDB_INVALID_ADDRESS)
1033 {
Greg Clayton49d888d2012-12-06 22:49:16 +00001034 result.AppendError("invalid address expression\n");
1035 result.AppendError(error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001036 result.SetStatus(eReturnStatusFailed);
1037 return false;
1038 }
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001039
Greg Claytona42880a2011-10-25 06:44:01 +00001040 if (m_memory_options.m_infile)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001041 {
1042 size_t length = SIZE_MAX;
Greg Claytona42880a2011-10-25 06:44:01 +00001043 if (item_byte_size > 0)
1044 length = item_byte_size;
1045 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001046 if (data_sp)
1047 {
1048 length = data_sp->GetByteSize();
1049 if (length > 0)
1050 {
1051 Error error;
1052 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1053
1054 if (bytes_written == length)
1055 {
1056 // All bytes written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001057 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001058 result.SetStatus(eReturnStatusSuccessFinishResult);
1059 }
1060 else if (bytes_written > 0)
1061 {
1062 // Some byte written
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001063 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 +00001064 result.SetStatus(eReturnStatusSuccessFinishResult);
1065 }
1066 else
1067 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001068 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001069 result.SetStatus(eReturnStatusFailed);
1070 }
1071 }
1072 }
1073 else
1074 {
1075 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1076 result.SetStatus(eReturnStatusFailed);
1077 }
1078 return result.Succeeded();
1079 }
Greg Claytona42880a2011-10-25 06:44:01 +00001080 else if (item_byte_size == 0)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001081 {
Greg Claytona42880a2011-10-25 06:44:01 +00001082 if (m_format_options.GetFormat() == eFormatPointer)
Greg Claytone9f5fbd2010-10-10 20:52:20 +00001083 item_byte_size = buffer.GetAddressByteSize();
1084 else
1085 item_byte_size = 1;
1086 }
1087
Chris Lattner24943d22010-06-08 16:52:24 +00001088 command.Shift(); // shift off the address argument
1089 uint64_t uval64;
1090 int64_t sval64;
1091 bool success = false;
1092 const uint32_t num_value_args = command.GetArgumentCount();
1093 uint32_t i;
1094 for (i=0; i<num_value_args; ++i)
1095 {
1096 const char *value_str = command.GetArgumentAtIndex(i);
1097
Greg Claytona42880a2011-10-25 06:44:01 +00001098 switch (m_format_options.GetFormat())
Chris Lattner24943d22010-06-08 16:52:24 +00001099 {
Greg Clayton3182eff2011-06-23 21:22:24 +00001100 case kNumFormats:
Chris Lattner24943d22010-06-08 16:52:24 +00001101 case eFormatFloat: // TODO: add support for floats soon
1102 case eFormatCharPrintable:
1103 case eFormatBytesWithASCII:
1104 case eFormatComplex:
1105 case eFormatEnum:
1106 case eFormatUnicode16:
1107 case eFormatUnicode32:
1108 case eFormatVectorOfChar:
1109 case eFormatVectorOfSInt8:
1110 case eFormatVectorOfUInt8:
1111 case eFormatVectorOfSInt16:
1112 case eFormatVectorOfUInt16:
1113 case eFormatVectorOfSInt32:
1114 case eFormatVectorOfUInt32:
1115 case eFormatVectorOfSInt64:
1116 case eFormatVectorOfUInt64:
1117 case eFormatVectorOfFloat32:
1118 case eFormatVectorOfFloat64:
1119 case eFormatVectorOfUInt128:
Greg Clayton4fdf7602011-03-20 04:57:14 +00001120 case eFormatOSType:
1121 case eFormatComplexInteger:
Greg Clayton24a6bd92011-10-27 17:55:14 +00001122 case eFormatAddressInfo:
1123 case eFormatHexFloat:
1124 case eFormatInstruction:
Sean Callanan96abc622012-08-08 17:35:10 +00001125 case eFormatVoid:
Chris Lattner24943d22010-06-08 16:52:24 +00001126 result.AppendError("unsupported format for writing memory");
1127 result.SetStatus(eReturnStatusFailed);
1128 return false;
1129
1130 case eFormatDefault:
1131 case eFormatBytes:
1132 case eFormatHex:
Enrico Granata535543d2012-08-09 19:33:34 +00001133 case eFormatHexUppercase:
Greg Clayton54e7afa2010-07-09 20:39:50 +00001134 case eFormatPointer:
1135
Chris Lattner24943d22010-06-08 16:52:24 +00001136 // Decode hex bytes
1137 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1138 if (!success)
1139 {
1140 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1141 result.SetStatus(eReturnStatusFailed);
1142 return false;
1143 }
1144 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1145 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001146 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 +00001147 result.SetStatus(eReturnStatusFailed);
1148 return false;
1149 }
1150 buffer.PutMaxHex64 (uval64, item_byte_size);
1151 break;
1152
1153 case eFormatBoolean:
1154 uval64 = Args::StringToBoolean(value_str, false, &success);
1155 if (!success)
1156 {
1157 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1158 result.SetStatus(eReturnStatusFailed);
1159 return false;
1160 }
1161 buffer.PutMaxHex64 (uval64, item_byte_size);
1162 break;
1163
1164 case eFormatBinary:
1165 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1166 if (!success)
1167 {
1168 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1169 result.SetStatus(eReturnStatusFailed);
1170 return false;
1171 }
1172 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1173 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001174 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 +00001175 result.SetStatus(eReturnStatusFailed);
1176 return false;
1177 }
1178 buffer.PutMaxHex64 (uval64, item_byte_size);
1179 break;
1180
Greg Clayton307fa072011-06-17 23:50:44 +00001181 case eFormatCharArray:
Chris Lattner24943d22010-06-08 16:52:24 +00001182 case eFormatChar:
1183 case eFormatCString:
1184 if (value_str[0])
1185 {
1186 size_t len = strlen (value_str);
1187 // Include the NULL for C strings...
Greg Claytona42880a2011-10-25 06:44:01 +00001188 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner24943d22010-06-08 16:52:24 +00001189 ++len;
1190 Error error;
1191 if (process->WriteMemory (addr, value_str, len, error) == len)
1192 {
1193 addr += len;
1194 }
1195 else
1196 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001197 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001198 result.SetStatus(eReturnStatusFailed);
1199 return false;
1200 }
1201 }
1202 break;
1203
1204 case eFormatDecimal:
1205 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1206 if (!success)
1207 {
1208 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1209 result.SetStatus(eReturnStatusFailed);
1210 return false;
1211 }
1212 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1213 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001214 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 +00001215 result.SetStatus(eReturnStatusFailed);
1216 return false;
1217 }
1218 buffer.PutMaxHex64 (sval64, item_byte_size);
1219 break;
1220
1221 case eFormatUnsigned:
1222 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1223 if (!success)
1224 {
1225 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1226 result.SetStatus(eReturnStatusFailed);
1227 return false;
1228 }
1229 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1230 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001231 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 +00001232 result.SetStatus(eReturnStatusFailed);
1233 return false;
1234 }
1235 buffer.PutMaxHex64 (uval64, item_byte_size);
1236 break;
1237
1238 case eFormatOctal:
1239 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1240 if (!success)
1241 {
1242 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1243 result.SetStatus(eReturnStatusFailed);
1244 return false;
1245 }
1246 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1247 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001248 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 +00001249 result.SetStatus(eReturnStatusFailed);
1250 return false;
1251 }
1252 buffer.PutMaxHex64 (uval64, item_byte_size);
1253 break;
1254 }
1255 }
1256
1257 if (!buffer.GetString().empty())
1258 {
1259 Error error;
Greg Clayton53d68e72010-07-20 22:52:08 +00001260 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner24943d22010-06-08 16:52:24 +00001261 return true;
1262 else
1263 {
Daniel Malea5f35a4b2012-11-29 21:49:15 +00001264 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner24943d22010-06-08 16:52:24 +00001265 result.SetStatus(eReturnStatusFailed);
1266 return false;
1267 }
1268 }
1269 return true;
1270 }
1271
Greg Claytona42880a2011-10-25 06:44:01 +00001272 OptionGroupOptions m_option_group;
1273 OptionGroupFormat m_format_options;
1274 OptionGroupWriteMemory m_memory_options;
Chris Lattner24943d22010-06-08 16:52:24 +00001275};
1276
Chris Lattner24943d22010-06-08 16:52:24 +00001277
1278//-------------------------------------------------------------------------
1279// CommandObjectMemory
1280//-------------------------------------------------------------------------
1281
Greg Clayton63094e02010-06-23 01:19:29 +00001282CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Clayton238c0a12010-09-18 01:14:36 +00001283 CommandObjectMultiword (interpreter,
1284 "memory",
Caroline Ticec1ad82e2010-09-07 22:38:08 +00001285 "A set of commands for operating on memory.",
Chris Lattner24943d22010-06-08 16:52:24 +00001286 "memory <subcommand> [<subcommand-options>]")
1287{
Greg Clayton238c0a12010-09-18 01:14:36 +00001288 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1289 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Chris Lattner24943d22010-06-08 16:52:24 +00001290}
1291
1292CommandObjectMemory::~CommandObjectMemory ()
1293{
1294}