blob: 23da6e28920dedae0d614819a124526292f43cf7 [file] [log] [blame]
Chris Lattner30fdc8d2010-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 Malea93a64302012-12-05 00:20:57 +000010#include "lldb/lldb-python.h"
11
Chris Lattner30fdc8d2010-06-08 16:52:24 +000012#include "CommandObjectMemory.h"
13
14// C Includes
Virgile Bellobdae3782013-08-28 12:14:27 +000015#include <inttypes.h>
16
Chris Lattner30fdc8d2010-06-08 16:52:24 +000017// C++ Includes
18// Other libraries and framework includes
Zachary Turnera78bd7f2015-03-03 23:11:11 +000019#include "clang/AST/Decl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000020// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000021#include "lldb/Core/DataBufferHeap.h"
22#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000023#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000024#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000026#include "lldb/Core/ValueObjectMemory.h"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000027#include "lldb/DataFormatters/ValueObjectPrinter.h"
Zachary Turneraf0f45f2015-03-03 21:05:17 +000028#include "lldb/Expression/ClangPersistentVariables.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000029#include "lldb/Host/StringConvert.h"
Greg Clayton66111032010-06-23 01:19:29 +000030#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000031#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000032#include "lldb/Interpreter/CommandInterpreter.h"
33#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000034#include "lldb/Interpreter/OptionGroupFormat.h"
35#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000036#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000037#include "lldb/Interpreter/OptionValueString.h"
Greg Clayton1f746072012-08-29 21:13:06 +000038#include "lldb/Symbol/TypeList.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000039#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000040#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000041#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000042#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000043
44using namespace lldb;
45using namespace lldb_private;
46
Greg Clayton68ebae62011-04-28 20:55:26 +000047static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000048g_option_table[] =
49{
Zachary Turnerd37221d2014-07-09 16:31:49 +000050 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
51 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , NULL, 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."},
52 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
Greg Clayton2346fcf2012-11-02 21:14:58 +000053 { LLDB_OPT_SET_1|
54 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000055 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
Greg Clayton84c39662011-04-27 22:04:39 +000056};
57
58
59
60class OptionGroupReadMemory : public OptionGroup
61{
62public:
63
64 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000065 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000066 m_output_as_binary (false),
67 m_view_as_type()
68 {
69 }
70
71 virtual
72 ~OptionGroupReadMemory ()
73 {
74 }
75
76
77 virtual uint32_t
78 GetNumDefinitions ()
79 {
80 return sizeof (g_option_table) / sizeof (OptionDefinition);
81 }
82
83 virtual const OptionDefinition*
84 GetDefinitions ()
85 {
86 return g_option_table;
87 }
88
89 virtual Error
90 SetOptionValue (CommandInterpreter &interpreter,
91 uint32_t option_idx,
92 const char *option_arg)
93 {
94 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000095 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000096
97 switch (short_option)
98 {
99 case 'l':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000100 error = m_num_per_line.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000101 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000102 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000103 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000104
Greg Clayton84c39662011-04-27 22:04:39 +0000105 case 'b':
106 m_output_as_binary = true;
107 break;
108
109 case 't':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000110 error = m_view_as_type.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000111 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000112
113 case 'r':
114 m_force = true;
115 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000116
117 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000118 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000119 break;
120 }
121 return error;
122 }
123
124 virtual void
125 OptionParsingStarting (CommandInterpreter &interpreter)
126 {
Greg Clayton84c39662011-04-27 22:04:39 +0000127 m_num_per_line.Clear();
128 m_output_as_binary = false;
129 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000130 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000131 }
132
Greg Clayton68ebae62011-04-28 20:55:26 +0000133 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000134 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000135 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000136 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000137 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
138 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000139 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000140 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000141 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000142
Greg Clayton68ebae62011-04-28 20:55:26 +0000143 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000144 {
145 default:
146 break;
147
148 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000149 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000150 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000151 if (!num_per_line_option_set)
152 m_num_per_line = 1;
153 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000154 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000155 break;
156
157 case eFormatCString:
158 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000159
160 case eFormatInstruction:
161 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000162 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000163 m_num_per_line = 1;
164 break;
165
166 case eFormatAddressInfo:
167 if (!byte_size_option_set)
168 byte_size_value = target->GetArchitecture().GetAddressByteSize();
169 m_num_per_line = 1;
170 if (!count_option_set)
171 format_options.GetCountValue() = 8;
172 break;
173
Greg Clayton84c39662011-04-27 22:04:39 +0000174 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000175 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000176 if (!num_per_line_option_set)
177 m_num_per_line = 4;
178 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000179 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000180 break;
181
182 case eFormatBinary:
183 case eFormatFloat:
184 case eFormatOctal:
185 case eFormatDecimal:
186 case eFormatEnum:
187 case eFormatUnicode16:
188 case eFormatUnicode32:
189 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000190 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000191 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000192 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000193 if (!num_per_line_option_set)
194 m_num_per_line = 1;
195 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000196 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000197 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000198
Greg Clayton84c39662011-04-27 22:04:39 +0000199 case eFormatBytes:
200 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000201 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000202 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000203 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000204 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000205 "\tconsider using a different display format or don't specify the byte size",
206 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000207 }
208 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000209 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000210 if (!num_per_line_option_set)
211 m_num_per_line = 16;
212 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000213 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000214 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000215 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000216 case eFormatChar:
217 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000218 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000219 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000220 if (!num_per_line_option_set)
221 m_num_per_line = 32;
222 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000223 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000224 break;
225 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000226 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000227 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000228 if (!num_per_line_option_set)
229 m_num_per_line = 1;
230 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000231 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000232 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000233 case eFormatComplexInteger:
234 if (!byte_size_option_set)
235 byte_size_value = 8;
236 if (!num_per_line_option_set)
237 m_num_per_line = 1;
238 if (!count_option_set)
239 format_options.GetCountValue() = 8;
240 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000241 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000242 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000243 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000244 if (!num_per_line_option_set)
245 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000246 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000247 {
248 case 1:
249 case 2:
250 m_num_per_line = 8;
251 break;
252 case 4:
253 m_num_per_line = 4;
254 break;
255 case 8:
256 m_num_per_line = 2;
257 break;
258 default:
259 m_num_per_line = 1;
260 break;
261 }
262 }
263 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000264 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000265 break;
266
267 case eFormatVectorOfChar:
268 case eFormatVectorOfSInt8:
269 case eFormatVectorOfUInt8:
270 case eFormatVectorOfSInt16:
271 case eFormatVectorOfUInt16:
272 case eFormatVectorOfSInt32:
273 case eFormatVectorOfUInt32:
274 case eFormatVectorOfSInt64:
275 case eFormatVectorOfUInt64:
276 case eFormatVectorOfFloat32:
277 case eFormatVectorOfFloat64:
278 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000279 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000280 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000281 if (!num_per_line_option_set)
282 m_num_per_line = 1;
283 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000284 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000285 break;
286 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000287 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000288 }
289
Greg Clayton82f4cf42011-10-26 04:32:38 +0000290 bool
291 AnyOptionWasSet () const
292 {
293 return m_num_per_line.OptionWasSet() ||
294 m_output_as_binary ||
295 m_view_as_type.OptionWasSet();
296 }
297
Greg Clayton84c39662011-04-27 22:04:39 +0000298 OptionValueUInt64 m_num_per_line;
299 bool m_output_as_binary;
300 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000301 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000302};
303
304
305
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306//----------------------------------------------------------------------
307// Read memory from the inferior process
308//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000309class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310{
311public:
312
Greg Claytona7015092010-09-18 01:14:36 +0000313 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000314 CommandObjectParsed (interpreter,
315 "memory read",
316 "Read from the memory of the process being debugged.",
317 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +0000318 eFlagRequiresTarget | eFlagProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000319 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000320 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000321 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000322 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000323 m_varobj_options(),
324 m_next_addr(LLDB_INVALID_ADDRESS),
325 m_prev_byte_size(0),
326 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
327 m_prev_memory_options (),
328 m_prev_outfile_options (),
329 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000330 {
Caroline Tice405fe672010-10-04 22:28:36 +0000331 CommandArgumentEntry arg1;
332 CommandArgumentEntry arg2;
333 CommandArgumentData start_addr_arg;
334 CommandArgumentData end_addr_arg;
335
336 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000337 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000338 start_addr_arg.arg_repetition = eArgRepeatPlain;
339
340 // There is only one variant this argument could be; put it into the argument entry.
341 arg1.push_back (start_addr_arg);
342
343 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000344 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000345 end_addr_arg.arg_repetition = eArgRepeatOptional;
346
347 // There is only one variant this argument could be; put it into the argument entry.
348 arg2.push_back (end_addr_arg);
349
350 // Push the data for the first argument into the m_arguments vector.
351 m_arguments.push_back (arg1);
352 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000353
Greg Clayton1deb7962011-10-25 06:44:01 +0000354 // Add the "--format" and "--count" options to group 1 and 3
355 m_option_group.Append (&m_format_options,
356 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000357 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000358 m_option_group.Append (&m_format_options,
359 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000360 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000361 // Add the "--size" option to group 1 and 2
362 m_option_group.Append (&m_format_options,
363 OptionGroupFormat::OPTION_GROUP_SIZE,
364 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000365 m_option_group.Append (&m_memory_options);
366 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton68ebae62011-04-28 20:55:26 +0000367 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000368 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000369 }
370
371 virtual
372 ~CommandObjectMemoryRead ()
373 {
374 }
375
376 Options *
377 GetOptions ()
378 {
Greg Clayton84c39662011-04-27 22:04:39 +0000379 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000380 }
381
Greg Clayton82f4cf42011-10-26 04:32:38 +0000382 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
383 {
384 return m_cmd_name.c_str();
385 }
386
Jim Ingham5a988412012-06-08 21:56:10 +0000387protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 virtual bool
Greg Claytonb9d5df52012-12-06 22:49:16 +0000389 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000390 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000391 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
392 Target *target = m_exe_ctx.GetTargetPtr();
393
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000394 const size_t argc = command.GetArgumentCount();
395
Greg Clayton82f4cf42011-10-26 04:32:38 +0000396 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000397 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000398 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
Greg Clayton2e1f7452012-12-15 02:08:17 +0000399 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000400 result.SetStatus(eReturnStatusFailed);
401 return false;
402 }
403
Greg Clayton68ebae62011-04-28 20:55:26 +0000404 ClangASTType clang_ast_type;
405 Error error;
406
Greg Clayton84c39662011-04-27 22:04:39 +0000407 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
408 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000409 {
Greg Clayton84c39662011-04-27 22:04:39 +0000410 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000411
Greg Clayton84c39662011-04-27 22:04:39 +0000412 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000413 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000414 TypeList type_list;
415 uint32_t reference_count = 0;
416 uint32_t pointer_count = 0;
417 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000418
419#define ALL_KEYWORDS \
420 KEYWORD("const") \
421 KEYWORD("volatile") \
422 KEYWORD("restrict") \
423 KEYWORD("struct") \
424 KEYWORD("class") \
425 KEYWORD("union")
426
427#define KEYWORD(s) s,
428 static const char *g_keywords[] =
429 {
430 ALL_KEYWORDS
431 };
432#undef KEYWORD
433
434#define KEYWORD(s) (sizeof(s) - 1),
435 static const int g_keyword_lengths[] =
436 {
437 ALL_KEYWORDS
438 };
439#undef KEYWORD
440
441#undef ALL_KEYWORDS
442
443 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000444 std::string type_str(view_as_type_cstr);
445
446 // Remove all instances of g_keywords that are followed by spaces
447 for (size_t i = 0; i < g_num_keywords; ++i)
448 {
449 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000450 int keyword_len = g_keyword_lengths[i];
451
452 idx = 0;
453 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000454 {
455 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000456 {
Greg Clayton84c39662011-04-27 22:04:39 +0000457 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000458 idx = 0;
459 }
460 else
461 {
462 idx += keyword_len;
463 }
Greg Clayton84c39662011-04-27 22:04:39 +0000464 }
465 }
466 bool done = type_str.empty();
467 //
468 idx = type_str.find_first_not_of (" \t");
469 if (idx > 0 && idx != std::string::npos)
470 type_str.erase (0, idx);
471 while (!done)
472 {
473 // Strip trailing spaces
474 if (type_str.empty())
475 done = true;
476 else
477 {
478 switch (type_str[type_str.size()-1])
479 {
480 case '*':
481 ++pointer_count;
482 // fall through...
483 case ' ':
484 case '\t':
485 type_str.erase(type_str.size()-1);
486 break;
487
488 case '&':
489 if (reference_count == 0)
490 {
491 reference_count = 1;
492 type_str.erase(type_str.size()-1);
493 }
494 else
495 {
496 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
497 result.SetStatus(eReturnStatusFailed);
498 return false;
499 }
500 break;
501
502 default:
503 done = true;
504 break;
505 }
506 }
507 }
508
509 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000510 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000511 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000512 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000513 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000514 if (sc.module_sp)
515 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000516 sc.module_sp->FindTypes (sc,
517 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000518 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000519 1,
520 type_list);
521 }
522 }
523 if (type_list.GetSize() == 0)
524 {
Greg Clayton29399a22012-04-06 17:41:13 +0000525 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000526 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000527 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000528 1,
529 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000530 }
531
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000532 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000533 {
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000534 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
535 if (tdecl)
536 {
537 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
538 }
Greg Clayton84c39662011-04-27 22:04:39 +0000539 }
540
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000541 if (clang_ast_type.IsValid() == false)
542 {
543 if (type_list.GetSize() == 0)
544 {
545 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
546 lookup_type_name.GetCString(),
547 view_as_type_cstr);
548 result.SetStatus(eReturnStatusFailed);
549 return false;
550 }
551 else
552 {
553 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton57ee3062013-07-11 22:46:58 +0000554 clang_ast_type = type_sp->GetClangFullType();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000555 }
556 }
Greg Clayton84c39662011-04-27 22:04:39 +0000557
558 while (pointer_count > 0)
559 {
Greg Clayton57ee3062013-07-11 22:46:58 +0000560 ClangASTType pointer_type = clang_ast_type.GetPointerType();
561 if (pointer_type.IsValid())
562 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000563 else
564 {
565 result.AppendError ("unable make a pointer type\n");
566 result.SetStatus(eReturnStatusFailed);
567 return false;
568 }
569 --pointer_count;
570 }
571
Enrico Granata1cd5e922015-01-28 00:07:51 +0000572 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000573
Greg Clayton1deb7962011-10-25 06:44:01 +0000574 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000575 {
576 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
577 view_as_type_cstr);
578 result.SetStatus(eReturnStatusFailed);
579 return false;
580 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000581
Greg Clayton1deb7962011-10-25 06:44:01 +0000582 if (!m_format_options.GetCountValue().OptionWasSet())
583 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000584 }
585 else
586 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000587 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000588 }
589
590 // Look for invalid combinations of settings
591 if (error.Fail())
592 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000593 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000594 result.SetStatus(eReturnStatusFailed);
595 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000596 }
597
Greg Clayton82f4cf42011-10-26 04:32:38 +0000598 lldb::addr_t addr;
599 size_t total_byte_size = 0;
600 if (argc == 0)
601 {
602 // Use the last address and byte size and all options as they were
603 // if no options have been set
604 addr = m_next_addr;
605 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000606 clang_ast_type = m_prev_clang_ast_type;
607 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000608 !m_memory_options.AnyOptionWasSet() &&
609 !m_outfile_options.AnyOptionWasSet() &&
610 !m_varobj_options.AnyOptionWasSet())
611 {
612 m_format_options = m_prev_format_options;
613 m_memory_options = m_prev_memory_options;
614 m_outfile_options = m_prev_outfile_options;
615 m_varobj_options = m_prev_varobj_options;
616 }
617 }
618
Greg Clayton1deb7962011-10-25 06:44:01 +0000619 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000620
621 // TODO For non-8-bit byte addressable architectures this needs to be
622 // revisited to fully support all lldb's range of formatting options.
623 // Furthermore code memory reads (for those architectures) will not
624 // be correctly formatted even w/o formatting options.
625 size_t item_byte_size =
626 target->GetArchitecture().GetDataByteSize() > 1 ?
627 target->GetArchitecture().GetDataByteSize() :
628 m_format_options.GetByteSizeValue().GetCurrentValue();
629
Greg Clayton68ebae62011-04-28 20:55:26 +0000630 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000632 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000633 {
634 total_byte_size = item_count * item_byte_size;
635 if (total_byte_size == 0)
636 total_byte_size = 32;
637 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000638
Greg Clayton82f4cf42011-10-26 04:32:38 +0000639 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000640 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000641
642 if (addr == LLDB_INVALID_ADDRESS)
643 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000644 result.AppendError("invalid start address expression.");
645 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000646 result.SetStatus(eReturnStatusFailed);
647 return false;
648 }
649
650 if (argc == 2)
651 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000652 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000653 if (end_addr == LLDB_INVALID_ADDRESS)
654 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000655 result.AppendError("invalid end address expression.");
656 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657 result.SetStatus(eReturnStatusFailed);
658 return false;
659 }
660 else if (end_addr <= addr)
661 {
Daniel Malead01b2952012-11-29 21:49:15 +0000662 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000663 result.SetStatus(eReturnStatusFailed);
664 return false;
665 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000666 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000667 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000668 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %" PRIu64 "), not both.\n", end_addr, (uint64_t)item_count);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000669 result.SetStatus(eReturnStatusFailed);
670 return false;
671 }
672
673 total_byte_size = end_addr - addr;
674 item_count = total_byte_size / item_byte_size;
675 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000676
Enrico Granatad325bf92013-06-04 22:54:16 +0000677 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
678
679 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000680 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000681 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
682 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
683 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
Sean Callanan1276c332012-04-28 01:27:38 +0000684 return false;
685 }
686
Greg Clayton84c39662011-04-27 22:04:39 +0000687 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000688 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000689 if (clang_ast_type.GetOpaqueQualType())
690 {
691 // Make sure we don't display our type as ASCII bytes like the default memory read
692 if (m_format_options.GetFormatValue().OptionWasSet() == false)
693 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
694
Enrico Granata1cd5e922015-01-28 00:07:51 +0000695 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000696 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000697 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000698 {
Greg Clayton84c39662011-04-27 22:04:39 +0000699 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000700 if (data_sp->GetBytes() == NULL)
701 {
Virgile Belloffeba252014-03-08 17:15:35 +0000702 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx32 " bytes for the memory read buffer, specify a smaller size to read", (uint32_t)total_byte_size);
Greg Clayton46a44262013-07-24 18:17:35 +0000703 result.SetStatus(eReturnStatusFailed);
704 return false;
705 }
706
Greg Claytone72dfb32012-02-24 01:59:29 +0000707 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000708 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000709 if (bytes_read == 0)
710 {
Greg Clayton57f06302012-05-25 17:05:55 +0000711 const char *error_cstr = error.AsCString();
712 if (error_cstr && error_cstr[0])
713 {
714 result.AppendError(error_cstr);
715 }
716 else
717 {
Daniel Malead01b2952012-11-29 21:49:15 +0000718 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000719 }
Greg Clayton84c39662011-04-27 22:04:39 +0000720 result.SetStatus(eReturnStatusFailed);
721 return false;
722 }
723
724 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000725 result.AppendWarningWithFormat("Not all bytes (%" PRIu64 "/%" PRIu64 ") were able to be read from 0x%" PRIx64 ".\n", (uint64_t)bytes_read, (uint64_t)total_byte_size, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000726 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000727 else
728 {
729 // we treat c-strings as a special case because they do not have a fixed size
730 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
731 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
732 else
733 item_byte_size = target->GetMaximumSizeOfStringSummary();
734 if (!m_format_options.GetCountValue().OptionWasSet())
735 item_count = 1;
736 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000737 if (data_sp->GetBytes() == NULL)
738 {
739 result.AppendErrorWithFormat ("can't allocate 0x%" PRIx64 " bytes for the memory read buffer, specify a smaller size to read", (uint64_t)((item_byte_size+1) * item_count));
740 result.SetStatus(eReturnStatusFailed);
741 return false;
742 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000743 uint8_t *data_ptr = data_sp->GetBytes();
744 auto data_addr = addr;
745 auto count = item_count;
746 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000747 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000748 while (item_count < count)
749 {
750 std::string buffer;
751 buffer.resize(item_byte_size+1,0);
752 Error error;
753 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
754 if (error.Fail())
755 {
756 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
757 result.SetStatus(eReturnStatusFailed);
758 return false;
759 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000760
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000761 if (item_byte_size == read)
762 {
763 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000764 --read;
765 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000766 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000767 else
768 ++read; // account for final NULL byte
769
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000770 memcpy(data_ptr, &buffer[0], read);
771 data_ptr += read;
772 data_addr += read;
773 bytes_read += read;
774 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000775
776 if (break_on_no_NULL)
777 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000778 }
779 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
780 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000781
Greg Clayton2e1f7452012-12-15 02:08:17 +0000782 m_next_addr = addr + bytes_read;
783 m_prev_byte_size = bytes_read;
784 m_prev_format_options = m_format_options;
785 m_prev_memory_options = m_memory_options;
786 m_prev_outfile_options = m_outfile_options;
787 m_prev_varobj_options = m_varobj_options;
788 m_prev_clang_ast_type = clang_ast_type;
789
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000790 StreamFile outfile_stream;
791 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000792 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
793 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000794 {
795 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000796 outfile_spec.GetPath (path, sizeof(path));
797
798 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
799 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
800 if (append)
801 open_options |= File::eOpenOptionAppend;
802
803 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000804 {
Greg Clayton84c39662011-04-27 22:04:39 +0000805 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000806 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000807 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000808 if (bytes_written > 0)
809 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000810 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000811 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000812 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000813 path);
814 return true;
815 }
816 else
817 {
Daniel Malead01b2952012-11-29 21:49:15 +0000818 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000819 result.SetStatus(eReturnStatusFailed);
820 return false;
821 }
822 }
823 else
824 {
825 // We are going to write ASCII to the file just point the
826 // output_stream to our outfile_stream...
827 output_stream = &outfile_stream;
828 }
829 }
830 else
831 {
Greg Clayton84c39662011-04-27 22:04:39 +0000832 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000833 result.SetStatus(eReturnStatusFailed);
834 return false;
835 }
836 }
837 else
838 {
839 output_stream = &result.GetOutputStream();
840 }
841
Greg Clayton84c39662011-04-27 22:04:39 +0000842
Greg Claytonf9fc6092013-01-09 19:44:40 +0000843 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000844 if (clang_ast_type.GetOpaqueQualType())
845 {
846 for (uint32_t i = 0; i<item_count; ++i)
847 {
848 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000849 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000850 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000851 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000852 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000853 name_strm.GetString().c_str(),
854 address,
855 clang_ast_type));
856 if (valobj_sp)
857 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000858 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000859 if (format != eFormatDefault)
860 valobj_sp->SetFormat (format);
861
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000862 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000863
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000864 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000865 }
866 else
867 {
868 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
869 view_as_type_cstr,
870 name_strm.GetString().c_str());
871 result.SetStatus(eReturnStatusFailed);
872 return false;
873 }
874 }
875 return true;
876 }
877
878 result.SetStatus(eReturnStatusSuccessFinishResult);
879 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000880 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000881 target->GetArchitecture().GetAddressByteSize(),
882 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000883
884 Format format = m_format_options.GetFormat();
885 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000886 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000887 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000888 // if a count was not passed, or it is 1
889 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
890 {
891 // this turns requests such as
892 // memory read -fc -s10 -c1 *charPtrPtr
893 // which make no sense (what is a char of size 10?)
894 // into a request for fetching 10 chars of size 1 from the same memory location
895 format = eFormatCharArray;
896 item_count = item_byte_size;
897 item_byte_size = 1;
898 }
899 else
900 {
901 // here we passed a count, and it was not 1
902 // so we have a byte_size and a count
903 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000904 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000905 result.SetStatus(eReturnStatusFailed);
906 return false;
907 }
Enrico Granata31898912013-05-21 17:39:04 +0000908 }
Greg Clayton84c39662011-04-27 22:04:39 +0000909
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000910 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000911 size_t bytes_dumped = data.Dump (output_stream,
912 0,
Enrico Granata31898912013-05-21 17:39:04 +0000913 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000914 item_byte_size,
915 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000916 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000917 addr,
918 0,
919 0,
920 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000921 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000922 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000923 return true;
924 }
925
Greg Clayton84c39662011-04-27 22:04:39 +0000926 OptionGroupOptions m_option_group;
927 OptionGroupFormat m_format_options;
928 OptionGroupReadMemory m_memory_options;
929 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000930 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000931 lldb::addr_t m_next_addr;
932 lldb::addr_t m_prev_byte_size;
933 OptionGroupFormat m_prev_format_options;
934 OptionGroupReadMemory m_prev_memory_options;
935 OptionGroupOutputFile m_prev_outfile_options;
936 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000937 ClangASTType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000938};
939
Enrico Granata53468432013-11-13 02:18:44 +0000940OptionDefinition
941g_memory_find_option_table[] =
942{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000943 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
944 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
945 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
946 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
Enrico Granata53468432013-11-13 02:18:44 +0000947};
948
Enrico Granata53468432013-11-13 02:18:44 +0000949//----------------------------------------------------------------------
950// Find the specified data in memory
951//----------------------------------------------------------------------
952class CommandObjectMemoryFind : public CommandObjectParsed
953{
954public:
955
956 class OptionGroupFindMemory : public OptionGroup
957 {
958 public:
959 OptionGroupFindMemory () :
960 OptionGroup(),
961 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000962 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000963 {
964 }
965
966 virtual
967 ~OptionGroupFindMemory ()
968 {
969 }
970
971 virtual uint32_t
972 GetNumDefinitions ()
973 {
974 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
975 }
976
977 virtual const OptionDefinition*
978 GetDefinitions ()
979 {
980 return g_memory_find_option_table;
981 }
982
983 virtual Error
984 SetOptionValue (CommandInterpreter &interpreter,
985 uint32_t option_idx,
986 const char *option_arg)
987 {
988 Error error;
989 const int short_option = g_memory_find_option_table[option_idx].short_option;
990
991 switch (short_option)
992 {
993 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000994 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000995 break;
996
997 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000998 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000999 break;
1000
1001 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001002 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001003 error.SetErrorString("unrecognized value for count");
1004 break;
1005
Enrico Granata8d81a842013-11-13 20:08:30 +00001006 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001007 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001008 error.SetErrorString("unrecognized value for dump-offset");
1009 break;
1010
Enrico Granata53468432013-11-13 02:18:44 +00001011 default:
1012 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1013 break;
1014 }
1015 return error;
1016 }
1017
1018 virtual void
1019 OptionParsingStarting (CommandInterpreter &interpreter)
1020 {
1021 m_expr.Clear();
1022 m_string.Clear();
1023 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001024 }
1025
1026 OptionValueString m_expr;
1027 OptionValueString m_string;
1028 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001029 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001030 };
1031
1032 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1033 CommandObjectParsed (interpreter,
1034 "memory find",
1035 "Find a value in the memory of the process being debugged.",
1036 NULL,
1037 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1038 m_option_group (interpreter),
1039 m_memory_options ()
1040 {
1041 CommandArgumentEntry arg1;
1042 CommandArgumentEntry arg2;
1043 CommandArgumentData addr_arg;
1044 CommandArgumentData value_arg;
1045
1046 // Define the first (and only) variant of this arg.
1047 addr_arg.arg_type = eArgTypeAddress;
1048 addr_arg.arg_repetition = eArgRepeatPlain;
1049
1050 // There is only one variant this argument could be; put it into the argument entry.
1051 arg1.push_back (addr_arg);
1052
1053 // Define the first (and only) variant of this arg.
1054 value_arg.arg_type = eArgTypeValue;
1055 value_arg.arg_repetition = eArgRepeatPlus;
1056
1057 // There is only one variant this argument could be; put it into the argument entry.
1058 arg2.push_back (value_arg);
1059
1060 // Push the data for the first argument into the m_arguments vector.
1061 m_arguments.push_back (arg1);
1062 m_arguments.push_back (arg2);
1063
1064 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1065 m_option_group.Finalize();
1066 }
1067
1068 virtual
1069 ~CommandObjectMemoryFind ()
1070 {
1071 }
1072
1073 Options *
1074 GetOptions ()
1075 {
1076 return &m_option_group;
1077 }
1078
1079protected:
1080 virtual bool
1081 DoExecute (Args& command, CommandReturnObject &result)
1082 {
1083 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1084 Process *process = m_exe_ctx.GetProcessPtr();
1085
1086 const size_t argc = command.GetArgumentCount();
1087
1088 if (argc != 2)
1089 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001090 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001091 return false;
1092 }
1093
1094 Error error;
1095 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1096 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1097 {
1098 result.AppendError("invalid low address");
1099 return false;
1100 }
1101 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1102 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1103 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001104 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001105 return false;
1106 }
1107
1108 if (high_addr <= low_addr)
1109 {
1110 result.AppendError("starting address must be smaller than ending address");
1111 return false;
1112 }
1113
1114 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1115
1116 DataBufferHeap buffer;
1117
1118 if (m_memory_options.m_string.OptionWasSet())
1119 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1120 else if (m_memory_options.m_expr.OptionWasSet())
1121 {
1122 StackFrame* frame = m_exe_ctx.GetFramePtr();
1123 ValueObjectSP result_sp;
1124 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1125 {
1126 uint64_t value = result_sp->GetValueAsUnsigned(0);
Enrico Granata1cd5e922015-01-28 00:07:51 +00001127 switch (result_sp->GetClangType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001128 {
1129 case 1: {
1130 uint8_t byte = (uint8_t)value;
1131 buffer.CopyData(&byte,1);
1132 }
1133 break;
1134 case 2: {
1135 uint16_t word = (uint16_t)value;
1136 buffer.CopyData(&word,2);
1137 }
1138 break;
1139 case 4: {
1140 uint32_t lword = (uint32_t)value;
1141 buffer.CopyData(&lword,4);
1142 }
1143 break;
1144 case 8: {
1145 buffer.CopyData(&value, 8);
1146 }
1147 break;
1148 case 3:
1149 case 5:
1150 case 6:
1151 case 7:
1152 result.AppendError("unknown type. pass a string instead");
1153 return false;
1154 default:
1155 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1156 return false;
1157 }
1158 }
1159 else
1160 {
1161 result.AppendError("expression evaluation failed. pass a string instead?");
1162 return false;
1163 }
1164 }
1165 else
1166 {
1167 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1168 return false;
1169 }
1170
1171 size_t count = m_memory_options.m_count.GetCurrentValue();
1172 found_location = low_addr;
1173 bool ever_found = false;
1174 while (count)
1175 {
1176 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1177 if (found_location == LLDB_INVALID_ADDRESS)
1178 {
1179 if (!ever_found)
1180 {
1181 result.AppendMessage("Your data was not found within the range.\n");
1182 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1183 }
1184 else
1185 result.AppendMessage("No more matches found within the range.\n");
1186 break;
1187 }
1188 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001189
1190 DataBufferHeap dumpbuffer(32,0);
1191 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1192 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001193 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001194 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1195 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1196 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001197 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001198
Enrico Granata53468432013-11-13 02:18:44 +00001199 --count;
1200 found_location++;
1201 ever_found = true;
1202 }
1203
1204 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1205 return true;
1206 }
1207
1208 lldb::addr_t
1209 Search (lldb::addr_t low,
1210 lldb::addr_t high,
1211 uint8_t* buffer,
1212 size_t buffer_size)
1213 {
1214 Process *process = m_exe_ctx.GetProcessPtr();
1215 DataBufferHeap heap(buffer_size, 0);
1216 lldb::addr_t fictional_ptr = low;
1217 for (auto ptr = low;
1218 low < high;
1219 fictional_ptr++)
1220 {
1221 Error error;
1222 if (ptr == low || buffer_size == 1)
1223 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1224 else
1225 {
1226 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1227 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1228 }
1229 if (error.Fail())
1230 return LLDB_INVALID_ADDRESS;
1231 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1232 return fictional_ptr;
1233 if (ptr == low)
1234 ptr += buffer_size;
1235 else
1236 ptr += 1;
1237 }
1238 return LLDB_INVALID_ADDRESS;
1239 }
1240
1241 OptionGroupOptions m_option_group;
1242 OptionGroupFindMemory m_memory_options;
1243};
1244
Greg Clayton1deb7962011-10-25 06:44:01 +00001245
1246OptionDefinition
1247g_memory_write_option_table[] =
1248{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001249{ LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
Bruce Mitchener350b78e2014-07-10 14:45:57 +00001250{ LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."},
Greg Clayton1deb7962011-10-25 06:44:01 +00001251};
1252
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001253//----------------------------------------------------------------------
1254// Write memory to the inferior process
1255//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001256class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001257{
1258public:
1259
Greg Clayton1deb7962011-10-25 06:44:01 +00001260 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001261 {
1262 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001263 OptionGroupWriteMemory () :
1264 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001265 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001266 }
1267
1268 virtual
Greg Clayton1deb7962011-10-25 06:44:01 +00001269 ~OptionGroupWriteMemory ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001270 {
1271 }
1272
Greg Clayton1deb7962011-10-25 06:44:01 +00001273 virtual uint32_t
1274 GetNumDefinitions ()
1275 {
1276 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1277 }
Enrico Granata53468432013-11-13 02:18:44 +00001278
Greg Clayton1deb7962011-10-25 06:44:01 +00001279 virtual const OptionDefinition*
1280 GetDefinitions ()
1281 {
1282 return g_memory_write_option_table;
1283 }
Enrico Granata53468432013-11-13 02:18:44 +00001284
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001285 virtual Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001286 SetOptionValue (CommandInterpreter &interpreter,
1287 uint32_t option_idx,
1288 const char *option_arg)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001289 {
1290 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001291 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001292
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001293 switch (short_option)
1294 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001295 case 'i':
1296 m_infile.SetFile (option_arg, true);
1297 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001298 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001299 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001300 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001301 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001302 break;
Enrico Granata53468432013-11-13 02:18:44 +00001303
Greg Clayton1deb7962011-10-25 06:44:01 +00001304 case 'o':
1305 {
1306 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001307 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001308 if (!success)
1309 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001310 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001311 }
1312 }
1313 break;
1314
1315 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001316 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001317 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001318 }
1319 return error;
1320 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001321
1322 virtual void
1323 OptionParsingStarting (CommandInterpreter &interpreter)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001324 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001325 m_infile.Clear();
1326 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001327 }
1328
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001329 FileSpec m_infile;
1330 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001331 };
1332
Greg Claytona7015092010-09-18 01:14:36 +00001333 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001334 CommandObjectParsed (interpreter,
1335 "memory write",
1336 "Write to the memory of the process being debugged.",
1337 NULL,
Greg Claytonf9fc6092013-01-09 19:44:40 +00001338 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001339 m_option_group (interpreter),
1340 m_format_options (eFormatBytes, 1, UINT64_MAX),
1341 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001342 {
Caroline Tice405fe672010-10-04 22:28:36 +00001343 CommandArgumentEntry arg1;
1344 CommandArgumentEntry arg2;
1345 CommandArgumentData addr_arg;
1346 CommandArgumentData value_arg;
1347
1348 // Define the first (and only) variant of this arg.
1349 addr_arg.arg_type = eArgTypeAddress;
1350 addr_arg.arg_repetition = eArgRepeatPlain;
1351
1352 // There is only one variant this argument could be; put it into the argument entry.
1353 arg1.push_back (addr_arg);
1354
1355 // Define the first (and only) variant of this arg.
1356 value_arg.arg_type = eArgTypeValue;
1357 value_arg.arg_repetition = eArgRepeatPlus;
1358
1359 // There is only one variant this argument could be; put it into the argument entry.
1360 arg2.push_back (value_arg);
1361
1362 // Push the data for the first argument into the m_arguments vector.
1363 m_arguments.push_back (arg1);
1364 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001365
1366 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1367 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1368 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1369 m_option_group.Finalize();
1370
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001371 }
1372
1373 virtual
1374 ~CommandObjectMemoryWrite ()
1375 {
1376 }
1377
1378 Options *
1379 GetOptions ()
1380 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001381 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001382 }
1383
1384 bool
1385 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1386 {
1387 if (total_byte_size > 8)
1388 return false;
1389
1390 if (total_byte_size == 8)
1391 return true;
1392
1393 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1394 return uval64 <= max;
1395 }
1396
1397 bool
1398 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1399 {
1400 if (total_byte_size > 8)
1401 return false;
1402
1403 if (total_byte_size == 8)
1404 return true;
1405
1406 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1407 const int64_t min = ~(max);
1408 return min <= sval64 && sval64 <= max;
1409 }
1410
Jim Ingham5a988412012-06-08 21:56:10 +00001411protected:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001412 virtual bool
Jim Ingham5a988412012-06-08 21:56:10 +00001413 DoExecute (Args& command, CommandReturnObject &result)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001414 {
Greg Claytonf9fc6092013-01-09 19:44:40 +00001415 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1416 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001417
1418 const size_t argc = command.GetArgumentCount();
1419
Greg Clayton1deb7962011-10-25 06:44:01 +00001420 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001421 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001422 if (argc < 1)
1423 {
1424 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1425 result.SetStatus(eReturnStatusFailed);
1426 return false;
1427 }
1428 }
1429 else if (argc < 2)
1430 {
1431 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001432 result.SetStatus(eReturnStatusFailed);
1433 return false;
1434 }
1435
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001436 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001437 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1438 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001439
Greg Clayton1deb7962011-10-25 06:44:01 +00001440 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1441 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001442
Greg Claytonb9d5df52012-12-06 22:49:16 +00001443 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001444 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001445 command.GetArgumentAtIndex(0),
1446 LLDB_INVALID_ADDRESS,
1447 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001448
1449 if (addr == LLDB_INVALID_ADDRESS)
1450 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001451 result.AppendError("invalid address expression\n");
1452 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001453 result.SetStatus(eReturnStatusFailed);
1454 return false;
1455 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001456
Greg Clayton1deb7962011-10-25 06:44:01 +00001457 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001458 {
1459 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001460 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001461 length = item_byte_size;
1462 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001463 if (data_sp)
1464 {
1465 length = data_sp->GetByteSize();
1466 if (length > 0)
1467 {
1468 Error error;
1469 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1470
1471 if (bytes_written == length)
1472 {
1473 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001474 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001475 result.SetStatus(eReturnStatusSuccessFinishResult);
1476 }
1477 else if (bytes_written > 0)
1478 {
1479 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001480 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001481 result.SetStatus(eReturnStatusSuccessFinishResult);
1482 }
1483 else
1484 {
Daniel Malead01b2952012-11-29 21:49:15 +00001485 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001486 result.SetStatus(eReturnStatusFailed);
1487 }
1488 }
1489 }
1490 else
1491 {
1492 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1493 result.SetStatus(eReturnStatusFailed);
1494 }
1495 return result.Succeeded();
1496 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001497 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001498 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001499 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001500 item_byte_size = buffer.GetAddressByteSize();
1501 else
1502 item_byte_size = 1;
1503 }
1504
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001505 command.Shift(); // shift off the address argument
1506 uint64_t uval64;
1507 int64_t sval64;
1508 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001509 const size_t num_value_args = command.GetArgumentCount();
1510 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001511 {
1512 const char *value_str = command.GetArgumentAtIndex(i);
1513
Greg Clayton1deb7962011-10-25 06:44:01 +00001514 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001515 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001516 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001517 case eFormatFloat: // TODO: add support for floats soon
1518 case eFormatCharPrintable:
1519 case eFormatBytesWithASCII:
1520 case eFormatComplex:
1521 case eFormatEnum:
1522 case eFormatUnicode16:
1523 case eFormatUnicode32:
1524 case eFormatVectorOfChar:
1525 case eFormatVectorOfSInt8:
1526 case eFormatVectorOfUInt8:
1527 case eFormatVectorOfSInt16:
1528 case eFormatVectorOfUInt16:
1529 case eFormatVectorOfSInt32:
1530 case eFormatVectorOfUInt32:
1531 case eFormatVectorOfSInt64:
1532 case eFormatVectorOfUInt64:
1533 case eFormatVectorOfFloat32:
1534 case eFormatVectorOfFloat64:
1535 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001536 case eFormatOSType:
1537 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001538 case eFormatAddressInfo:
1539 case eFormatHexFloat:
1540 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001541 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001542 result.AppendError("unsupported format for writing memory");
1543 result.SetStatus(eReturnStatusFailed);
1544 return false;
1545
1546 case eFormatDefault:
1547 case eFormatBytes:
1548 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001549 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001550 case eFormatPointer:
1551
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001552 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001553 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001554 if (!success)
1555 {
1556 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1557 result.SetStatus(eReturnStatusFailed);
1558 return false;
1559 }
1560 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1561 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001562 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001563 result.SetStatus(eReturnStatusFailed);
1564 return false;
1565 }
1566 buffer.PutMaxHex64 (uval64, item_byte_size);
1567 break;
1568
1569 case eFormatBoolean:
1570 uval64 = Args::StringToBoolean(value_str, false, &success);
1571 if (!success)
1572 {
1573 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1574 result.SetStatus(eReturnStatusFailed);
1575 return false;
1576 }
1577 buffer.PutMaxHex64 (uval64, item_byte_size);
1578 break;
1579
1580 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001581 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001582 if (!success)
1583 {
1584 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1585 result.SetStatus(eReturnStatusFailed);
1586 return false;
1587 }
1588 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1589 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001590 result.AppendErrorWithFormat("Value 0x%" PRIx64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001591 result.SetStatus(eReturnStatusFailed);
1592 return false;
1593 }
1594 buffer.PutMaxHex64 (uval64, item_byte_size);
1595 break;
1596
Greg Clayton4e4294b2011-06-17 23:50:44 +00001597 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001598 case eFormatChar:
1599 case eFormatCString:
1600 if (value_str[0])
1601 {
1602 size_t len = strlen (value_str);
1603 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001604 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001605 ++len;
1606 Error error;
1607 if (process->WriteMemory (addr, value_str, len, error) == len)
1608 {
1609 addr += len;
1610 }
1611 else
1612 {
Daniel Malead01b2952012-11-29 21:49:15 +00001613 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001614 result.SetStatus(eReturnStatusFailed);
1615 return false;
1616 }
1617 }
1618 break;
1619
1620 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001621 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001622 if (!success)
1623 {
1624 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1625 result.SetStatus(eReturnStatusFailed);
1626 return false;
1627 }
1628 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1629 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001630 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %" PRIu64 " byte signed integer value.\n", sval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001631 result.SetStatus(eReturnStatusFailed);
1632 return false;
1633 }
1634 buffer.PutMaxHex64 (sval64, item_byte_size);
1635 break;
1636
1637 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001638 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001639 if (!success)
1640 {
1641 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1642 result.SetStatus(eReturnStatusFailed);
1643 return false;
1644 }
1645 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1646 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001647 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001648 result.SetStatus(eReturnStatusFailed);
1649 return false;
1650 }
1651 buffer.PutMaxHex64 (uval64, item_byte_size);
1652 break;
1653
1654 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001655 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001656 if (!success)
1657 {
1658 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1659 result.SetStatus(eReturnStatusFailed);
1660 return false;
1661 }
1662 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1663 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001664 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %" PRIu64 " byte unsigned integer value.\n", uval64, (uint64_t)item_byte_size);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001665 result.SetStatus(eReturnStatusFailed);
1666 return false;
1667 }
1668 buffer.PutMaxHex64 (uval64, item_byte_size);
1669 break;
1670 }
1671 }
1672
1673 if (!buffer.GetString().empty())
1674 {
1675 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001676 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001677 return true;
1678 else
1679 {
Daniel Malead01b2952012-11-29 21:49:15 +00001680 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001681 result.SetStatus(eReturnStatusFailed);
1682 return false;
1683 }
1684 }
1685 return true;
1686 }
1687
Greg Clayton1deb7962011-10-25 06:44:01 +00001688 OptionGroupOptions m_option_group;
1689 OptionGroupFormat m_format_options;
1690 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001691};
1692
Kuba Breckabeed8212014-09-04 01:03:18 +00001693//----------------------------------------------------------------------
1694// Get malloc/free history of a memory address.
1695//----------------------------------------------------------------------
1696class CommandObjectMemoryHistory : public CommandObjectParsed
1697{
1698public:
1699
1700 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1701 CommandObjectParsed (interpreter,
1702 "memory history",
1703 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1704 NULL,
1705 eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBePaused | eFlagProcessMustBeLaunched)
1706 {
1707 CommandArgumentEntry arg1;
1708 CommandArgumentData addr_arg;
1709
1710 // Define the first (and only) variant of this arg.
1711 addr_arg.arg_type = eArgTypeAddress;
1712 addr_arg.arg_repetition = eArgRepeatPlain;
1713
1714 // There is only one variant this argument could be; put it into the argument entry.
1715 arg1.push_back (addr_arg);
1716
1717 // Push the data for the first argument into the m_arguments vector.
1718 m_arguments.push_back (arg1);
1719 }
1720
1721 virtual
1722 ~CommandObjectMemoryHistory ()
1723 {
1724 }
1725
1726 virtual const char *GetRepeatCommand (Args &current_command_args, uint32_t index)
1727 {
1728 return m_cmd_name.c_str();
1729 }
1730
1731protected:
1732 virtual bool
1733 DoExecute (Args& command, CommandReturnObject &result)
1734 {
1735 const size_t argc = command.GetArgumentCount();
1736
1737 if (argc == 0 || argc > 1)
1738 {
1739 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1740 result.SetStatus(eReturnStatusFailed);
1741 return false;
1742 }
1743
1744 Error error;
1745 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1746 command.GetArgumentAtIndex(0),
1747 LLDB_INVALID_ADDRESS,
1748 &error);
1749
1750 if (addr == LLDB_INVALID_ADDRESS)
1751 {
1752 result.AppendError("invalid address expression");
1753 result.AppendError(error.AsCString());
1754 result.SetStatus(eReturnStatusFailed);
1755 return false;
1756 }
1757
1758 Stream *output_stream = &result.GetOutputStream();
1759
1760 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1761 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1762
1763 if (! memory_history.get())
1764 {
1765 result.AppendError("no available memory history provider");
1766 result.SetStatus(eReturnStatusFailed);
1767 return false;
1768 }
1769
1770 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1771
1772 for (auto thread : thread_list) {
1773 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1774 }
1775
1776 result.SetStatus(eReturnStatusSuccessFinishResult);
1777
1778 return true;
1779 }
1780
1781};
1782
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001783
1784//-------------------------------------------------------------------------
1785// CommandObjectMemory
1786//-------------------------------------------------------------------------
1787
Greg Clayton66111032010-06-23 01:19:29 +00001788CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001789 CommandObjectMultiword (interpreter,
1790 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001791 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001792 "memory <subcommand> [<subcommand-options>]")
1793{
Enrico Granata53468432013-11-13 02:18:44 +00001794 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001795 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1796 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001797 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001798}
1799
1800CommandObjectMemory::~CommandObjectMemory ()
1801{
1802}