blob: 249e3cbddd7e85000e02bec8aa848a547cea26c5 [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
10#include "CommandObjectMemory.h"
11
12// C Includes
Virgile Bellobdae3782013-08-28 12:14:27 +000013#include <inttypes.h>
14
Chris Lattner30fdc8d2010-06-08 16:52:24 +000015// C++ Includes
16// Other libraries and framework includes
Zachary Turnera78bd7f2015-03-03 23:11:11 +000017#include "clang/AST/Decl.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000018// Project includes
Chris Lattner30fdc8d2010-06-08 16:52:24 +000019#include "lldb/Core/DataBufferHeap.h"
20#include "lldb/Core/DataExtractor.h"
Greg Clayton66111032010-06-23 01:19:29 +000021#include "lldb/Core/Debugger.h"
Greg Clayton1f746072012-08-29 21:13:06 +000022#include "lldb/Core/Module.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000023#include "lldb/Core/StreamString.h"
Greg Clayton84c39662011-04-27 22:04:39 +000024#include "lldb/Core/ValueObjectMemory.h"
Enrico Granata4d93b8c2013-09-30 19:11:51 +000025#include "lldb/DataFormatters/ValueObjectPrinter.h"
Sean Callanan4dbb2712015-09-25 20:35:58 +000026#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h"
Vince Harron5275aaa2015-01-15 20:08:35 +000027#include "lldb/Host/StringConvert.h"
Greg Clayton66111032010-06-23 01:19:29 +000028#include "lldb/Interpreter/Args.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000029#include "lldb/Interpreter/CommandReturnObject.h"
Greg Clayton66111032010-06-23 01:19:29 +000030#include "lldb/Interpreter/CommandInterpreter.h"
31#include "lldb/Interpreter/Options.h"
Greg Clayton84c39662011-04-27 22:04:39 +000032#include "lldb/Interpreter/OptionGroupFormat.h"
33#include "lldb/Interpreter/OptionGroupOutputFile.h"
Greg Clayton68ebae62011-04-28 20:55:26 +000034#include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
Greg Clayton67cc0632012-08-22 17:17:09 +000035#include "lldb/Interpreter/OptionValueString.h"
Greg Claytond8d4a572015-08-11 21:38:15 +000036#include "lldb/Symbol/ClangASTContext.h"
Greg Clayton1f746072012-08-29 21:13:06 +000037#include "lldb/Symbol/TypeList.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000038#include "lldb/Target/MemoryHistory.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039#include "lldb/Target/Process.h"
Jason Molendab57e4a12013-11-04 09:33:30 +000040#include "lldb/Target/StackFrame.h"
Kuba Breckabeed8212014-09-04 01:03:18 +000041#include "lldb/Target/Thread.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000042
43using namespace lldb;
44using namespace lldb_private;
45
Greg Clayton68ebae62011-04-28 20:55:26 +000046static OptionDefinition
Greg Clayton84c39662011-04-27 22:04:39 +000047g_option_table[] =
48{
Zachary Turnerd37221d2014-07-09 16:31:49 +000049 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
50 { 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."},
51 { 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 +000052 { LLDB_OPT_SET_1|
53 LLDB_OPT_SET_2|
Zachary Turnerd37221d2014-07-09 16:31:49 +000054 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 +000055};
56
57
58
59class OptionGroupReadMemory : public OptionGroup
60{
61public:
62
63 OptionGroupReadMemory () :
Greg Clayton68ebae62011-04-28 20:55:26 +000064 m_num_per_line (1,1),
Greg Clayton84c39662011-04-27 22:04:39 +000065 m_output_as_binary (false),
66 m_view_as_type()
67 {
68 }
69
Bruce Mitchener13d21e92015-10-07 16:56:17 +000070 ~OptionGroupReadMemory () override
Greg Clayton84c39662011-04-27 22:04:39 +000071 {
72 }
73
74
Bruce Mitchener13d21e92015-10-07 16:56:17 +000075 uint32_t
76 GetNumDefinitions () override
Greg Clayton84c39662011-04-27 22:04:39 +000077 {
78 return sizeof (g_option_table) / sizeof (OptionDefinition);
79 }
80
Bruce Mitchener13d21e92015-10-07 16:56:17 +000081 const OptionDefinition*
82 GetDefinitions () override
Greg Clayton84c39662011-04-27 22:04:39 +000083 {
84 return g_option_table;
85 }
86
Bruce Mitchener13d21e92015-10-07 16:56:17 +000087 Error
Greg Clayton84c39662011-04-27 22:04:39 +000088 SetOptionValue (CommandInterpreter &interpreter,
89 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +000090 const char *option_arg) override
Greg Clayton84c39662011-04-27 22:04:39 +000091 {
92 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +000093 const int short_option = g_option_table[option_idx].short_option;
Greg Clayton84c39662011-04-27 22:04:39 +000094
95 switch (short_option)
96 {
97 case 'l':
Pavel Labathc95f7e22015-02-20 11:14:59 +000098 error = m_num_per_line.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +000099 if (m_num_per_line.GetCurrentValue() == 0)
Greg Clayton86edbf42011-10-26 00:56:27 +0000100 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000101 break;
Greg Clayton1deb7962011-10-25 06:44:01 +0000102
Greg Clayton84c39662011-04-27 22:04:39 +0000103 case 'b':
104 m_output_as_binary = true;
105 break;
106
107 case 't':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000108 error = m_view_as_type.SetValueFromString (option_arg);
Greg Clayton84c39662011-04-27 22:04:39 +0000109 break;
Sean Callanan1276c332012-04-28 01:27:38 +0000110
111 case 'r':
112 m_force = true;
113 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000114
115 default:
Greg Clayton86edbf42011-10-26 00:56:27 +0000116 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton84c39662011-04-27 22:04:39 +0000117 break;
118 }
119 return error;
120 }
121
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000122 void
123 OptionParsingStarting (CommandInterpreter &interpreter) override
Greg Clayton84c39662011-04-27 22:04:39 +0000124 {
Greg Clayton84c39662011-04-27 22:04:39 +0000125 m_num_per_line.Clear();
126 m_output_as_binary = false;
127 m_view_as_type.Clear();
Enrico Granatad325bf92013-06-04 22:54:16 +0000128 m_force = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000129 }
130
Greg Clayton68ebae62011-04-28 20:55:26 +0000131 Error
Greg Clayton1deb7962011-10-25 06:44:01 +0000132 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
Greg Clayton84c39662011-04-27 22:04:39 +0000133 {
Greg Clayton68ebae62011-04-28 20:55:26 +0000134 Error error;
Greg Clayton1deb7962011-10-25 06:44:01 +0000135 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
136 OptionValueUInt64 &count_value = format_options.GetCountValue();
Greg Clayton86edbf42011-10-26 00:56:27 +0000137 const bool byte_size_option_set = byte_size_value.OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000138 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
Greg Clayton1deb7962011-10-25 06:44:01 +0000139 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
Greg Clayton68ebae62011-04-28 20:55:26 +0000140
Greg Clayton68ebae62011-04-28 20:55:26 +0000141 switch (format_options.GetFormat())
Greg Clayton84c39662011-04-27 22:04:39 +0000142 {
143 default:
144 break;
145
146 case eFormatBoolean:
Greg Clayton68ebae62011-04-28 20:55:26 +0000147 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000148 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000149 if (!num_per_line_option_set)
150 m_num_per_line = 1;
151 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000152 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000153 break;
154
155 case eFormatCString:
156 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000157
158 case eFormatInstruction:
159 if (count_option_set)
Jim Inghamd073fe42012-11-07 01:52:04 +0000160 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
Greg Clayton5009f9d2011-10-27 17:55:14 +0000161 m_num_per_line = 1;
162 break;
163
164 case eFormatAddressInfo:
165 if (!byte_size_option_set)
166 byte_size_value = target->GetArchitecture().GetAddressByteSize();
167 m_num_per_line = 1;
168 if (!count_option_set)
169 format_options.GetCountValue() = 8;
170 break;
171
Greg Clayton84c39662011-04-27 22:04:39 +0000172 case eFormatPointer:
Greg Clayton1deb7962011-10-25 06:44:01 +0000173 byte_size_value = target->GetArchitecture().GetAddressByteSize();
Greg Clayton68ebae62011-04-28 20:55:26 +0000174 if (!num_per_line_option_set)
175 m_num_per_line = 4;
176 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000177 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000178 break;
179
180 case eFormatBinary:
181 case eFormatFloat:
182 case eFormatOctal:
183 case eFormatDecimal:
184 case eFormatEnum:
185 case eFormatUnicode16:
186 case eFormatUnicode32:
187 case eFormatUnsigned:
Greg Clayton5009f9d2011-10-27 17:55:14 +0000188 case eFormatHexFloat:
Greg Clayton68ebae62011-04-28 20:55:26 +0000189 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000190 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000191 if (!num_per_line_option_set)
192 m_num_per_line = 1;
193 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000194 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000195 break;
Greg Clayton5009f9d2011-10-27 17:55:14 +0000196
Greg Clayton84c39662011-04-27 22:04:39 +0000197 case eFormatBytes:
198 case eFormatBytesWithASCII:
Greg Clayton86edbf42011-10-26 00:56:27 +0000199 if (byte_size_option_set)
Greg Clayton68ebae62011-04-28 20:55:26 +0000200 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000201 if (byte_size_value > 1)
Daniel Malead01b2952012-11-29 21:49:15 +0000202 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
Johnny Chenda324de2012-03-06 01:17:59 +0000203 "\tconsider using a different display format or don't specify the byte size",
204 byte_size_value.GetCurrentValue());
Greg Clayton68ebae62011-04-28 20:55:26 +0000205 }
206 else
Greg Clayton1deb7962011-10-25 06:44:01 +0000207 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000208 if (!num_per_line_option_set)
209 m_num_per_line = 16;
210 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000211 format_options.GetCountValue() = 32;
Greg Clayton84c39662011-04-27 22:04:39 +0000212 break;
Greg Clayton4e4294b2011-06-17 23:50:44 +0000213 case eFormatCharArray:
Greg Clayton84c39662011-04-27 22:04:39 +0000214 case eFormatChar:
215 case eFormatCharPrintable:
Greg Clayton68ebae62011-04-28 20:55:26 +0000216 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000217 byte_size_value = 1;
Greg Clayton68ebae62011-04-28 20:55:26 +0000218 if (!num_per_line_option_set)
219 m_num_per_line = 32;
220 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000221 format_options.GetCountValue() = 64;
Greg Clayton84c39662011-04-27 22:04:39 +0000222 break;
223 case eFormatComplex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000224 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000225 byte_size_value = 8;
Greg Clayton68ebae62011-04-28 20:55:26 +0000226 if (!num_per_line_option_set)
227 m_num_per_line = 1;
228 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000229 format_options.GetCountValue() = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000230 break;
Jason Molendafc306d32013-03-23 05:16:54 +0000231 case eFormatComplexInteger:
232 if (!byte_size_option_set)
233 byte_size_value = 8;
234 if (!num_per_line_option_set)
235 m_num_per_line = 1;
236 if (!count_option_set)
237 format_options.GetCountValue() = 8;
238 break;
Greg Clayton84c39662011-04-27 22:04:39 +0000239 case eFormatHex:
Greg Clayton68ebae62011-04-28 20:55:26 +0000240 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000241 byte_size_value = 4;
Greg Clayton68ebae62011-04-28 20:55:26 +0000242 if (!num_per_line_option_set)
243 {
Greg Clayton1deb7962011-10-25 06:44:01 +0000244 switch (byte_size_value)
Greg Clayton68ebae62011-04-28 20:55:26 +0000245 {
246 case 1:
247 case 2:
248 m_num_per_line = 8;
249 break;
250 case 4:
251 m_num_per_line = 4;
252 break;
253 case 8:
254 m_num_per_line = 2;
255 break;
256 default:
257 m_num_per_line = 1;
258 break;
259 }
260 }
261 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000262 count_value = 8;
Greg Clayton84c39662011-04-27 22:04:39 +0000263 break;
264
265 case eFormatVectorOfChar:
266 case eFormatVectorOfSInt8:
267 case eFormatVectorOfUInt8:
268 case eFormatVectorOfSInt16:
269 case eFormatVectorOfUInt16:
270 case eFormatVectorOfSInt32:
271 case eFormatVectorOfUInt32:
272 case eFormatVectorOfSInt64:
273 case eFormatVectorOfUInt64:
274 case eFormatVectorOfFloat32:
275 case eFormatVectorOfFloat64:
276 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000277 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000278 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000279 if (!num_per_line_option_set)
280 m_num_per_line = 1;
281 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000282 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000283 break;
284 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000285 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000286 }
287
Greg Clayton82f4cf42011-10-26 04:32:38 +0000288 bool
289 AnyOptionWasSet () const
290 {
291 return m_num_per_line.OptionWasSet() ||
292 m_output_as_binary ||
293 m_view_as_type.OptionWasSet();
294 }
295
Greg Clayton84c39662011-04-27 22:04:39 +0000296 OptionValueUInt64 m_num_per_line;
297 bool m_output_as_binary;
298 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000299 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000300};
301
302
303
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000304//----------------------------------------------------------------------
305// Read memory from the inferior process
306//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000307class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000308{
309public:
310
Greg Claytona7015092010-09-18 01:14:36 +0000311 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000312 CommandObjectParsed (interpreter,
313 "memory read",
314 "Read from the memory of the process being debugged.",
315 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +0000316 eCommandRequiresTarget | eCommandProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000317 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000318 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000319 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000320 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000321 m_varobj_options(),
322 m_next_addr(LLDB_INVALID_ADDRESS),
323 m_prev_byte_size(0),
324 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
325 m_prev_memory_options (),
326 m_prev_outfile_options (),
327 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000328 {
Caroline Tice405fe672010-10-04 22:28:36 +0000329 CommandArgumentEntry arg1;
330 CommandArgumentEntry arg2;
331 CommandArgumentData start_addr_arg;
332 CommandArgumentData end_addr_arg;
333
334 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000335 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000336 start_addr_arg.arg_repetition = eArgRepeatPlain;
337
338 // There is only one variant this argument could be; put it into the argument entry.
339 arg1.push_back (start_addr_arg);
340
341 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000342 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000343 end_addr_arg.arg_repetition = eArgRepeatOptional;
344
345 // There is only one variant this argument could be; put it into the argument entry.
346 arg2.push_back (end_addr_arg);
347
348 // Push the data for the first argument into the m_arguments vector.
349 m_arguments.push_back (arg1);
350 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000351
Greg Clayton1deb7962011-10-25 06:44:01 +0000352 // Add the "--format" and "--count" options to group 1 and 3
353 m_option_group.Append (&m_format_options,
354 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000355 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000356 m_option_group.Append (&m_format_options,
357 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000358 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000359 // Add the "--size" option to group 1 and 2
360 m_option_group.Append (&m_format_options,
361 OptionGroupFormat::OPTION_GROUP_SIZE,
362 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000363 m_option_group.Append (&m_memory_options);
364 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 +0000365 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000366 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000367 }
368
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000369 ~CommandObjectMemoryRead () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000370 {
371 }
372
373 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000374 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000375 {
Greg Clayton84c39662011-04-27 22:04:39 +0000376 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000377 }
378
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000379 const char *
380 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Greg Clayton82f4cf42011-10-26 04:32:38 +0000381 {
382 return m_cmd_name.c_str();
383 }
384
Jim Ingham5a988412012-06-08 21:56:10 +0000385protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000386 bool
387 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000388 {
Enrico Granatae87764f2015-05-27 05:04:35 +0000389 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +0000390 Target *target = m_exe_ctx.GetTargetPtr();
391
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000392 const size_t argc = command.GetArgumentCount();
393
Greg Clayton82f4cf42011-10-26 04:32:38 +0000394 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000395 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000396 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 +0000397 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000398 result.SetStatus(eReturnStatusFailed);
399 return false;
400 }
401
Greg Claytona1e5dc82015-08-11 22:53:00 +0000402 CompilerType clang_ast_type;
Greg Clayton68ebae62011-04-28 20:55:26 +0000403 Error error;
404
Greg Clayton84c39662011-04-27 22:04:39 +0000405 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
406 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000407 {
Greg Clayton84c39662011-04-27 22:04:39 +0000408 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000409
Greg Clayton84c39662011-04-27 22:04:39 +0000410 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000411 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000412 TypeList type_list;
413 uint32_t reference_count = 0;
414 uint32_t pointer_count = 0;
415 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000416
417#define ALL_KEYWORDS \
418 KEYWORD("const") \
419 KEYWORD("volatile") \
420 KEYWORD("restrict") \
421 KEYWORD("struct") \
422 KEYWORD("class") \
423 KEYWORD("union")
424
425#define KEYWORD(s) s,
426 static const char *g_keywords[] =
427 {
428 ALL_KEYWORDS
429 };
430#undef KEYWORD
431
432#define KEYWORD(s) (sizeof(s) - 1),
433 static const int g_keyword_lengths[] =
434 {
435 ALL_KEYWORDS
436 };
437#undef KEYWORD
438
439#undef ALL_KEYWORDS
440
441 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000442 std::string type_str(view_as_type_cstr);
443
444 // Remove all instances of g_keywords that are followed by spaces
445 for (size_t i = 0; i < g_num_keywords; ++i)
446 {
447 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000448 int keyword_len = g_keyword_lengths[i];
449
450 idx = 0;
451 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000452 {
453 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000454 {
Greg Clayton84c39662011-04-27 22:04:39 +0000455 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000456 idx = 0;
457 }
458 else
459 {
460 idx += keyword_len;
461 }
Greg Clayton84c39662011-04-27 22:04:39 +0000462 }
463 }
464 bool done = type_str.empty();
465 //
466 idx = type_str.find_first_not_of (" \t");
467 if (idx > 0 && idx != std::string::npos)
468 type_str.erase (0, idx);
469 while (!done)
470 {
471 // Strip trailing spaces
472 if (type_str.empty())
473 done = true;
474 else
475 {
476 switch (type_str[type_str.size()-1])
477 {
478 case '*':
479 ++pointer_count;
480 // fall through...
481 case ' ':
482 case '\t':
483 type_str.erase(type_str.size()-1);
484 break;
485
486 case '&':
487 if (reference_count == 0)
488 {
489 reference_count = 1;
490 type_str.erase(type_str.size()-1);
491 }
492 else
493 {
494 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
495 result.SetStatus(eReturnStatusFailed);
496 return false;
497 }
498 break;
499
500 default:
501 done = true;
502 break;
503 }
504 }
505 }
506
507 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000508 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000509 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000510 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000511 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000512 if (sc.module_sp)
513 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000514 sc.module_sp->FindTypes (sc,
515 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000516 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000517 1,
518 type_list);
519 }
520 }
521 if (type_list.GetSize() == 0)
522 {
Greg Clayton29399a22012-04-06 17:41:13 +0000523 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000524 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000525 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000526 1,
527 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000528 }
529
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000530 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000531 {
Sean Callananb92bd752015-10-01 16:28:02 +0000532 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)))
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000533 {
Sean Callananb92bd752015-10-01 16:28:02 +0000534 clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name));
535
536 if (tdecl)
537 {
538 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),(const lldb::opaque_compiler_type_t)tdecl->getTypeForDecl());
539 }
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000540 }
Greg Clayton84c39662011-04-27 22:04:39 +0000541 }
542
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000543 if (clang_ast_type.IsValid() == false)
544 {
545 if (type_list.GetSize() == 0)
546 {
547 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
548 lookup_type_name.GetCString(),
549 view_as_type_cstr);
550 result.SetStatus(eReturnStatusFailed);
551 return false;
552 }
553 else
554 {
555 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton99558cc42015-08-24 23:46:31 +0000556 clang_ast_type = type_sp->GetFullCompilerType ();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000557 }
558 }
Greg Clayton84c39662011-04-27 22:04:39 +0000559
560 while (pointer_count > 0)
561 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000562 CompilerType pointer_type = clang_ast_type.GetPointerType();
Greg Clayton57ee3062013-07-11 22:46:58 +0000563 if (pointer_type.IsValid())
564 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000565 else
566 {
567 result.AppendError ("unable make a pointer type\n");
568 result.SetStatus(eReturnStatusFailed);
569 return false;
570 }
571 --pointer_count;
572 }
573
Enrico Granata1cd5e922015-01-28 00:07:51 +0000574 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000575
Greg Clayton1deb7962011-10-25 06:44:01 +0000576 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000577 {
578 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
579 view_as_type_cstr);
580 result.SetStatus(eReturnStatusFailed);
581 return false;
582 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000583
Greg Clayton1deb7962011-10-25 06:44:01 +0000584 if (!m_format_options.GetCountValue().OptionWasSet())
585 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000586 }
587 else
588 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000589 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000590 }
591
592 // Look for invalid combinations of settings
593 if (error.Fail())
594 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000595 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000596 result.SetStatus(eReturnStatusFailed);
597 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000598 }
599
Greg Clayton82f4cf42011-10-26 04:32:38 +0000600 lldb::addr_t addr;
601 size_t total_byte_size = 0;
602 if (argc == 0)
603 {
604 // Use the last address and byte size and all options as they were
605 // if no options have been set
606 addr = m_next_addr;
607 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000608 clang_ast_type = m_prev_clang_ast_type;
609 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000610 !m_memory_options.AnyOptionWasSet() &&
611 !m_outfile_options.AnyOptionWasSet() &&
612 !m_varobj_options.AnyOptionWasSet())
613 {
614 m_format_options = m_prev_format_options;
615 m_memory_options = m_prev_memory_options;
616 m_outfile_options = m_prev_outfile_options;
617 m_varobj_options = m_prev_varobj_options;
618 }
619 }
620
Greg Clayton1deb7962011-10-25 06:44:01 +0000621 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000622
623 // TODO For non-8-bit byte addressable architectures this needs to be
624 // revisited to fully support all lldb's range of formatting options.
625 // Furthermore code memory reads (for those architectures) will not
626 // be correctly formatted even w/o formatting options.
627 size_t item_byte_size =
628 target->GetArchitecture().GetDataByteSize() > 1 ?
629 target->GetArchitecture().GetDataByteSize() :
630 m_format_options.GetByteSizeValue().GetCurrentValue();
631
Greg Clayton68ebae62011-04-28 20:55:26 +0000632 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000633
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000634 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000635 {
636 total_byte_size = item_count * item_byte_size;
637 if (total_byte_size == 0)
638 total_byte_size = 32;
639 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000640
Greg Clayton82f4cf42011-10-26 04:32:38 +0000641 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000642 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000643
644 if (addr == LLDB_INVALID_ADDRESS)
645 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000646 result.AppendError("invalid start address expression.");
647 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000648 result.SetStatus(eReturnStatusFailed);
649 return false;
650 }
651
652 if (argc == 2)
653 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000654 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000655 if (end_addr == LLDB_INVALID_ADDRESS)
656 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000657 result.AppendError("invalid end address expression.");
658 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000659 result.SetStatus(eReturnStatusFailed);
660 return false;
661 }
662 else if (end_addr <= addr)
663 {
Daniel Malead01b2952012-11-29 21:49:15 +0000664 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 +0000665 result.SetStatus(eReturnStatusFailed);
666 return false;
667 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000668 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000669 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000670 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 +0000671 result.SetStatus(eReturnStatusFailed);
672 return false;
673 }
674
675 total_byte_size = end_addr - addr;
676 item_count = total_byte_size / item_byte_size;
677 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000678
Enrico Granatad325bf92013-06-04 22:54:16 +0000679 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
680
681 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000682 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000683 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
684 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
685 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 +0000686 return false;
687 }
688
Greg Clayton84c39662011-04-27 22:04:39 +0000689 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000690 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000691 if (clang_ast_type.GetOpaqueQualType())
692 {
693 // Make sure we don't display our type as ASCII bytes like the default memory read
694 if (m_format_options.GetFormatValue().OptionWasSet() == false)
695 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
696
Enrico Granata1cd5e922015-01-28 00:07:51 +0000697 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000698 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000699 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000700 {
Greg Clayton84c39662011-04-27 22:04:39 +0000701 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000702 if (data_sp->GetBytes() == NULL)
703 {
Virgile Belloffeba252014-03-08 17:15:35 +0000704 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 +0000705 result.SetStatus(eReturnStatusFailed);
706 return false;
707 }
708
Greg Claytone72dfb32012-02-24 01:59:29 +0000709 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000710 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000711 if (bytes_read == 0)
712 {
Greg Clayton57f06302012-05-25 17:05:55 +0000713 const char *error_cstr = error.AsCString();
714 if (error_cstr && error_cstr[0])
715 {
716 result.AppendError(error_cstr);
717 }
718 else
719 {
Daniel Malead01b2952012-11-29 21:49:15 +0000720 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000721 }
Greg Clayton84c39662011-04-27 22:04:39 +0000722 result.SetStatus(eReturnStatusFailed);
723 return false;
724 }
725
726 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000727 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 +0000728 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000729 else
730 {
731 // we treat c-strings as a special case because they do not have a fixed size
732 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
733 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
734 else
735 item_byte_size = target->GetMaximumSizeOfStringSummary();
736 if (!m_format_options.GetCountValue().OptionWasSet())
737 item_count = 1;
738 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000739 if (data_sp->GetBytes() == NULL)
740 {
741 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));
742 result.SetStatus(eReturnStatusFailed);
743 return false;
744 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000745 uint8_t *data_ptr = data_sp->GetBytes();
746 auto data_addr = addr;
747 auto count = item_count;
748 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000749 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000750 while (item_count < count)
751 {
752 std::string buffer;
753 buffer.resize(item_byte_size+1,0);
754 Error error;
755 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
756 if (error.Fail())
757 {
758 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
759 result.SetStatus(eReturnStatusFailed);
760 return false;
761 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000762
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000763 if (item_byte_size == read)
764 {
765 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 +0000766 --read;
767 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000768 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000769 else
770 ++read; // account for final NULL byte
771
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000772 memcpy(data_ptr, &buffer[0], read);
773 data_ptr += read;
774 data_addr += read;
775 bytes_read += read;
776 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000777
778 if (break_on_no_NULL)
779 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000780 }
781 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
782 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000783
Greg Clayton2e1f7452012-12-15 02:08:17 +0000784 m_next_addr = addr + bytes_read;
785 m_prev_byte_size = bytes_read;
786 m_prev_format_options = m_format_options;
787 m_prev_memory_options = m_memory_options;
788 m_prev_outfile_options = m_outfile_options;
789 m_prev_varobj_options = m_varobj_options;
790 m_prev_clang_ast_type = clang_ast_type;
791
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000792 StreamFile outfile_stream;
793 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000794 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
795 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000796 {
797 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000798 outfile_spec.GetPath (path, sizeof(path));
799
800 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
801 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
802 if (append)
803 open_options |= File::eOpenOptionAppend;
804
805 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000806 {
Greg Clayton84c39662011-04-27 22:04:39 +0000807 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000808 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000809 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000810 if (bytes_written > 0)
811 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000812 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000813 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000814 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000815 path);
816 return true;
817 }
818 else
819 {
Daniel Malead01b2952012-11-29 21:49:15 +0000820 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000821 result.SetStatus(eReturnStatusFailed);
822 return false;
823 }
824 }
825 else
826 {
827 // We are going to write ASCII to the file just point the
828 // output_stream to our outfile_stream...
829 output_stream = &outfile_stream;
830 }
831 }
832 else
833 {
Greg Clayton84c39662011-04-27 22:04:39 +0000834 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000835 result.SetStatus(eReturnStatusFailed);
836 return false;
837 }
838 }
839 else
840 {
841 output_stream = &result.GetOutputStream();
842 }
843
Greg Clayton84c39662011-04-27 22:04:39 +0000844
Greg Claytonf9fc6092013-01-09 19:44:40 +0000845 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000846 if (clang_ast_type.GetOpaqueQualType())
847 {
848 for (uint32_t i = 0; i<item_count; ++i)
849 {
850 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000851 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000852 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000853 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000854 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000855 name_strm.GetString().c_str(),
856 address,
857 clang_ast_type));
858 if (valobj_sp)
859 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000860 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000861 if (format != eFormatDefault)
862 valobj_sp->SetFormat (format);
863
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000864 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000865
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000866 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000867 }
868 else
869 {
870 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
871 view_as_type_cstr,
872 name_strm.GetString().c_str());
873 result.SetStatus(eReturnStatusFailed);
874 return false;
875 }
876 }
877 return true;
878 }
879
880 result.SetStatus(eReturnStatusSuccessFinishResult);
881 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000882 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000883 target->GetArchitecture().GetAddressByteSize(),
884 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000885
886 Format format = m_format_options.GetFormat();
887 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000888 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000889 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000890 // if a count was not passed, or it is 1
891 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
892 {
893 // this turns requests such as
894 // memory read -fc -s10 -c1 *charPtrPtr
895 // which make no sense (what is a char of size 10?)
896 // into a request for fetching 10 chars of size 1 from the same memory location
897 format = eFormatCharArray;
898 item_count = item_byte_size;
899 item_byte_size = 1;
900 }
901 else
902 {
903 // here we passed a count, and it was not 1
904 // so we have a byte_size and a count
905 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000906 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000907 result.SetStatus(eReturnStatusFailed);
908 return false;
909 }
Enrico Granata31898912013-05-21 17:39:04 +0000910 }
Greg Clayton84c39662011-04-27 22:04:39 +0000911
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000912 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000913 size_t bytes_dumped = data.Dump (output_stream,
914 0,
Enrico Granata31898912013-05-21 17:39:04 +0000915 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000916 item_byte_size,
917 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000918 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000919 addr,
920 0,
921 0,
922 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000923 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000924 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000925 return true;
926 }
927
Greg Clayton84c39662011-04-27 22:04:39 +0000928 OptionGroupOptions m_option_group;
929 OptionGroupFormat m_format_options;
930 OptionGroupReadMemory m_memory_options;
931 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000932 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000933 lldb::addr_t m_next_addr;
934 lldb::addr_t m_prev_byte_size;
935 OptionGroupFormat m_prev_format_options;
936 OptionGroupReadMemory m_prev_memory_options;
937 OptionGroupOutputFile m_prev_outfile_options;
938 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000939 CompilerType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000940};
941
Enrico Granata53468432013-11-13 02:18:44 +0000942OptionDefinition
943g_memory_find_option_table[] =
944{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000945 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
946 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
947 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
948 { 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 +0000949};
950
Enrico Granata53468432013-11-13 02:18:44 +0000951//----------------------------------------------------------------------
952// Find the specified data in memory
953//----------------------------------------------------------------------
954class CommandObjectMemoryFind : public CommandObjectParsed
955{
956public:
957
958 class OptionGroupFindMemory : public OptionGroup
959 {
960 public:
961 OptionGroupFindMemory () :
962 OptionGroup(),
963 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000964 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000965 {
966 }
967
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000968 ~OptionGroupFindMemory () override
Enrico Granata53468432013-11-13 02:18:44 +0000969 {
970 }
971
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000972 uint32_t
973 GetNumDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000974 {
975 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
976 }
977
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000978 const OptionDefinition*
979 GetDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000980 {
981 return g_memory_find_option_table;
982 }
983
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000984 Error
Enrico Granata53468432013-11-13 02:18:44 +0000985 SetOptionValue (CommandInterpreter &interpreter,
986 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000987 const char *option_arg) override
Enrico Granata53468432013-11-13 02:18:44 +0000988 {
989 Error error;
990 const int short_option = g_memory_find_option_table[option_idx].short_option;
991
992 switch (short_option)
993 {
994 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000995 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000996 break;
997
998 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000999 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +00001000 break;
1001
1002 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001003 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001004 error.SetErrorString("unrecognized value for count");
1005 break;
1006
Enrico Granata8d81a842013-11-13 20:08:30 +00001007 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001008 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001009 error.SetErrorString("unrecognized value for dump-offset");
1010 break;
1011
Enrico Granata53468432013-11-13 02:18:44 +00001012 default:
1013 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1014 break;
1015 }
1016 return error;
1017 }
1018
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001019 void
1020 OptionParsingStarting (CommandInterpreter &interpreter) override
Enrico Granata53468432013-11-13 02:18:44 +00001021 {
1022 m_expr.Clear();
1023 m_string.Clear();
1024 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001025 }
1026
1027 OptionValueString m_expr;
1028 OptionValueString m_string;
1029 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001030 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001031 };
1032
1033 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1034 CommandObjectParsed (interpreter,
1035 "memory find",
1036 "Find a value in the memory of the process being debugged.",
1037 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001038 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Enrico Granata53468432013-11-13 02:18:44 +00001039 m_option_group (interpreter),
1040 m_memory_options ()
1041 {
1042 CommandArgumentEntry arg1;
1043 CommandArgumentEntry arg2;
1044 CommandArgumentData addr_arg;
1045 CommandArgumentData value_arg;
1046
1047 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001048 addr_arg.arg_type = eArgTypeAddressOrExpression;
Enrico Granata53468432013-11-13 02:18:44 +00001049 addr_arg.arg_repetition = eArgRepeatPlain;
1050
1051 // There is only one variant this argument could be; put it into the argument entry.
1052 arg1.push_back (addr_arg);
1053
1054 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001055 value_arg.arg_type = eArgTypeAddressOrExpression;
1056 value_arg.arg_repetition = eArgRepeatPlain;
Enrico Granata53468432013-11-13 02:18:44 +00001057
1058 // There is only one variant this argument could be; put it into the argument entry.
1059 arg2.push_back (value_arg);
1060
1061 // Push the data for the first argument into the m_arguments vector.
1062 m_arguments.push_back (arg1);
1063 m_arguments.push_back (arg2);
1064
1065 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1066 m_option_group.Finalize();
1067 }
1068
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001069 ~CommandObjectMemoryFind () override
Enrico Granata53468432013-11-13 02:18:44 +00001070 {
1071 }
1072
1073 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001074 GetOptions () override
Enrico Granata53468432013-11-13 02:18:44 +00001075 {
1076 return &m_option_group;
1077 }
1078
1079protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001080 bool
1081 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata53468432013-11-13 02:18:44 +00001082 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001083 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Enrico Granata53468432013-11-13 02:18:44 +00001084 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;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001124 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1125 result_sp.get())
Enrico Granata53468432013-11-13 02:18:44 +00001126 {
1127 uint64_t value = result_sp->GetValueAsUnsigned(0);
Greg Clayton99558cc42015-08-24 23:46:31 +00001128 switch (result_sp->GetCompilerType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001129 {
1130 case 1: {
1131 uint8_t byte = (uint8_t)value;
1132 buffer.CopyData(&byte,1);
1133 }
1134 break;
1135 case 2: {
1136 uint16_t word = (uint16_t)value;
1137 buffer.CopyData(&word,2);
1138 }
1139 break;
1140 case 4: {
1141 uint32_t lword = (uint32_t)value;
1142 buffer.CopyData(&lword,4);
1143 }
1144 break;
1145 case 8: {
1146 buffer.CopyData(&value, 8);
1147 }
1148 break;
1149 case 3:
1150 case 5:
1151 case 6:
1152 case 7:
1153 result.AppendError("unknown type. pass a string instead");
1154 return false;
1155 default:
Enrico Granata0b3b9872015-08-03 18:51:39 +00001156 result.AppendError("result size larger than 8 bytes. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001157 return false;
1158 }
1159 }
1160 else
1161 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001162 result.AppendError("expression evaluation failed. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001163 return false;
1164 }
1165 }
1166 else
1167 {
1168 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1169 return false;
1170 }
1171
1172 size_t count = m_memory_options.m_count.GetCurrentValue();
1173 found_location = low_addr;
1174 bool ever_found = false;
1175 while (count)
1176 {
1177 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1178 if (found_location == LLDB_INVALID_ADDRESS)
1179 {
1180 if (!ever_found)
1181 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001182 result.AppendMessage("data not found within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001183 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1184 }
1185 else
Enrico Granata0b3b9872015-08-03 18:51:39 +00001186 result.AppendMessage("no more matches within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001187 break;
1188 }
Enrico Granata0b3b9872015-08-03 18:51:39 +00001189 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001190
1191 DataBufferHeap dumpbuffer(32,0);
1192 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1193 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001194 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001195 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1196 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1197 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001198 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001199
Enrico Granata53468432013-11-13 02:18:44 +00001200 --count;
1201 found_location++;
1202 ever_found = true;
1203 }
1204
1205 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1206 return true;
1207 }
1208
1209 lldb::addr_t
1210 Search (lldb::addr_t low,
1211 lldb::addr_t high,
1212 uint8_t* buffer,
1213 size_t buffer_size)
1214 {
1215 Process *process = m_exe_ctx.GetProcessPtr();
1216 DataBufferHeap heap(buffer_size, 0);
Enrico Granata53468432013-11-13 02:18:44 +00001217 for (auto ptr = low;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001218 ptr < high;
1219 ptr++)
Enrico Granata53468432013-11-13 02:18:44 +00001220 {
1221 Error error;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001222 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
Enrico Granata53468432013-11-13 02:18:44 +00001223 if (error.Fail())
1224 return LLDB_INVALID_ADDRESS;
1225 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
Enrico Granata0b3b9872015-08-03 18:51:39 +00001226 return ptr;
Enrico Granata53468432013-11-13 02:18:44 +00001227 }
1228 return LLDB_INVALID_ADDRESS;
1229 }
1230
1231 OptionGroupOptions m_option_group;
1232 OptionGroupFindMemory m_memory_options;
1233};
1234
Greg Clayton1deb7962011-10-25 06:44:01 +00001235
1236OptionDefinition
1237g_memory_write_option_table[] =
1238{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001239{ 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 +00001240{ 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 +00001241};
1242
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001243//----------------------------------------------------------------------
1244// Write memory to the inferior process
1245//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001246class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001247{
1248public:
1249
Greg Clayton1deb7962011-10-25 06:44:01 +00001250 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001251 {
1252 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001253 OptionGroupWriteMemory () :
1254 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001255 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001256 }
1257
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001258 ~OptionGroupWriteMemory () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001259 {
1260 }
1261
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001262 uint32_t
1263 GetNumDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001264 {
1265 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1266 }
Enrico Granata53468432013-11-13 02:18:44 +00001267
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001268 const OptionDefinition*
1269 GetDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001270 {
1271 return g_memory_write_option_table;
1272 }
Enrico Granata53468432013-11-13 02:18:44 +00001273
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001274 Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001275 SetOptionValue (CommandInterpreter &interpreter,
1276 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001277 const char *option_arg) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001278 {
1279 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001280 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001281
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001282 switch (short_option)
1283 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001284 case 'i':
1285 m_infile.SetFile (option_arg, true);
1286 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001287 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001288 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001289 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001290 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001291 break;
Enrico Granata53468432013-11-13 02:18:44 +00001292
Greg Clayton1deb7962011-10-25 06:44:01 +00001293 case 'o':
1294 {
1295 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001296 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001297 if (!success)
1298 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001299 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001300 }
1301 }
1302 break;
1303
1304 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001305 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001306 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001307 }
1308 return error;
1309 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001310
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001311 void
1312 OptionParsingStarting (CommandInterpreter &interpreter) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001313 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001314 m_infile.Clear();
1315 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001316 }
1317
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001318 FileSpec m_infile;
1319 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001320 };
1321
Greg Claytona7015092010-09-18 01:14:36 +00001322 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001323 CommandObjectParsed (interpreter,
1324 "memory write",
1325 "Write to the memory of the process being debugged.",
1326 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001327 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001328 m_option_group (interpreter),
1329 m_format_options (eFormatBytes, 1, UINT64_MAX),
1330 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001331 {
Caroline Tice405fe672010-10-04 22:28:36 +00001332 CommandArgumentEntry arg1;
1333 CommandArgumentEntry arg2;
1334 CommandArgumentData addr_arg;
1335 CommandArgumentData value_arg;
1336
1337 // Define the first (and only) variant of this arg.
1338 addr_arg.arg_type = eArgTypeAddress;
1339 addr_arg.arg_repetition = eArgRepeatPlain;
1340
1341 // There is only one variant this argument could be; put it into the argument entry.
1342 arg1.push_back (addr_arg);
1343
1344 // Define the first (and only) variant of this arg.
1345 value_arg.arg_type = eArgTypeValue;
1346 value_arg.arg_repetition = eArgRepeatPlus;
1347
1348 // There is only one variant this argument could be; put it into the argument entry.
1349 arg2.push_back (value_arg);
1350
1351 // Push the data for the first argument into the m_arguments vector.
1352 m_arguments.push_back (arg1);
1353 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001354
1355 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1356 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1357 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1358 m_option_group.Finalize();
1359
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001360 }
1361
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001362 ~CommandObjectMemoryWrite () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001363 {
1364 }
1365
1366 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001367 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001368 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001369 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370 }
1371
1372 bool
1373 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1374 {
1375 if (total_byte_size > 8)
1376 return false;
1377
1378 if (total_byte_size == 8)
1379 return true;
1380
1381 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1382 return uval64 <= max;
1383 }
1384
1385 bool
1386 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1387 {
1388 if (total_byte_size > 8)
1389 return false;
1390
1391 if (total_byte_size == 8)
1392 return true;
1393
1394 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1395 const int64_t min = ~(max);
1396 return min <= sval64 && sval64 <= max;
1397 }
1398
Jim Ingham5a988412012-06-08 21:56:10 +00001399protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001400 bool
1401 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001402 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001403 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +00001404 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001405
1406 const size_t argc = command.GetArgumentCount();
1407
Greg Clayton1deb7962011-10-25 06:44:01 +00001408 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001409 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001410 if (argc < 1)
1411 {
1412 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1413 result.SetStatus(eReturnStatusFailed);
1414 return false;
1415 }
1416 }
1417 else if (argc < 2)
1418 {
1419 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 +00001420 result.SetStatus(eReturnStatusFailed);
1421 return false;
1422 }
1423
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001424 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001425 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1426 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001427
Greg Clayton1deb7962011-10-25 06:44:01 +00001428 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1429 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001430
Greg Claytonb9d5df52012-12-06 22:49:16 +00001431 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001432 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001433 command.GetArgumentAtIndex(0),
1434 LLDB_INVALID_ADDRESS,
1435 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001436
1437 if (addr == LLDB_INVALID_ADDRESS)
1438 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001439 result.AppendError("invalid address expression\n");
1440 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001441 result.SetStatus(eReturnStatusFailed);
1442 return false;
1443 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001444
Greg Clayton1deb7962011-10-25 06:44:01 +00001445 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001446 {
1447 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001448 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001449 length = item_byte_size;
1450 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001451 if (data_sp)
1452 {
1453 length = data_sp->GetByteSize();
1454 if (length > 0)
1455 {
1456 Error error;
1457 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1458
1459 if (bytes_written == length)
1460 {
1461 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001462 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001463 result.SetStatus(eReturnStatusSuccessFinishResult);
1464 }
1465 else if (bytes_written > 0)
1466 {
1467 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001468 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 +00001469 result.SetStatus(eReturnStatusSuccessFinishResult);
1470 }
1471 else
1472 {
Daniel Malead01b2952012-11-29 21:49:15 +00001473 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001474 result.SetStatus(eReturnStatusFailed);
1475 }
1476 }
1477 }
1478 else
1479 {
1480 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1481 result.SetStatus(eReturnStatusFailed);
1482 }
1483 return result.Succeeded();
1484 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001485 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001486 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001487 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001488 item_byte_size = buffer.GetAddressByteSize();
1489 else
1490 item_byte_size = 1;
1491 }
1492
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001493 command.Shift(); // shift off the address argument
1494 uint64_t uval64;
1495 int64_t sval64;
1496 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001497 const size_t num_value_args = command.GetArgumentCount();
1498 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001499 {
1500 const char *value_str = command.GetArgumentAtIndex(i);
1501
Greg Clayton1deb7962011-10-25 06:44:01 +00001502 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001503 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001504 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001505 case eFormatFloat: // TODO: add support for floats soon
1506 case eFormatCharPrintable:
1507 case eFormatBytesWithASCII:
1508 case eFormatComplex:
1509 case eFormatEnum:
1510 case eFormatUnicode16:
1511 case eFormatUnicode32:
1512 case eFormatVectorOfChar:
1513 case eFormatVectorOfSInt8:
1514 case eFormatVectorOfUInt8:
1515 case eFormatVectorOfSInt16:
1516 case eFormatVectorOfUInt16:
1517 case eFormatVectorOfSInt32:
1518 case eFormatVectorOfUInt32:
1519 case eFormatVectorOfSInt64:
1520 case eFormatVectorOfUInt64:
1521 case eFormatVectorOfFloat32:
1522 case eFormatVectorOfFloat64:
1523 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001524 case eFormatOSType:
1525 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001526 case eFormatAddressInfo:
1527 case eFormatHexFloat:
1528 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001529 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001530 result.AppendError("unsupported format for writing memory");
1531 result.SetStatus(eReturnStatusFailed);
1532 return false;
1533
1534 case eFormatDefault:
1535 case eFormatBytes:
1536 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001537 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001538 case eFormatPointer:
1539
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001540 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001541 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001542 if (!success)
1543 {
1544 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1545 result.SetStatus(eReturnStatusFailed);
1546 return false;
1547 }
1548 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1549 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001550 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 +00001551 result.SetStatus(eReturnStatusFailed);
1552 return false;
1553 }
1554 buffer.PutMaxHex64 (uval64, item_byte_size);
1555 break;
1556
1557 case eFormatBoolean:
1558 uval64 = Args::StringToBoolean(value_str, false, &success);
1559 if (!success)
1560 {
1561 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1562 result.SetStatus(eReturnStatusFailed);
1563 return false;
1564 }
1565 buffer.PutMaxHex64 (uval64, item_byte_size);
1566 break;
1567
1568 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001569 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001570 if (!success)
1571 {
1572 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1573 result.SetStatus(eReturnStatusFailed);
1574 return false;
1575 }
1576 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1577 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001578 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 +00001579 result.SetStatus(eReturnStatusFailed);
1580 return false;
1581 }
1582 buffer.PutMaxHex64 (uval64, item_byte_size);
1583 break;
1584
Greg Clayton4e4294b2011-06-17 23:50:44 +00001585 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001586 case eFormatChar:
1587 case eFormatCString:
1588 if (value_str[0])
1589 {
1590 size_t len = strlen (value_str);
1591 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001592 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001593 ++len;
1594 Error error;
1595 if (process->WriteMemory (addr, value_str, len, error) == len)
1596 {
1597 addr += len;
1598 }
1599 else
1600 {
Daniel Malead01b2952012-11-29 21:49:15 +00001601 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001602 result.SetStatus(eReturnStatusFailed);
1603 return false;
1604 }
1605 }
1606 break;
1607
1608 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001609 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001610 if (!success)
1611 {
1612 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1613 result.SetStatus(eReturnStatusFailed);
1614 return false;
1615 }
1616 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1617 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001618 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 +00001619 result.SetStatus(eReturnStatusFailed);
1620 return false;
1621 }
1622 buffer.PutMaxHex64 (sval64, item_byte_size);
1623 break;
1624
1625 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001626 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001627 if (!success)
1628 {
1629 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1630 result.SetStatus(eReturnStatusFailed);
1631 return false;
1632 }
1633 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1634 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001635 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 +00001636 result.SetStatus(eReturnStatusFailed);
1637 return false;
1638 }
1639 buffer.PutMaxHex64 (uval64, item_byte_size);
1640 break;
1641
1642 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001643 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001644 if (!success)
1645 {
1646 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1647 result.SetStatus(eReturnStatusFailed);
1648 return false;
1649 }
1650 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1651 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001652 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 +00001653 result.SetStatus(eReturnStatusFailed);
1654 return false;
1655 }
1656 buffer.PutMaxHex64 (uval64, item_byte_size);
1657 break;
1658 }
1659 }
1660
1661 if (!buffer.GetString().empty())
1662 {
1663 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001664 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001665 return true;
1666 else
1667 {
Daniel Malead01b2952012-11-29 21:49:15 +00001668 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001669 result.SetStatus(eReturnStatusFailed);
1670 return false;
1671 }
1672 }
1673 return true;
1674 }
1675
Greg Clayton1deb7962011-10-25 06:44:01 +00001676 OptionGroupOptions m_option_group;
1677 OptionGroupFormat m_format_options;
1678 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001679};
1680
Kuba Breckabeed8212014-09-04 01:03:18 +00001681//----------------------------------------------------------------------
1682// Get malloc/free history of a memory address.
1683//----------------------------------------------------------------------
1684class CommandObjectMemoryHistory : public CommandObjectParsed
1685{
1686public:
1687
1688 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1689 CommandObjectParsed (interpreter,
1690 "memory history",
1691 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1692 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001693 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
Kuba Breckabeed8212014-09-04 01:03:18 +00001694 {
1695 CommandArgumentEntry arg1;
1696 CommandArgumentData addr_arg;
1697
1698 // Define the first (and only) variant of this arg.
1699 addr_arg.arg_type = eArgTypeAddress;
1700 addr_arg.arg_repetition = eArgRepeatPlain;
1701
1702 // There is only one variant this argument could be; put it into the argument entry.
1703 arg1.push_back (addr_arg);
1704
1705 // Push the data for the first argument into the m_arguments vector.
1706 m_arguments.push_back (arg1);
1707 }
1708
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001709 ~CommandObjectMemoryHistory () override
Kuba Breckabeed8212014-09-04 01:03:18 +00001710 {
1711 }
1712
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001713 const char *
1714 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001715 {
1716 return m_cmd_name.c_str();
1717 }
1718
1719protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001720 bool
1721 DoExecute (Args& command, CommandReturnObject &result) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001722 {
1723 const size_t argc = command.GetArgumentCount();
1724
1725 if (argc == 0 || argc > 1)
1726 {
1727 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1728 result.SetStatus(eReturnStatusFailed);
1729 return false;
1730 }
1731
1732 Error error;
1733 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1734 command.GetArgumentAtIndex(0),
1735 LLDB_INVALID_ADDRESS,
1736 &error);
1737
1738 if (addr == LLDB_INVALID_ADDRESS)
1739 {
1740 result.AppendError("invalid address expression");
1741 result.AppendError(error.AsCString());
1742 result.SetStatus(eReturnStatusFailed);
1743 return false;
1744 }
1745
1746 Stream *output_stream = &result.GetOutputStream();
1747
1748 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1749 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1750
1751 if (! memory_history.get())
1752 {
1753 result.AppendError("no available memory history provider");
1754 result.SetStatus(eReturnStatusFailed);
1755 return false;
1756 }
1757
1758 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1759
1760 for (auto thread : thread_list) {
1761 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1762 }
1763
1764 result.SetStatus(eReturnStatusSuccessFinishResult);
1765
1766 return true;
1767 }
1768
1769};
1770
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001771
1772//-------------------------------------------------------------------------
1773// CommandObjectMemory
1774//-------------------------------------------------------------------------
1775
Greg Clayton66111032010-06-23 01:19:29 +00001776CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001777 CommandObjectMultiword (interpreter,
1778 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001779 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001780 "memory <subcommand> [<subcommand-options>]")
1781{
Enrico Granata53468432013-11-13 02:18:44 +00001782 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001783 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1784 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001785 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001786}
1787
1788CommandObjectMemory::~CommandObjectMemory ()
1789{
1790}