blob: f91a6be6d79b19064f24130eb29655fb34a3070c [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:
Ewan Crawforda0f08672015-10-16 08:28:47 +0000274 case eFormatVectorOfFloat16:
Greg Clayton84c39662011-04-27 22:04:39 +0000275 case eFormatVectorOfFloat32:
276 case eFormatVectorOfFloat64:
277 case eFormatVectorOfUInt128:
Greg Clayton68ebae62011-04-28 20:55:26 +0000278 if (!byte_size_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000279 byte_size_value = 128;
Greg Clayton68ebae62011-04-28 20:55:26 +0000280 if (!num_per_line_option_set)
281 m_num_per_line = 1;
282 if (!count_option_set)
Greg Clayton1deb7962011-10-25 06:44:01 +0000283 count_value = 4;
Greg Clayton84c39662011-04-27 22:04:39 +0000284 break;
285 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000286 return error;
Greg Clayton84c39662011-04-27 22:04:39 +0000287 }
288
Greg Clayton82f4cf42011-10-26 04:32:38 +0000289 bool
290 AnyOptionWasSet () const
291 {
292 return m_num_per_line.OptionWasSet() ||
293 m_output_as_binary ||
294 m_view_as_type.OptionWasSet();
295 }
296
Greg Clayton84c39662011-04-27 22:04:39 +0000297 OptionValueUInt64 m_num_per_line;
298 bool m_output_as_binary;
299 OptionValueString m_view_as_type;
Sean Callanan1276c332012-04-28 01:27:38 +0000300 bool m_force;
Greg Clayton84c39662011-04-27 22:04:39 +0000301};
302
303
304
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305//----------------------------------------------------------------------
306// Read memory from the inferior process
307//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +0000308class CommandObjectMemoryRead : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000309{
310public:
311
Greg Claytona7015092010-09-18 01:14:36 +0000312 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +0000313 CommandObjectParsed (interpreter,
314 "memory read",
315 "Read from the memory of the process being debugged.",
316 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +0000317 eCommandRequiresTarget | eCommandProcessMustBePaused),
Greg Clayton84c39662011-04-27 22:04:39 +0000318 m_option_group (interpreter),
Greg Clayton1deb7962011-10-25 06:44:01 +0000319 m_format_options (eFormatBytesWithASCII, 1, 8),
Greg Clayton84c39662011-04-27 22:04:39 +0000320 m_memory_options (),
Greg Clayton68ebae62011-04-28 20:55:26 +0000321 m_outfile_options (),
Greg Clayton82f4cf42011-10-26 04:32:38 +0000322 m_varobj_options(),
323 m_next_addr(LLDB_INVALID_ADDRESS),
324 m_prev_byte_size(0),
325 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
326 m_prev_memory_options (),
327 m_prev_outfile_options (),
328 m_prev_varobj_options()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000329 {
Caroline Tice405fe672010-10-04 22:28:36 +0000330 CommandArgumentEntry arg1;
331 CommandArgumentEntry arg2;
332 CommandArgumentData start_addr_arg;
333 CommandArgumentData end_addr_arg;
334
335 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000336 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000337 start_addr_arg.arg_repetition = eArgRepeatPlain;
338
339 // There is only one variant this argument could be; put it into the argument entry.
340 arg1.push_back (start_addr_arg);
341
342 // Define the first (and only) variant of this arg.
Enrico Granatab84a9db2013-01-29 01:48:30 +0000343 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
Caroline Tice405fe672010-10-04 22:28:36 +0000344 end_addr_arg.arg_repetition = eArgRepeatOptional;
345
346 // There is only one variant this argument could be; put it into the argument entry.
347 arg2.push_back (end_addr_arg);
348
349 // Push the data for the first argument into the m_arguments vector.
350 m_arguments.push_back (arg1);
351 m_arguments.push_back (arg2);
Greg Clayton84c39662011-04-27 22:04:39 +0000352
Greg Clayton1deb7962011-10-25 06:44:01 +0000353 // Add the "--format" and "--count" options to group 1 and 3
354 m_option_group.Append (&m_format_options,
355 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
Greg Clayton83889552011-11-22 18:07:35 +0000356 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000357 m_option_group.Append (&m_format_options,
358 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
Greg Clayton83889552011-11-22 18:07:35 +0000359 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
Greg Clayton1deb7962011-10-25 06:44:01 +0000360 // Add the "--size" option to group 1 and 2
361 m_option_group.Append (&m_format_options,
362 OptionGroupFormat::OPTION_GROUP_SIZE,
363 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
Greg Clayton84c39662011-04-27 22:04:39 +0000364 m_option_group.Append (&m_memory_options);
365 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 +0000366 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
Greg Clayton84c39662011-04-27 22:04:39 +0000367 m_option_group.Finalize();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000368 }
369
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000370 ~CommandObjectMemoryRead () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000371 {
372 }
373
374 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000375 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000376 {
Greg Clayton84c39662011-04-27 22:04:39 +0000377 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000378 }
379
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000380 const char *
381 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Greg Clayton82f4cf42011-10-26 04:32:38 +0000382 {
383 return m_cmd_name.c_str();
384 }
385
Jim Ingham5a988412012-06-08 21:56:10 +0000386protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000387 bool
388 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000389 {
Enrico Granatae87764f2015-05-27 05:04:35 +0000390 // No need to check "target" for validity as eCommandRequiresTarget ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +0000391 Target *target = m_exe_ctx.GetTargetPtr();
392
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000393 const size_t argc = command.GetArgumentCount();
394
Greg Clayton82f4cf42011-10-26 04:32:38 +0000395 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000396 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000397 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 +0000398 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000399 result.SetStatus(eReturnStatusFailed);
400 return false;
401 }
402
Greg Claytona1e5dc82015-08-11 22:53:00 +0000403 CompilerType clang_ast_type;
Greg Clayton68ebae62011-04-28 20:55:26 +0000404 Error error;
405
Greg Clayton84c39662011-04-27 22:04:39 +0000406 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
407 if (view_as_type_cstr && view_as_type_cstr[0])
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000408 {
Greg Clayton84c39662011-04-27 22:04:39 +0000409 // We are viewing memory as a type
Greg Clayton2e1f7452012-12-15 02:08:17 +0000410
Greg Clayton84c39662011-04-27 22:04:39 +0000411 SymbolContext sc;
Greg Clayton84db9102012-03-26 23:03:23 +0000412 const bool exact_match = false;
Greg Clayton84c39662011-04-27 22:04:39 +0000413 TypeList type_list;
414 uint32_t reference_count = 0;
415 uint32_t pointer_count = 0;
416 size_t idx;
Sean Callanan17cf1132012-07-10 21:24:26 +0000417
418#define ALL_KEYWORDS \
419 KEYWORD("const") \
420 KEYWORD("volatile") \
421 KEYWORD("restrict") \
422 KEYWORD("struct") \
423 KEYWORD("class") \
424 KEYWORD("union")
425
426#define KEYWORD(s) s,
427 static const char *g_keywords[] =
428 {
429 ALL_KEYWORDS
430 };
431#undef KEYWORD
432
433#define KEYWORD(s) (sizeof(s) - 1),
434 static const int g_keyword_lengths[] =
435 {
436 ALL_KEYWORDS
437 };
438#undef KEYWORD
439
440#undef ALL_KEYWORDS
441
442 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
Greg Clayton84c39662011-04-27 22:04:39 +0000443 std::string type_str(view_as_type_cstr);
444
445 // Remove all instances of g_keywords that are followed by spaces
446 for (size_t i = 0; i < g_num_keywords; ++i)
447 {
448 const char *keyword = g_keywords[i];
Sean Callanan17cf1132012-07-10 21:24:26 +0000449 int keyword_len = g_keyword_lengths[i];
450
451 idx = 0;
452 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
Greg Clayton84c39662011-04-27 22:04:39 +0000453 {
454 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
Sean Callanan17cf1132012-07-10 21:24:26 +0000455 {
Greg Clayton84c39662011-04-27 22:04:39 +0000456 type_str.erase(idx, keyword_len+1);
Sean Callanan17cf1132012-07-10 21:24:26 +0000457 idx = 0;
458 }
459 else
460 {
461 idx += keyword_len;
462 }
Greg Clayton84c39662011-04-27 22:04:39 +0000463 }
464 }
465 bool done = type_str.empty();
466 //
467 idx = type_str.find_first_not_of (" \t");
468 if (idx > 0 && idx != std::string::npos)
469 type_str.erase (0, idx);
470 while (!done)
471 {
472 // Strip trailing spaces
473 if (type_str.empty())
474 done = true;
475 else
476 {
477 switch (type_str[type_str.size()-1])
478 {
479 case '*':
480 ++pointer_count;
481 // fall through...
482 case ' ':
483 case '\t':
484 type_str.erase(type_str.size()-1);
485 break;
486
487 case '&':
488 if (reference_count == 0)
489 {
490 reference_count = 1;
491 type_str.erase(type_str.size()-1);
492 }
493 else
494 {
495 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
496 result.SetStatus(eReturnStatusFailed);
497 return false;
498 }
499 break;
500
501 default:
502 done = true;
503 break;
504 }
505 }
506 }
507
508 ConstString lookup_type_name(type_str.c_str());
Jason Molendab57e4a12013-11-04 09:33:30 +0000509 StackFrame *frame = m_exe_ctx.GetFramePtr();
Greg Claytonc14ee322011-09-22 04:58:26 +0000510 if (frame)
Greg Clayton84c39662011-04-27 22:04:39 +0000511 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000512 sc = frame->GetSymbolContext (eSymbolContextModule);
Greg Clayton84c39662011-04-27 22:04:39 +0000513 if (sc.module_sp)
514 {
Sean Callananb6d70eb2011-10-12 02:08:07 +0000515 sc.module_sp->FindTypes (sc,
516 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000517 exact_match,
Greg Clayton84c39662011-04-27 22:04:39 +0000518 1,
519 type_list);
520 }
521 }
522 if (type_list.GetSize() == 0)
523 {
Greg Clayton29399a22012-04-06 17:41:13 +0000524 target->GetImages().FindTypes (sc,
Greg Claytonc14ee322011-09-22 04:58:26 +0000525 lookup_type_name,
Greg Clayton84db9102012-03-26 23:03:23 +0000526 exact_match,
Greg Claytonc14ee322011-09-22 04:58:26 +0000527 1,
528 type_list);
Greg Clayton84c39662011-04-27 22:04:39 +0000529 }
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000530
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000531 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
Greg Clayton84c39662011-04-27 22:04:39 +0000532 {
Sean Callananb92bd752015-10-01 16:28:02 +0000533 if (ClangPersistentVariables *persistent_vars = llvm::dyn_cast_or_null<ClangPersistentVariables>(target->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)))
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000534 {
Sean Callananb92bd752015-10-01 16:28:02 +0000535 clang::TypeDecl *tdecl = persistent_vars->GetPersistentType(ConstString(lookup_type_name));
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000536
Sean Callananb92bd752015-10-01 16:28:02 +0000537 if (tdecl)
538 {
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000539 clang_ast_type.SetCompilerType(ClangASTContext::GetASTContext(&tdecl->getASTContext()),
540 reinterpret_cast<lldb::opaque_compiler_type_t>(const_cast<clang::Type*>(tdecl->getTypeForDecl())));
Sean Callananb92bd752015-10-01 16:28:02 +0000541 }
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000542 }
Greg Clayton84c39662011-04-27 22:04:39 +0000543 }
Saleem Abdulrasoolba507b02015-10-18 19:34:38 +0000544
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000545 if (clang_ast_type.IsValid() == false)
546 {
547 if (type_list.GetSize() == 0)
548 {
549 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
550 lookup_type_name.GetCString(),
551 view_as_type_cstr);
552 result.SetStatus(eReturnStatusFailed);
553 return false;
554 }
555 else
556 {
557 TypeSP type_sp (type_list.GetTypeAtIndex(0));
Greg Clayton99558cc42015-08-24 23:46:31 +0000558 clang_ast_type = type_sp->GetFullCompilerType ();
Enrico Granata7bd2bbb2013-06-11 18:47:55 +0000559 }
560 }
Greg Clayton84c39662011-04-27 22:04:39 +0000561
562 while (pointer_count > 0)
563 {
Greg Claytona1e5dc82015-08-11 22:53:00 +0000564 CompilerType pointer_type = clang_ast_type.GetPointerType();
Greg Clayton57ee3062013-07-11 22:46:58 +0000565 if (pointer_type.IsValid())
566 clang_ast_type = pointer_type;
Greg Clayton84c39662011-04-27 22:04:39 +0000567 else
568 {
569 result.AppendError ("unable make a pointer type\n");
570 result.SetStatus(eReturnStatusFailed);
571 return false;
572 }
573 --pointer_count;
574 }
575
Enrico Granata1cd5e922015-01-28 00:07:51 +0000576 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize(nullptr);
Greg Clayton84c39662011-04-27 22:04:39 +0000577
Greg Clayton1deb7962011-10-25 06:44:01 +0000578 if (m_format_options.GetByteSizeValue() == 0)
Greg Clayton84c39662011-04-27 22:04:39 +0000579 {
580 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
581 view_as_type_cstr);
582 result.SetStatus(eReturnStatusFailed);
583 return false;
584 }
Greg Clayton68ebae62011-04-28 20:55:26 +0000585
Greg Clayton1deb7962011-10-25 06:44:01 +0000586 if (!m_format_options.GetCountValue().OptionWasSet())
587 m_format_options.GetCountValue() = 1;
Greg Clayton84c39662011-04-27 22:04:39 +0000588 }
589 else
590 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000591 error = m_memory_options.FinalizeSettings (target, m_format_options);
Greg Clayton68ebae62011-04-28 20:55:26 +0000592 }
593
594 // Look for invalid combinations of settings
595 if (error.Fail())
596 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000597 result.AppendError(error.AsCString());
Greg Clayton68ebae62011-04-28 20:55:26 +0000598 result.SetStatus(eReturnStatusFailed);
599 return false;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000600 }
601
Greg Clayton82f4cf42011-10-26 04:32:38 +0000602 lldb::addr_t addr;
603 size_t total_byte_size = 0;
604 if (argc == 0)
605 {
606 // Use the last address and byte size and all options as they were
607 // if no options have been set
608 addr = m_next_addr;
609 total_byte_size = m_prev_byte_size;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000610 clang_ast_type = m_prev_clang_ast_type;
611 if (!m_format_options.AnyOptionWasSet() &&
Greg Clayton82f4cf42011-10-26 04:32:38 +0000612 !m_memory_options.AnyOptionWasSet() &&
613 !m_outfile_options.AnyOptionWasSet() &&
614 !m_varobj_options.AnyOptionWasSet())
615 {
616 m_format_options = m_prev_format_options;
617 m_memory_options = m_prev_memory_options;
618 m_outfile_options = m_prev_outfile_options;
619 m_varobj_options = m_prev_varobj_options;
620 }
621 }
622
Greg Clayton1deb7962011-10-25 06:44:01 +0000623 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000624
625 // TODO For non-8-bit byte addressable architectures this needs to be
626 // revisited to fully support all lldb's range of formatting options.
627 // Furthermore code memory reads (for those architectures) will not
628 // be correctly formatted even w/o formatting options.
629 size_t item_byte_size =
630 target->GetArchitecture().GetDataByteSize() > 1 ?
631 target->GetArchitecture().GetDataByteSize() :
632 m_format_options.GetByteSizeValue().GetCurrentValue();
633
Greg Clayton68ebae62011-04-28 20:55:26 +0000634 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000635
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000636 if (total_byte_size == 0)
Greg Clayton82f4cf42011-10-26 04:32:38 +0000637 {
638 total_byte_size = item_count * item_byte_size;
639 if (total_byte_size == 0)
640 total_byte_size = 32;
641 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642
Greg Clayton82f4cf42011-10-26 04:32:38 +0000643 if (argc > 0)
Greg Claytonf9fc6092013-01-09 19:44:40 +0000644 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000645
646 if (addr == LLDB_INVALID_ADDRESS)
647 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000648 result.AppendError("invalid start address expression.");
649 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000650 result.SetStatus(eReturnStatusFailed);
651 return false;
652 }
653
654 if (argc == 2)
655 {
Greg Claytonf9fc6092013-01-09 19:44:40 +0000656 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000657 if (end_addr == LLDB_INVALID_ADDRESS)
658 {
Greg Claytonb9d5df52012-12-06 22:49:16 +0000659 result.AppendError("invalid end address expression.");
660 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000661 result.SetStatus(eReturnStatusFailed);
662 return false;
663 }
664 else if (end_addr <= addr)
665 {
Daniel Malead01b2952012-11-29 21:49:15 +0000666 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 +0000667 result.SetStatus(eReturnStatusFailed);
668 return false;
669 }
Greg Clayton1deb7962011-10-25 06:44:01 +0000670 else if (m_format_options.GetCountValue().OptionWasSet())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000671 {
Greg Clayton6fea17e2014-03-03 19:15:20 +0000672 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 +0000673 result.SetStatus(eReturnStatusFailed);
674 return false;
675 }
676
677 total_byte_size = end_addr - addr;
678 item_count = total_byte_size / item_byte_size;
679 }
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000680
Enrico Granatad325bf92013-06-04 22:54:16 +0000681 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
682
683 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
Sean Callanan1276c332012-04-28 01:27:38 +0000684 {
Enrico Granatad325bf92013-06-04 22:54:16 +0000685 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
686 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
687 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 +0000688 return false;
689 }
690
Greg Clayton84c39662011-04-27 22:04:39 +0000691 DataBufferSP data_sp;
Greg Clayton84c39662011-04-27 22:04:39 +0000692 size_t bytes_read = 0;
Greg Clayton2e1f7452012-12-15 02:08:17 +0000693 if (clang_ast_type.GetOpaqueQualType())
694 {
695 // Make sure we don't display our type as ASCII bytes like the default memory read
696 if (m_format_options.GetFormatValue().OptionWasSet() == false)
697 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
698
Enrico Granata1cd5e922015-01-28 00:07:51 +0000699 bytes_read = clang_ast_type.GetByteSize(nullptr) * m_format_options.GetCountValue().GetCurrentValue();
Greg Clayton2e1f7452012-12-15 02:08:17 +0000700 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000701 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000702 {
Greg Clayton84c39662011-04-27 22:04:39 +0000703 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
Greg Clayton46a44262013-07-24 18:17:35 +0000704 if (data_sp->GetBytes() == NULL)
705 {
Virgile Belloffeba252014-03-08 17:15:35 +0000706 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 +0000707 result.SetStatus(eReturnStatusFailed);
708 return false;
709 }
710
Greg Claytone72dfb32012-02-24 01:59:29 +0000711 Address address(addr, NULL);
Greg Claytonc14ee322011-09-22 04:58:26 +0000712 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
Greg Clayton84c39662011-04-27 22:04:39 +0000713 if (bytes_read == 0)
714 {
Greg Clayton57f06302012-05-25 17:05:55 +0000715 const char *error_cstr = error.AsCString();
716 if (error_cstr && error_cstr[0])
717 {
718 result.AppendError(error_cstr);
719 }
720 else
721 {
Daniel Malead01b2952012-11-29 21:49:15 +0000722 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
Greg Clayton57f06302012-05-25 17:05:55 +0000723 }
Greg Clayton84c39662011-04-27 22:04:39 +0000724 result.SetStatus(eReturnStatusFailed);
725 return false;
726 }
727
728 if (bytes_read < total_byte_size)
Greg Clayton6fea17e2014-03-03 19:15:20 +0000729 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 +0000730 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000731 else
732 {
733 // we treat c-strings as a special case because they do not have a fixed size
734 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
735 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
736 else
737 item_byte_size = target->GetMaximumSizeOfStringSummary();
738 if (!m_format_options.GetCountValue().OptionWasSet())
739 item_count = 1;
740 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
Greg Clayton46a44262013-07-24 18:17:35 +0000741 if (data_sp->GetBytes() == NULL)
742 {
743 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));
744 result.SetStatus(eReturnStatusFailed);
745 return false;
746 }
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000747 uint8_t *data_ptr = data_sp->GetBytes();
748 auto data_addr = addr;
749 auto count = item_count;
750 item_count = 0;
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000751 bool break_on_no_NULL = false;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000752 while (item_count < count)
753 {
754 std::string buffer;
755 buffer.resize(item_byte_size+1,0);
756 Error error;
757 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
758 if (error.Fail())
759 {
760 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
761 result.SetStatus(eReturnStatusFailed);
762 return false;
763 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000764
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000765 if (item_byte_size == read)
766 {
767 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 +0000768 --read;
769 break_on_no_NULL = true;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000770 }
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000771 else
772 ++read; // account for final NULL byte
773
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000774 memcpy(data_ptr, &buffer[0], read);
775 data_ptr += read;
776 data_addr += read;
777 bytes_read += read;
778 item_count++; // if we break early we know we only read item_count strings
Enrico Granatadc3c3ee2015-04-06 18:41:17 +0000779
780 if (break_on_no_NULL)
781 break;
Enrico Granata6b4ddc62013-01-21 19:20:50 +0000782 }
783 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
784 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000785
Greg Clayton2e1f7452012-12-15 02:08:17 +0000786 m_next_addr = addr + bytes_read;
787 m_prev_byte_size = bytes_read;
788 m_prev_format_options = m_format_options;
789 m_prev_memory_options = m_memory_options;
790 m_prev_outfile_options = m_outfile_options;
791 m_prev_varobj_options = m_varobj_options;
792 m_prev_clang_ast_type = clang_ast_type;
793
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000794 StreamFile outfile_stream;
795 Stream *output_stream = NULL;
Greg Clayton84c39662011-04-27 22:04:39 +0000796 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
797 if (outfile_spec)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000798 {
799 char path[PATH_MAX];
Greg Clayton84c39662011-04-27 22:04:39 +0000800 outfile_spec.GetPath (path, sizeof(path));
801
802 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
803 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
804 if (append)
805 open_options |= File::eOpenOptionAppend;
806
807 if (outfile_stream.GetFile ().Open (path, open_options).Success())
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000808 {
Greg Clayton84c39662011-04-27 22:04:39 +0000809 if (m_memory_options.m_output_as_binary)
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000810 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000811 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000812 if (bytes_written > 0)
813 {
Greg Claytonc7bece562013-01-25 18:06:21 +0000814 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000815 bytes_written,
Greg Clayton84c39662011-04-27 22:04:39 +0000816 append ? "appended" : "written",
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000817 path);
818 return true;
819 }
820 else
821 {
Daniel Malead01b2952012-11-29 21:49:15 +0000822 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000823 result.SetStatus(eReturnStatusFailed);
824 return false;
825 }
826 }
827 else
828 {
829 // We are going to write ASCII to the file just point the
830 // output_stream to our outfile_stream...
831 output_stream = &outfile_stream;
832 }
833 }
834 else
835 {
Greg Clayton84c39662011-04-27 22:04:39 +0000836 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000837 result.SetStatus(eReturnStatusFailed);
838 return false;
839 }
840 }
841 else
842 {
843 output_stream = &result.GetOutputStream();
844 }
845
Greg Clayton84c39662011-04-27 22:04:39 +0000846
Greg Claytonf9fc6092013-01-09 19:44:40 +0000847 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
Greg Clayton84c39662011-04-27 22:04:39 +0000848 if (clang_ast_type.GetOpaqueQualType())
849 {
850 for (uint32_t i = 0; i<item_count; ++i)
851 {
852 addr_t item_addr = addr + (i * item_byte_size);
Greg Claytone72dfb32012-02-24 01:59:29 +0000853 Address address (item_addr);
Greg Clayton84c39662011-04-27 22:04:39 +0000854 StreamString name_strm;
Daniel Malead01b2952012-11-29 21:49:15 +0000855 name_strm.Printf ("0x%" PRIx64, item_addr);
Greg Clayton5009f9d2011-10-27 17:55:14 +0000856 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
Greg Clayton84c39662011-04-27 22:04:39 +0000857 name_strm.GetString().c_str(),
858 address,
859 clang_ast_type));
860 if (valobj_sp)
861 {
Greg Clayton2e1f7452012-12-15 02:08:17 +0000862 Format format = m_format_options.GetFormat();
Greg Clayton68ebae62011-04-28 20:55:26 +0000863 if (format != eFormatDefault)
864 valobj_sp->SetFormat (format);
865
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000866 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
Enrico Granata9fb5ab52013-03-26 18:04:53 +0000867
Enrico Granata4d93b8c2013-09-30 19:11:51 +0000868 valobj_sp->Dump(*output_stream,options);
Greg Clayton84c39662011-04-27 22:04:39 +0000869 }
870 else
871 {
872 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
873 view_as_type_cstr,
874 name_strm.GetString().c_str());
875 result.SetStatus(eReturnStatusFailed);
876 return false;
877 }
878 }
879 return true;
880 }
881
882 result.SetStatus(eReturnStatusSuccessFinishResult);
883 DataExtractor data (data_sp,
Greg Claytonc14ee322011-09-22 04:58:26 +0000884 target->GetArchitecture().GetByteOrder(),
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000885 target->GetArchitecture().GetAddressByteSize(),
886 target->GetArchitecture().GetDataByteSize());
Enrico Granata31898912013-05-21 17:39:04 +0000887
888 Format format = m_format_options.GetFormat();
889 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
Enrico Granata0947a6e2013-10-29 23:04:29 +0000890 && (item_byte_size != 1))
Enrico Granata31898912013-05-21 17:39:04 +0000891 {
Enrico Granata0947a6e2013-10-29 23:04:29 +0000892 // if a count was not passed, or it is 1
893 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
894 {
895 // this turns requests such as
896 // memory read -fc -s10 -c1 *charPtrPtr
897 // which make no sense (what is a char of size 10?)
898 // into a request for fetching 10 chars of size 1 from the same memory location
899 format = eFormatCharArray;
900 item_count = item_byte_size;
901 item_byte_size = 1;
902 }
903 else
904 {
905 // here we passed a count, and it was not 1
906 // so we have a byte_size and a count
907 // we could well multiply those, but instead let's just fail
Greg Clayton6fea17e2014-03-03 19:15:20 +0000908 result.AppendErrorWithFormat("reading memory as characters of size %" PRIu64 " is not supported", (uint64_t)item_byte_size);
Enrico Granata0947a6e2013-10-29 23:04:29 +0000909 result.SetStatus(eReturnStatusFailed);
910 return false;
911 }
Enrico Granata31898912013-05-21 17:39:04 +0000912 }
Greg Clayton84c39662011-04-27 22:04:39 +0000913
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000914 assert (output_stream);
Greg Claytonc7bece562013-01-25 18:06:21 +0000915 size_t bytes_dumped = data.Dump (output_stream,
916 0,
Enrico Granata31898912013-05-21 17:39:04 +0000917 format,
Greg Claytonc7bece562013-01-25 18:06:21 +0000918 item_byte_size,
919 item_count,
Matthew Gardinerf03e6d842014-09-29 08:02:24 +0000920 num_per_line / target->GetArchitecture().GetDataByteSize(),
Greg Claytonc7bece562013-01-25 18:06:21 +0000921 addr,
922 0,
923 0,
924 exe_scope);
Greg Clayton1848afb2011-10-28 23:44:55 +0000925 m_next_addr = addr + bytes_dumped;
Greg Clayton6d7e77b2010-10-10 20:52:20 +0000926 output_stream->EOL();
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000927 return true;
928 }
929
Greg Clayton84c39662011-04-27 22:04:39 +0000930 OptionGroupOptions m_option_group;
931 OptionGroupFormat m_format_options;
932 OptionGroupReadMemory m_memory_options;
933 OptionGroupOutputFile m_outfile_options;
Greg Clayton68ebae62011-04-28 20:55:26 +0000934 OptionGroupValueObjectDisplay m_varobj_options;
Greg Clayton82f4cf42011-10-26 04:32:38 +0000935 lldb::addr_t m_next_addr;
936 lldb::addr_t m_prev_byte_size;
937 OptionGroupFormat m_prev_format_options;
938 OptionGroupReadMemory m_prev_memory_options;
939 OptionGroupOutputFile m_prev_outfile_options;
940 OptionGroupValueObjectDisplay m_prev_varobj_options;
Greg Claytona1e5dc82015-08-11 22:53:00 +0000941 CompilerType m_prev_clang_ast_type;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000942};
943
Enrico Granata53468432013-11-13 02:18:44 +0000944OptionDefinition
945g_memory_find_option_table[] =
946{
Zachary Turnerd37221d2014-07-09 16:31:49 +0000947 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
948 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
949 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeCount, "How many times to perform the search."},
950 { 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 +0000951};
952
Enrico Granata53468432013-11-13 02:18:44 +0000953//----------------------------------------------------------------------
954// Find the specified data in memory
955//----------------------------------------------------------------------
956class CommandObjectMemoryFind : public CommandObjectParsed
957{
958public:
959
960 class OptionGroupFindMemory : public OptionGroup
961 {
962 public:
963 OptionGroupFindMemory () :
964 OptionGroup(),
965 m_count(1),
Enrico Granata8d81a842013-11-13 20:08:30 +0000966 m_offset(0)
Enrico Granata53468432013-11-13 02:18:44 +0000967 {
968 }
969
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000970 ~OptionGroupFindMemory () override
Enrico Granata53468432013-11-13 02:18:44 +0000971 {
972 }
973
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000974 uint32_t
975 GetNumDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000976 {
977 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
978 }
979
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000980 const OptionDefinition*
981 GetDefinitions () override
Enrico Granata53468432013-11-13 02:18:44 +0000982 {
983 return g_memory_find_option_table;
984 }
985
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000986 Error
Enrico Granata53468432013-11-13 02:18:44 +0000987 SetOptionValue (CommandInterpreter &interpreter,
988 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +0000989 const char *option_arg) override
Enrico Granata53468432013-11-13 02:18:44 +0000990 {
991 Error error;
992 const int short_option = g_memory_find_option_table[option_idx].short_option;
993
994 switch (short_option)
995 {
996 case 'e':
Pavel Labathc95f7e22015-02-20 11:14:59 +0000997 m_expr.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +0000998 break;
999
1000 case 's':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001001 m_string.SetValueFromString(option_arg);
Enrico Granata53468432013-11-13 02:18:44 +00001002 break;
1003
1004 case 'c':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001005 if (m_count.SetValueFromString(option_arg).Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001006 error.SetErrorString("unrecognized value for count");
1007 break;
1008
Enrico Granata8d81a842013-11-13 20:08:30 +00001009 case 'o':
Pavel Labathc95f7e22015-02-20 11:14:59 +00001010 if (m_offset.SetValueFromString(option_arg).Fail())
Enrico Granata8d81a842013-11-13 20:08:30 +00001011 error.SetErrorString("unrecognized value for dump-offset");
1012 break;
1013
Enrico Granata53468432013-11-13 02:18:44 +00001014 default:
1015 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1016 break;
1017 }
1018 return error;
1019 }
1020
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001021 void
1022 OptionParsingStarting (CommandInterpreter &interpreter) override
Enrico Granata53468432013-11-13 02:18:44 +00001023 {
1024 m_expr.Clear();
1025 m_string.Clear();
1026 m_count.Clear();
Enrico Granata53468432013-11-13 02:18:44 +00001027 }
1028
1029 OptionValueString m_expr;
1030 OptionValueString m_string;
1031 OptionValueUInt64 m_count;
Enrico Granata8d81a842013-11-13 20:08:30 +00001032 OptionValueUInt64 m_offset;
Enrico Granata53468432013-11-13 02:18:44 +00001033 };
1034
1035 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1036 CommandObjectParsed (interpreter,
1037 "memory find",
1038 "Find a value in the memory of the process being debugged.",
1039 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001040 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Enrico Granata53468432013-11-13 02:18:44 +00001041 m_option_group (interpreter),
1042 m_memory_options ()
1043 {
1044 CommandArgumentEntry arg1;
1045 CommandArgumentEntry arg2;
1046 CommandArgumentData addr_arg;
1047 CommandArgumentData value_arg;
1048
1049 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001050 addr_arg.arg_type = eArgTypeAddressOrExpression;
Enrico Granata53468432013-11-13 02:18:44 +00001051 addr_arg.arg_repetition = eArgRepeatPlain;
1052
1053 // There is only one variant this argument could be; put it into the argument entry.
1054 arg1.push_back (addr_arg);
1055
1056 // Define the first (and only) variant of this arg.
Enrico Granata760af882015-08-03 20:47:19 +00001057 value_arg.arg_type = eArgTypeAddressOrExpression;
1058 value_arg.arg_repetition = eArgRepeatPlain;
Enrico Granata53468432013-11-13 02:18:44 +00001059
1060 // There is only one variant this argument could be; put it into the argument entry.
1061 arg2.push_back (value_arg);
1062
1063 // Push the data for the first argument into the m_arguments vector.
1064 m_arguments.push_back (arg1);
1065 m_arguments.push_back (arg2);
1066
1067 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1068 m_option_group.Finalize();
1069 }
1070
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001071 ~CommandObjectMemoryFind () override
Enrico Granata53468432013-11-13 02:18:44 +00001072 {
1073 }
1074
1075 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001076 GetOptions () override
Enrico Granata53468432013-11-13 02:18:44 +00001077 {
1078 return &m_option_group;
1079 }
1080
1081protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001082 bool
1083 DoExecute (Args& command, CommandReturnObject &result) override
Enrico Granata53468432013-11-13 02:18:44 +00001084 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001085 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Enrico Granata53468432013-11-13 02:18:44 +00001086 Process *process = m_exe_ctx.GetProcessPtr();
1087
1088 const size_t argc = command.GetArgumentCount();
1089
1090 if (argc != 2)
1091 {
Enrico Granata6e49c482013-11-13 02:22:24 +00001092 result.AppendError("two addresses needed for memory find");
Enrico Granata53468432013-11-13 02:18:44 +00001093 return false;
1094 }
1095
1096 Error error;
1097 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1098 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1099 {
1100 result.AppendError("invalid low address");
1101 return false;
1102 }
1103 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1104 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1105 {
Ed Maste47a8a5e2014-09-06 11:29:08 +00001106 result.AppendError("invalid high address");
Enrico Granata53468432013-11-13 02:18:44 +00001107 return false;
1108 }
1109
1110 if (high_addr <= low_addr)
1111 {
1112 result.AppendError("starting address must be smaller than ending address");
1113 return false;
1114 }
1115
1116 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1117
1118 DataBufferHeap buffer;
1119
1120 if (m_memory_options.m_string.OptionWasSet())
1121 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1122 else if (m_memory_options.m_expr.OptionWasSet())
1123 {
1124 StackFrame* frame = m_exe_ctx.GetFramePtr();
1125 ValueObjectSP result_sp;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001126 if ((eExpressionCompleted == process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp)) &&
1127 result_sp.get())
Enrico Granata53468432013-11-13 02:18:44 +00001128 {
1129 uint64_t value = result_sp->GetValueAsUnsigned(0);
Greg Clayton99558cc42015-08-24 23:46:31 +00001130 switch (result_sp->GetCompilerType().GetByteSize(nullptr))
Enrico Granata53468432013-11-13 02:18:44 +00001131 {
1132 case 1: {
1133 uint8_t byte = (uint8_t)value;
1134 buffer.CopyData(&byte,1);
1135 }
1136 break;
1137 case 2: {
1138 uint16_t word = (uint16_t)value;
1139 buffer.CopyData(&word,2);
1140 }
1141 break;
1142 case 4: {
1143 uint32_t lword = (uint32_t)value;
1144 buffer.CopyData(&lword,4);
1145 }
1146 break;
1147 case 8: {
1148 buffer.CopyData(&value, 8);
1149 }
1150 break;
1151 case 3:
1152 case 5:
1153 case 6:
1154 case 7:
1155 result.AppendError("unknown type. pass a string instead");
1156 return false;
1157 default:
Enrico Granata0b3b9872015-08-03 18:51:39 +00001158 result.AppendError("result size larger than 8 bytes. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001159 return false;
1160 }
1161 }
1162 else
1163 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001164 result.AppendError("expression evaluation failed. pass a string instead");
Enrico Granata53468432013-11-13 02:18:44 +00001165 return false;
1166 }
1167 }
1168 else
1169 {
1170 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1171 return false;
1172 }
1173
1174 size_t count = m_memory_options.m_count.GetCurrentValue();
1175 found_location = low_addr;
1176 bool ever_found = false;
1177 while (count)
1178 {
1179 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1180 if (found_location == LLDB_INVALID_ADDRESS)
1181 {
1182 if (!ever_found)
1183 {
Enrico Granata0b3b9872015-08-03 18:51:39 +00001184 result.AppendMessage("data not found within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001185 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1186 }
1187 else
Enrico Granata0b3b9872015-08-03 18:51:39 +00001188 result.AppendMessage("no more matches within the range.\n");
Enrico Granata53468432013-11-13 02:18:44 +00001189 break;
1190 }
Enrico Granata0b3b9872015-08-03 18:51:39 +00001191 result.AppendMessageWithFormat("data found at location: 0x%" PRIx64 "\n", found_location);
Enrico Granata8d81a842013-11-13 20:08:30 +00001192
1193 DataBufferHeap dumpbuffer(32,0);
1194 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1195 if (!error.Fail())
Enrico Granata53468432013-11-13 02:18:44 +00001196 {
Enrico Granata8d81a842013-11-13 20:08:30 +00001197 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1198 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1199 result.GetOutputStream().EOL();
Enrico Granata53468432013-11-13 02:18:44 +00001200 }
Enrico Granata8d81a842013-11-13 20:08:30 +00001201
Enrico Granata53468432013-11-13 02:18:44 +00001202 --count;
1203 found_location++;
1204 ever_found = true;
1205 }
1206
1207 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1208 return true;
1209 }
1210
1211 lldb::addr_t
1212 Search (lldb::addr_t low,
1213 lldb::addr_t high,
1214 uint8_t* buffer,
1215 size_t buffer_size)
1216 {
1217 Process *process = m_exe_ctx.GetProcessPtr();
1218 DataBufferHeap heap(buffer_size, 0);
Enrico Granata53468432013-11-13 02:18:44 +00001219 for (auto ptr = low;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001220 ptr < high;
1221 ptr++)
Enrico Granata53468432013-11-13 02:18:44 +00001222 {
1223 Error error;
Enrico Granata0b3b9872015-08-03 18:51:39 +00001224 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
Enrico Granata53468432013-11-13 02:18:44 +00001225 if (error.Fail())
1226 return LLDB_INVALID_ADDRESS;
1227 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
Enrico Granata0b3b9872015-08-03 18:51:39 +00001228 return ptr;
Enrico Granata53468432013-11-13 02:18:44 +00001229 }
1230 return LLDB_INVALID_ADDRESS;
1231 }
1232
1233 OptionGroupOptions m_option_group;
1234 OptionGroupFindMemory m_memory_options;
1235};
1236
Greg Clayton1deb7962011-10-25 06:44:01 +00001237
1238OptionDefinition
1239g_memory_write_option_table[] =
1240{
Zachary Turnerd37221d2014-07-09 16:31:49 +00001241{ 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 +00001242{ 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 +00001243};
1244
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001245//----------------------------------------------------------------------
1246// Write memory to the inferior process
1247//----------------------------------------------------------------------
Jim Ingham5a988412012-06-08 21:56:10 +00001248class CommandObjectMemoryWrite : public CommandObjectParsed
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001249{
1250public:
1251
Greg Clayton1deb7962011-10-25 06:44:01 +00001252 class OptionGroupWriteMemory : public OptionGroup
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001253 {
1254 public:
Greg Clayton1deb7962011-10-25 06:44:01 +00001255 OptionGroupWriteMemory () :
1256 OptionGroup()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001257 {
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001258 }
1259
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001260 ~OptionGroupWriteMemory () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001261 {
1262 }
1263
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001264 uint32_t
1265 GetNumDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001266 {
1267 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1268 }
Enrico Granata53468432013-11-13 02:18:44 +00001269
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001270 const OptionDefinition*
1271 GetDefinitions () override
Greg Clayton1deb7962011-10-25 06:44:01 +00001272 {
1273 return g_memory_write_option_table;
1274 }
Enrico Granata53468432013-11-13 02:18:44 +00001275
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001276 Error
Greg Clayton1deb7962011-10-25 06:44:01 +00001277 SetOptionValue (CommandInterpreter &interpreter,
1278 uint32_t option_idx,
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001279 const char *option_arg) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001280 {
1281 Error error;
Greg Clayton3bcdfc02012-12-04 00:32:51 +00001282 const int short_option = g_memory_write_option_table[option_idx].short_option;
Enrico Granata53468432013-11-13 02:18:44 +00001283
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001284 switch (short_option)
1285 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001286 case 'i':
1287 m_infile.SetFile (option_arg, true);
1288 if (!m_infile.Exists())
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001289 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001290 m_infile.Clear();
Greg Clayton86edbf42011-10-26 00:56:27 +00001291 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001292 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001293 break;
Enrico Granata53468432013-11-13 02:18:44 +00001294
Greg Clayton1deb7962011-10-25 06:44:01 +00001295 case 'o':
1296 {
1297 bool success;
Vince Harron5275aaa2015-01-15 20:08:35 +00001298 m_infile_offset = StringConvert::ToUInt64(option_arg, 0, 0, &success);
Greg Clayton1deb7962011-10-25 06:44:01 +00001299 if (!success)
1300 {
Greg Clayton86edbf42011-10-26 00:56:27 +00001301 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
Greg Clayton1deb7962011-10-25 06:44:01 +00001302 }
1303 }
1304 break;
1305
1306 default:
Greg Clayton86edbf42011-10-26 00:56:27 +00001307 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
Greg Clayton1deb7962011-10-25 06:44:01 +00001308 break;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001309 }
1310 return error;
1311 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001312
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001313 void
1314 OptionParsingStarting (CommandInterpreter &interpreter) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001315 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001316 m_infile.Clear();
1317 m_infile_offset = 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001318 }
1319
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001320 FileSpec m_infile;
1321 off_t m_infile_offset;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001322 };
1323
Greg Claytona7015092010-09-18 01:14:36 +00001324 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
Jim Ingham5a988412012-06-08 21:56:10 +00001325 CommandObjectParsed (interpreter,
1326 "memory write",
1327 "Write to the memory of the process being debugged.",
1328 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001329 eCommandRequiresProcess | eCommandProcessMustBeLaunched),
Greg Clayton1deb7962011-10-25 06:44:01 +00001330 m_option_group (interpreter),
1331 m_format_options (eFormatBytes, 1, UINT64_MAX),
1332 m_memory_options ()
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001333 {
Caroline Tice405fe672010-10-04 22:28:36 +00001334 CommandArgumentEntry arg1;
1335 CommandArgumentEntry arg2;
1336 CommandArgumentData addr_arg;
1337 CommandArgumentData value_arg;
1338
1339 // Define the first (and only) variant of this arg.
1340 addr_arg.arg_type = eArgTypeAddress;
1341 addr_arg.arg_repetition = eArgRepeatPlain;
1342
1343 // There is only one variant this argument could be; put it into the argument entry.
1344 arg1.push_back (addr_arg);
1345
1346 // Define the first (and only) variant of this arg.
1347 value_arg.arg_type = eArgTypeValue;
1348 value_arg.arg_repetition = eArgRepeatPlus;
1349
1350 // There is only one variant this argument could be; put it into the argument entry.
1351 arg2.push_back (value_arg);
1352
1353 // Push the data for the first argument into the m_arguments vector.
1354 m_arguments.push_back (arg1);
1355 m_arguments.push_back (arg2);
Greg Clayton1deb7962011-10-25 06:44:01 +00001356
1357 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1358 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1359 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1360 m_option_group.Finalize();
1361
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001362 }
1363
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001364 ~CommandObjectMemoryWrite () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001365 {
1366 }
1367
1368 Options *
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001369 GetOptions () override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001370 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001371 return &m_option_group;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001372 }
1373
1374 bool
1375 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1376 {
1377 if (total_byte_size > 8)
1378 return false;
1379
1380 if (total_byte_size == 8)
1381 return true;
1382
1383 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1384 return uval64 <= max;
1385 }
1386
1387 bool
1388 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1389 {
1390 if (total_byte_size > 8)
1391 return false;
1392
1393 if (total_byte_size == 8)
1394 return true;
1395
1396 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1397 const int64_t min = ~(max);
1398 return min <= sval64 && sval64 <= max;
1399 }
1400
Jim Ingham5a988412012-06-08 21:56:10 +00001401protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001402 bool
1403 DoExecute (Args& command, CommandReturnObject &result) override
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001404 {
Enrico Granatae87764f2015-05-27 05:04:35 +00001405 // No need to check "process" for validity as eCommandRequiresProcess ensures it is valid
Greg Claytonf9fc6092013-01-09 19:44:40 +00001406 Process *process = m_exe_ctx.GetProcessPtr();
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001407
1408 const size_t argc = command.GetArgumentCount();
1409
Greg Clayton1deb7962011-10-25 06:44:01 +00001410 if (m_memory_options.m_infile)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001411 {
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001412 if (argc < 1)
1413 {
1414 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1415 result.SetStatus(eReturnStatusFailed);
1416 return false;
1417 }
1418 }
1419 else if (argc < 2)
1420 {
1421 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 +00001422 result.SetStatus(eReturnStatusFailed);
1423 return false;
1424 }
1425
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001426 StreamString buffer (Stream::eBinary,
Greg Clayton514487e2011-02-15 21:59:32 +00001427 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1428 process->GetTarget().GetArchitecture().GetByteOrder());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001429
Greg Clayton1deb7962011-10-25 06:44:01 +00001430 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1431 size_t item_byte_size = byte_size_value.GetCurrentValue();
Greg Claytonc982c762010-07-09 20:39:50 +00001432
Greg Claytonb9d5df52012-12-06 22:49:16 +00001433 Error error;
Greg Claytonf9fc6092013-01-09 19:44:40 +00001434 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
Greg Claytonb9d5df52012-12-06 22:49:16 +00001435 command.GetArgumentAtIndex(0),
1436 LLDB_INVALID_ADDRESS,
1437 &error);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001438
1439 if (addr == LLDB_INVALID_ADDRESS)
1440 {
Greg Claytonb9d5df52012-12-06 22:49:16 +00001441 result.AppendError("invalid address expression\n");
1442 result.AppendError(error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001443 result.SetStatus(eReturnStatusFailed);
1444 return false;
1445 }
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001446
Greg Clayton1deb7962011-10-25 06:44:01 +00001447 if (m_memory_options.m_infile)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001448 {
1449 size_t length = SIZE_MAX;
Jason Molenda250b1b892015-02-03 23:39:47 +00001450 if (item_byte_size > 1)
Greg Clayton1deb7962011-10-25 06:44:01 +00001451 length = item_byte_size;
1452 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001453 if (data_sp)
1454 {
1455 length = data_sp->GetByteSize();
1456 if (length > 0)
1457 {
1458 Error error;
1459 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1460
1461 if (bytes_written == length)
1462 {
1463 // All bytes written
Daniel Malead01b2952012-11-29 21:49:15 +00001464 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001465 result.SetStatus(eReturnStatusSuccessFinishResult);
1466 }
1467 else if (bytes_written > 0)
1468 {
1469 // Some byte written
Daniel Malead01b2952012-11-29 21:49:15 +00001470 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 +00001471 result.SetStatus(eReturnStatusSuccessFinishResult);
1472 }
1473 else
1474 {
Daniel Malead01b2952012-11-29 21:49:15 +00001475 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001476 result.SetStatus(eReturnStatusFailed);
1477 }
1478 }
1479 }
1480 else
1481 {
1482 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1483 result.SetStatus(eReturnStatusFailed);
1484 }
1485 return result.Succeeded();
1486 }
Greg Clayton1deb7962011-10-25 06:44:01 +00001487 else if (item_byte_size == 0)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001488 {
Greg Clayton1deb7962011-10-25 06:44:01 +00001489 if (m_format_options.GetFormat() == eFormatPointer)
Greg Clayton6d7e77b2010-10-10 20:52:20 +00001490 item_byte_size = buffer.GetAddressByteSize();
1491 else
1492 item_byte_size = 1;
1493 }
1494
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001495 command.Shift(); // shift off the address argument
1496 uint64_t uval64;
1497 int64_t sval64;
1498 bool success = false;
Greg Claytonc7bece562013-01-25 18:06:21 +00001499 const size_t num_value_args = command.GetArgumentCount();
1500 for (size_t i=0; i<num_value_args; ++i)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001501 {
1502 const char *value_str = command.GetArgumentAtIndex(i);
1503
Greg Clayton1deb7962011-10-25 06:44:01 +00001504 switch (m_format_options.GetFormat())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001505 {
Greg Claytonbb7f31f2011-06-23 21:22:24 +00001506 case kNumFormats:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001507 case eFormatFloat: // TODO: add support for floats soon
1508 case eFormatCharPrintable:
1509 case eFormatBytesWithASCII:
1510 case eFormatComplex:
1511 case eFormatEnum:
1512 case eFormatUnicode16:
1513 case eFormatUnicode32:
1514 case eFormatVectorOfChar:
1515 case eFormatVectorOfSInt8:
1516 case eFormatVectorOfUInt8:
1517 case eFormatVectorOfSInt16:
1518 case eFormatVectorOfUInt16:
1519 case eFormatVectorOfSInt32:
1520 case eFormatVectorOfUInt32:
1521 case eFormatVectorOfSInt64:
1522 case eFormatVectorOfUInt64:
Enrico Granata15560772015-10-16 23:42:04 +00001523 case eFormatVectorOfFloat16:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001524 case eFormatVectorOfFloat32:
1525 case eFormatVectorOfFloat64:
1526 case eFormatVectorOfUInt128:
Greg Clayton7a5388b2011-03-20 04:57:14 +00001527 case eFormatOSType:
1528 case eFormatComplexInteger:
Greg Clayton5009f9d2011-10-27 17:55:14 +00001529 case eFormatAddressInfo:
1530 case eFormatHexFloat:
1531 case eFormatInstruction:
Sean Callananbf154da2012-08-08 17:35:10 +00001532 case eFormatVoid:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001533 result.AppendError("unsupported format for writing memory");
1534 result.SetStatus(eReturnStatusFailed);
1535 return false;
1536
1537 case eFormatDefault:
1538 case eFormatBytes:
1539 case eFormatHex:
Enrico Granata7ec18e32012-08-09 19:33:34 +00001540 case eFormatHexUppercase:
Greg Claytonc982c762010-07-09 20:39:50 +00001541 case eFormatPointer:
1542
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001543 // Decode hex bytes
Vince Harron5275aaa2015-01-15 20:08:35 +00001544 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 16, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001545 if (!success)
1546 {
1547 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1548 result.SetStatus(eReturnStatusFailed);
1549 return false;
1550 }
1551 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1552 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001553 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 +00001554 result.SetStatus(eReturnStatusFailed);
1555 return false;
1556 }
1557 buffer.PutMaxHex64 (uval64, item_byte_size);
1558 break;
1559
1560 case eFormatBoolean:
1561 uval64 = Args::StringToBoolean(value_str, false, &success);
1562 if (!success)
1563 {
1564 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1565 result.SetStatus(eReturnStatusFailed);
1566 return false;
1567 }
1568 buffer.PutMaxHex64 (uval64, item_byte_size);
1569 break;
1570
1571 case eFormatBinary:
Vince Harron5275aaa2015-01-15 20:08:35 +00001572 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 2, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001573 if (!success)
1574 {
1575 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1576 result.SetStatus(eReturnStatusFailed);
1577 return false;
1578 }
1579 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1580 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001581 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 +00001582 result.SetStatus(eReturnStatusFailed);
1583 return false;
1584 }
1585 buffer.PutMaxHex64 (uval64, item_byte_size);
1586 break;
1587
Greg Clayton4e4294b2011-06-17 23:50:44 +00001588 case eFormatCharArray:
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001589 case eFormatChar:
1590 case eFormatCString:
1591 if (value_str[0])
1592 {
1593 size_t len = strlen (value_str);
1594 // Include the NULL for C strings...
Greg Clayton1deb7962011-10-25 06:44:01 +00001595 if (m_format_options.GetFormat() == eFormatCString)
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001596 ++len;
1597 Error error;
1598 if (process->WriteMemory (addr, value_str, len, error) == len)
1599 {
1600 addr += len;
1601 }
1602 else
1603 {
Daniel Malead01b2952012-11-29 21:49:15 +00001604 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001605 result.SetStatus(eReturnStatusFailed);
1606 return false;
1607 }
1608 }
1609 break;
1610
1611 case eFormatDecimal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001612 sval64 = StringConvert::ToSInt64(value_str, INT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001613 if (!success)
1614 {
1615 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1616 result.SetStatus(eReturnStatusFailed);
1617 return false;
1618 }
1619 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1620 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001621 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 +00001622 result.SetStatus(eReturnStatusFailed);
1623 return false;
1624 }
1625 buffer.PutMaxHex64 (sval64, item_byte_size);
1626 break;
1627
1628 case eFormatUnsigned:
Vince Harron5275aaa2015-01-15 20:08:35 +00001629 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 0, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001630 if (!success)
1631 {
1632 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1633 result.SetStatus(eReturnStatusFailed);
1634 return false;
1635 }
1636 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1637 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001638 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 +00001639 result.SetStatus(eReturnStatusFailed);
1640 return false;
1641 }
1642 buffer.PutMaxHex64 (uval64, item_byte_size);
1643 break;
1644
1645 case eFormatOctal:
Vince Harron5275aaa2015-01-15 20:08:35 +00001646 uval64 = StringConvert::ToUInt64(value_str, UINT64_MAX, 8, &success);
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001647 if (!success)
1648 {
1649 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1650 result.SetStatus(eReturnStatusFailed);
1651 return false;
1652 }
1653 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1654 {
Greg Clayton6fea17e2014-03-03 19:15:20 +00001655 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 +00001656 result.SetStatus(eReturnStatusFailed);
1657 return false;
1658 }
1659 buffer.PutMaxHex64 (uval64, item_byte_size);
1660 break;
1661 }
1662 }
1663
1664 if (!buffer.GetString().empty())
1665 {
1666 Error error;
Greg Clayton471b31c2010-07-20 22:52:08 +00001667 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001668 return true;
1669 else
1670 {
Daniel Malead01b2952012-11-29 21:49:15 +00001671 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001672 result.SetStatus(eReturnStatusFailed);
1673 return false;
1674 }
1675 }
1676 return true;
1677 }
1678
Greg Clayton1deb7962011-10-25 06:44:01 +00001679 OptionGroupOptions m_option_group;
1680 OptionGroupFormat m_format_options;
1681 OptionGroupWriteMemory m_memory_options;
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001682};
1683
Kuba Breckabeed8212014-09-04 01:03:18 +00001684//----------------------------------------------------------------------
1685// Get malloc/free history of a memory address.
1686//----------------------------------------------------------------------
1687class CommandObjectMemoryHistory : public CommandObjectParsed
1688{
1689public:
1690
1691 CommandObjectMemoryHistory (CommandInterpreter &interpreter) :
1692 CommandObjectParsed (interpreter,
1693 "memory history",
1694 "Prints out the recorded stack traces for allocation/deallocation of a memory address.",
1695 NULL,
Enrico Granatae87764f2015-05-27 05:04:35 +00001696 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBePaused | eCommandProcessMustBeLaunched)
Kuba Breckabeed8212014-09-04 01:03:18 +00001697 {
1698 CommandArgumentEntry arg1;
1699 CommandArgumentData addr_arg;
1700
1701 // Define the first (and only) variant of this arg.
1702 addr_arg.arg_type = eArgTypeAddress;
1703 addr_arg.arg_repetition = eArgRepeatPlain;
1704
1705 // There is only one variant this argument could be; put it into the argument entry.
1706 arg1.push_back (addr_arg);
1707
1708 // Push the data for the first argument into the m_arguments vector.
1709 m_arguments.push_back (arg1);
1710 }
1711
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001712 ~CommandObjectMemoryHistory () override
Kuba Breckabeed8212014-09-04 01:03:18 +00001713 {
1714 }
1715
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001716 const char *
1717 GetRepeatCommand (Args &current_command_args, uint32_t index) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001718 {
1719 return m_cmd_name.c_str();
1720 }
1721
1722protected:
Bruce Mitchener13d21e92015-10-07 16:56:17 +00001723 bool
1724 DoExecute (Args& command, CommandReturnObject &result) override
Kuba Breckabeed8212014-09-04 01:03:18 +00001725 {
1726 const size_t argc = command.GetArgumentCount();
1727
1728 if (argc == 0 || argc > 1)
1729 {
1730 result.AppendErrorWithFormat ("%s takes an address expression", m_cmd_name.c_str());
1731 result.SetStatus(eReturnStatusFailed);
1732 return false;
1733 }
1734
1735 Error error;
1736 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1737 command.GetArgumentAtIndex(0),
1738 LLDB_INVALID_ADDRESS,
1739 &error);
1740
1741 if (addr == LLDB_INVALID_ADDRESS)
1742 {
1743 result.AppendError("invalid address expression");
1744 result.AppendError(error.AsCString());
1745 result.SetStatus(eReturnStatusFailed);
1746 return false;
1747 }
1748
1749 Stream *output_stream = &result.GetOutputStream();
1750
1751 const ProcessSP &process_sp = m_exe_ctx.GetProcessSP();
1752 const MemoryHistorySP &memory_history = MemoryHistory::FindPlugin(process_sp);
1753
1754 if (! memory_history.get())
1755 {
1756 result.AppendError("no available memory history provider");
1757 result.SetStatus(eReturnStatusFailed);
1758 return false;
1759 }
1760
1761 HistoryThreads thread_list = memory_history->GetHistoryThreads(addr);
1762
1763 for (auto thread : thread_list) {
1764 thread->GetStatus(*output_stream, 0, UINT32_MAX, 0);
1765 }
1766
1767 result.SetStatus(eReturnStatusSuccessFinishResult);
1768
1769 return true;
1770 }
1771
1772};
1773
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001774
1775//-------------------------------------------------------------------------
1776// CommandObjectMemory
1777//-------------------------------------------------------------------------
1778
Greg Clayton66111032010-06-23 01:19:29 +00001779CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
Greg Claytona7015092010-09-18 01:14:36 +00001780 CommandObjectMultiword (interpreter,
1781 "memory",
Caroline Tice3f4c09c2010-09-07 22:38:08 +00001782 "A set of commands for operating on memory.",
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001783 "memory <subcommand> [<subcommand-options>]")
1784{
Enrico Granata53468432013-11-13 02:18:44 +00001785 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
Greg Claytona7015092010-09-18 01:14:36 +00001786 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1787 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
Kuba Breckabeed8212014-09-04 01:03:18 +00001788 LoadSubCommand ("history", CommandObjectSP (new CommandObjectMemoryHistory (interpreter)));
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001789}
1790
1791CommandObjectMemory::~CommandObjectMemory ()
1792{
1793}