1 //===-- CommandObjectMemory.cpp ---------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
12 #include "CommandObjectMemory.h"
18 // Other libraries and framework includes
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/Module.h"
24 #include "lldb/Core/StreamString.h"
25 #include "lldb/Core/ValueObjectMemory.h"
26 #include "lldb/DataFormatters/ValueObjectPrinter.h"
27 #include "lldb/Interpreter/Args.h"
28 #include "lldb/Interpreter/CommandReturnObject.h"
29 #include "lldb/Interpreter/CommandInterpreter.h"
30 #include "lldb/Interpreter/Options.h"
31 #include "lldb/Interpreter/OptionGroupFormat.h"
32 #include "lldb/Interpreter/OptionGroupOutputFile.h"
33 #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h"
34 #include "lldb/Interpreter/OptionValueString.h"
35 #include "lldb/Symbol/TypeList.h"
36 #include "lldb/Target/Process.h"
37 #include "lldb/Target/StackFrame.h"
40 using namespace lldb_private;
42 static OptionDefinition
45 { LLDB_OPT_SET_1, false, "num-per-line" ,'l', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNumberPerLine ,"The number of items per line to display."},
46 { LLDB_OPT_SET_2, false, "binary" ,'b', OptionParser::eNoArgument , 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."},
47 { LLDB_OPT_SET_3, true , "type" ,'t', OptionParser::eRequiredArgument, NULL, 0, eArgTypeNone ,"The name of a type to view memory as."},
50 LLDB_OPT_SET_3, false, "force" ,'r', OptionParser::eNoArgument, NULL, 0, eArgTypeNone ,"Necessary if reading over target.max-memory-read-size bytes."},
55 class OptionGroupReadMemory : public OptionGroup
59 OptionGroupReadMemory () :
61 m_output_as_binary (false),
67 ~OptionGroupReadMemory ()
75 return sizeof (g_option_table) / sizeof (OptionDefinition);
78 virtual const OptionDefinition*
81 return g_option_table;
85 SetOptionValue (CommandInterpreter &interpreter,
87 const char *option_arg)
90 const int short_option = g_option_table[option_idx].short_option;
95 error = m_num_per_line.SetValueFromCString (option_arg);
96 if (m_num_per_line.GetCurrentValue() == 0)
97 error.SetErrorStringWithFormat("invalid value for --num-per-line option '%s'", option_arg);
101 m_output_as_binary = true;
105 error = m_view_as_type.SetValueFromCString (option_arg);
113 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
120 OptionParsingStarting (CommandInterpreter &interpreter)
122 m_num_per_line.Clear();
123 m_output_as_binary = false;
124 m_view_as_type.Clear();
129 FinalizeSettings (Target *target, OptionGroupFormat& format_options)
132 OptionValueUInt64 &byte_size_value = format_options.GetByteSizeValue();
133 OptionValueUInt64 &count_value = format_options.GetCountValue();
134 const bool byte_size_option_set = byte_size_value.OptionWasSet();
135 const bool num_per_line_option_set = m_num_per_line.OptionWasSet();
136 const bool count_option_set = format_options.GetCountValue().OptionWasSet();
138 switch (format_options.GetFormat())
144 if (!byte_size_option_set)
146 if (!num_per_line_option_set)
148 if (!count_option_set)
149 format_options.GetCountValue() = 8;
155 case eFormatInstruction:
156 if (count_option_set)
157 byte_size_value = target->GetArchitecture().GetMaximumOpcodeByteSize();
161 case eFormatAddressInfo:
162 if (!byte_size_option_set)
163 byte_size_value = target->GetArchitecture().GetAddressByteSize();
165 if (!count_option_set)
166 format_options.GetCountValue() = 8;
170 byte_size_value = target->GetArchitecture().GetAddressByteSize();
171 if (!num_per_line_option_set)
173 if (!count_option_set)
174 format_options.GetCountValue() = 8;
182 case eFormatUnicode16:
183 case eFormatUnicode32:
184 case eFormatUnsigned:
185 case eFormatHexFloat:
186 if (!byte_size_option_set)
188 if (!num_per_line_option_set)
190 if (!count_option_set)
191 format_options.GetCountValue() = 8;
195 case eFormatBytesWithASCII:
196 if (byte_size_option_set)
198 if (byte_size_value > 1)
199 error.SetErrorStringWithFormat ("display format (bytes/bytes with ascii) conflicts with the specified byte size %" PRIu64 "\n"
200 "\tconsider using a different display format or don't specify the byte size",
201 byte_size_value.GetCurrentValue());
205 if (!num_per_line_option_set)
207 if (!count_option_set)
208 format_options.GetCountValue() = 32;
210 case eFormatCharArray:
212 case eFormatCharPrintable:
213 if (!byte_size_option_set)
215 if (!num_per_line_option_set)
217 if (!count_option_set)
218 format_options.GetCountValue() = 64;
221 if (!byte_size_option_set)
223 if (!num_per_line_option_set)
225 if (!count_option_set)
226 format_options.GetCountValue() = 8;
228 case eFormatComplexInteger:
229 if (!byte_size_option_set)
231 if (!num_per_line_option_set)
233 if (!count_option_set)
234 format_options.GetCountValue() = 8;
237 if (!byte_size_option_set)
239 if (!num_per_line_option_set)
241 switch (byte_size_value)
258 if (!count_option_set)
262 case eFormatVectorOfChar:
263 case eFormatVectorOfSInt8:
264 case eFormatVectorOfUInt8:
265 case eFormatVectorOfSInt16:
266 case eFormatVectorOfUInt16:
267 case eFormatVectorOfSInt32:
268 case eFormatVectorOfUInt32:
269 case eFormatVectorOfSInt64:
270 case eFormatVectorOfUInt64:
271 case eFormatVectorOfFloat32:
272 case eFormatVectorOfFloat64:
273 case eFormatVectorOfUInt128:
274 if (!byte_size_option_set)
275 byte_size_value = 128;
276 if (!num_per_line_option_set)
278 if (!count_option_set)
286 AnyOptionWasSet () const
288 return m_num_per_line.OptionWasSet() ||
289 m_output_as_binary ||
290 m_view_as_type.OptionWasSet();
293 OptionValueUInt64 m_num_per_line;
294 bool m_output_as_binary;
295 OptionValueString m_view_as_type;
301 //----------------------------------------------------------------------
302 // Read memory from the inferior process
303 //----------------------------------------------------------------------
304 class CommandObjectMemoryRead : public CommandObjectParsed
308 CommandObjectMemoryRead (CommandInterpreter &interpreter) :
309 CommandObjectParsed (interpreter,
311 "Read from the memory of the process being debugged.",
313 eFlagRequiresTarget | eFlagProcessMustBePaused),
314 m_option_group (interpreter),
315 m_format_options (eFormatBytesWithASCII, 1, 8),
317 m_outfile_options (),
319 m_next_addr(LLDB_INVALID_ADDRESS),
321 m_prev_format_options (eFormatBytesWithASCII, 1, 8),
322 m_prev_memory_options (),
323 m_prev_outfile_options (),
324 m_prev_varobj_options()
326 CommandArgumentEntry arg1;
327 CommandArgumentEntry arg2;
328 CommandArgumentData start_addr_arg;
329 CommandArgumentData end_addr_arg;
331 // Define the first (and only) variant of this arg.
332 start_addr_arg.arg_type = eArgTypeAddressOrExpression;
333 start_addr_arg.arg_repetition = eArgRepeatPlain;
335 // There is only one variant this argument could be; put it into the argument entry.
336 arg1.push_back (start_addr_arg);
338 // Define the first (and only) variant of this arg.
339 end_addr_arg.arg_type = eArgTypeAddressOrExpression;
340 end_addr_arg.arg_repetition = eArgRepeatOptional;
342 // There is only one variant this argument could be; put it into the argument entry.
343 arg2.push_back (end_addr_arg);
345 // Push the data for the first argument into the m_arguments vector.
346 m_arguments.push_back (arg1);
347 m_arguments.push_back (arg2);
349 // Add the "--format" and "--count" options to group 1 and 3
350 m_option_group.Append (&m_format_options,
351 OptionGroupFormat::OPTION_GROUP_FORMAT | OptionGroupFormat::OPTION_GROUP_COUNT,
352 LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
353 m_option_group.Append (&m_format_options,
354 OptionGroupFormat::OPTION_GROUP_GDB_FMT,
355 LLDB_OPT_SET_1 | LLDB_OPT_SET_3);
356 // Add the "--size" option to group 1 and 2
357 m_option_group.Append (&m_format_options,
358 OptionGroupFormat::OPTION_GROUP_SIZE,
359 LLDB_OPT_SET_1 | LLDB_OPT_SET_2);
360 m_option_group.Append (&m_memory_options);
361 m_option_group.Append (&m_outfile_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3);
362 m_option_group.Append (&m_varobj_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_3);
363 m_option_group.Finalize();
367 ~CommandObjectMemoryRead ()
374 return &m_option_group;
377 virtual const char *GetRepeatCommand (Args ¤t_command_args, uint32_t index)
379 return m_cmd_name.c_str();
384 DoExecute (Args& command, CommandReturnObject &result)
386 // No need to check "target" for validity as eFlagRequiresTarget ensures it is valid
387 Target *target = m_exe_ctx.GetTargetPtr();
389 const size_t argc = command.GetArgumentCount();
391 if ((argc == 0 && m_next_addr == LLDB_INVALID_ADDRESS) || argc > 2)
393 result.AppendErrorWithFormat ("%s takes a start address expression with an optional end address expression.\n", m_cmd_name.c_str());
394 result.AppendRawWarning("Expressions should be quoted if they contain spaces or other special characters.\n");
395 result.SetStatus(eReturnStatusFailed);
399 ClangASTType clang_ast_type;
402 const char *view_as_type_cstr = m_memory_options.m_view_as_type.GetCurrentValue();
403 if (view_as_type_cstr && view_as_type_cstr[0])
405 // We are viewing memory as a type
408 const bool exact_match = false;
410 uint32_t reference_count = 0;
411 uint32_t pointer_count = 0;
414 #define ALL_KEYWORDS \
416 KEYWORD("volatile") \
417 KEYWORD("restrict") \
422 #define KEYWORD(s) s,
423 static const char *g_keywords[] =
429 #define KEYWORD(s) (sizeof(s) - 1),
430 static const int g_keyword_lengths[] =
438 static size_t g_num_keywords = sizeof(g_keywords) / sizeof(const char *);
439 std::string type_str(view_as_type_cstr);
441 // Remove all instances of g_keywords that are followed by spaces
442 for (size_t i = 0; i < g_num_keywords; ++i)
444 const char *keyword = g_keywords[i];
445 int keyword_len = g_keyword_lengths[i];
448 while ((idx = type_str.find (keyword, idx)) != std::string::npos)
450 if (type_str[idx + keyword_len] == ' ' || type_str[idx + keyword_len] == '\t')
452 type_str.erase(idx, keyword_len+1);
461 bool done = type_str.empty();
463 idx = type_str.find_first_not_of (" \t");
464 if (idx > 0 && idx != std::string::npos)
465 type_str.erase (0, idx);
468 // Strip trailing spaces
469 if (type_str.empty())
473 switch (type_str[type_str.size()-1])
480 type_str.erase(type_str.size()-1);
484 if (reference_count == 0)
487 type_str.erase(type_str.size()-1);
491 result.AppendErrorWithFormat ("invalid type string: '%s'\n", view_as_type_cstr);
492 result.SetStatus(eReturnStatusFailed);
504 ConstString lookup_type_name(type_str.c_str());
505 StackFrame *frame = m_exe_ctx.GetFramePtr();
508 sc = frame->GetSymbolContext (eSymbolContextModule);
511 sc.module_sp->FindTypes (sc,
518 if (type_list.GetSize() == 0)
520 target->GetImages().FindTypes (sc,
527 if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && *lookup_type_name.GetCString() == '$')
529 clang::TypeDecl *tdecl = target->GetPersistentVariables().GetPersistentType(ConstString(lookup_type_name));
532 clang_ast_type.SetClangType(&tdecl->getASTContext(),(lldb::clang_type_t)tdecl->getTypeForDecl());
536 if (clang_ast_type.IsValid() == false)
538 if (type_list.GetSize() == 0)
540 result.AppendErrorWithFormat ("unable to find any types that match the raw type '%s' for full type '%s'\n",
541 lookup_type_name.GetCString(),
543 result.SetStatus(eReturnStatusFailed);
548 TypeSP type_sp (type_list.GetTypeAtIndex(0));
549 clang_ast_type = type_sp->GetClangFullType();
553 while (pointer_count > 0)
555 ClangASTType pointer_type = clang_ast_type.GetPointerType();
556 if (pointer_type.IsValid())
557 clang_ast_type = pointer_type;
560 result.AppendError ("unable make a pointer type\n");
561 result.SetStatus(eReturnStatusFailed);
567 m_format_options.GetByteSizeValue() = clang_ast_type.GetByteSize();
569 if (m_format_options.GetByteSizeValue() == 0)
571 result.AppendErrorWithFormat ("unable to get the byte size of the type '%s'\n",
573 result.SetStatus(eReturnStatusFailed);
577 if (!m_format_options.GetCountValue().OptionWasSet())
578 m_format_options.GetCountValue() = 1;
582 error = m_memory_options.FinalizeSettings (target, m_format_options);
585 // Look for invalid combinations of settings
588 result.AppendError(error.AsCString());
589 result.SetStatus(eReturnStatusFailed);
594 size_t total_byte_size = 0;
597 // Use the last address and byte size and all options as they were
598 // if no options have been set
600 total_byte_size = m_prev_byte_size;
601 clang_ast_type = m_prev_clang_ast_type;
602 if (!m_format_options.AnyOptionWasSet() &&
603 !m_memory_options.AnyOptionWasSet() &&
604 !m_outfile_options.AnyOptionWasSet() &&
605 !m_varobj_options.AnyOptionWasSet())
607 m_format_options = m_prev_format_options;
608 m_memory_options = m_prev_memory_options;
609 m_outfile_options = m_prev_outfile_options;
610 m_varobj_options = m_prev_varobj_options;
614 size_t item_count = m_format_options.GetCountValue().GetCurrentValue();
615 size_t item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
616 const size_t num_per_line = m_memory_options.m_num_per_line.GetCurrentValue();
618 if (total_byte_size == 0)
620 total_byte_size = item_count * item_byte_size;
621 if (total_byte_size == 0)
622 total_byte_size = 32;
626 addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, &error);
628 if (addr == LLDB_INVALID_ADDRESS)
630 result.AppendError("invalid start address expression.");
631 result.AppendError(error.AsCString());
632 result.SetStatus(eReturnStatusFailed);
638 lldb::addr_t end_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
639 if (end_addr == LLDB_INVALID_ADDRESS)
641 result.AppendError("invalid end address expression.");
642 result.AppendError(error.AsCString());
643 result.SetStatus(eReturnStatusFailed);
646 else if (end_addr <= addr)
648 result.AppendErrorWithFormat("end address (0x%" PRIx64 ") must be greater that the start address (0x%" PRIx64 ").\n", end_addr, addr);
649 result.SetStatus(eReturnStatusFailed);
652 else if (m_format_options.GetCountValue().OptionWasSet())
654 result.AppendErrorWithFormat("specify either the end address (0x%" PRIx64 ") or the count (--count %zu), not both.\n", end_addr, item_count);
655 result.SetStatus(eReturnStatusFailed);
659 total_byte_size = end_addr - addr;
660 item_count = total_byte_size / item_byte_size;
663 uint32_t max_unforced_size = target->GetMaximumMemReadSize();
665 if (total_byte_size > max_unforced_size && !m_memory_options.m_force)
667 result.AppendErrorWithFormat("Normally, \'memory read\' will not read over %" PRIu32 " bytes of data.\n",max_unforced_size);
668 result.AppendErrorWithFormat("Please use --force to override this restriction just once.\n");
669 result.AppendErrorWithFormat("or set target.max-memory-read-size if you will often need a larger limit.\n");
673 DataBufferSP data_sp;
674 size_t bytes_read = 0;
675 if (clang_ast_type.GetOpaqueQualType())
677 // Make sure we don't display our type as ASCII bytes like the default memory read
678 if (m_format_options.GetFormatValue().OptionWasSet() == false)
679 m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault);
681 bytes_read = clang_ast_type.GetByteSize() * m_format_options.GetCountValue().GetCurrentValue();
683 else if (m_format_options.GetFormatValue().GetCurrentValue() != eFormatCString)
685 data_sp.reset (new DataBufferHeap (total_byte_size, '\0'));
686 if (data_sp->GetBytes() == NULL)
688 result.AppendErrorWithFormat ("can't allocate 0x%zx bytes for the memory read buffer, specify a smaller size to read", total_byte_size);
689 result.SetStatus(eReturnStatusFailed);
693 Address address(addr, NULL);
694 bytes_read = target->ReadMemory(address, false, data_sp->GetBytes (), data_sp->GetByteSize(), error);
697 const char *error_cstr = error.AsCString();
698 if (error_cstr && error_cstr[0])
700 result.AppendError(error_cstr);
704 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
706 result.SetStatus(eReturnStatusFailed);
710 if (bytes_read < total_byte_size)
711 result.AppendWarningWithFormat("Not all bytes (%zu/%zu) were able to be read from 0x%" PRIx64 ".\n", bytes_read, total_byte_size, addr);
715 // we treat c-strings as a special case because they do not have a fixed size
716 if (m_format_options.GetByteSizeValue().OptionWasSet() && !m_format_options.HasGDBFormat())
717 item_byte_size = m_format_options.GetByteSizeValue().GetCurrentValue();
719 item_byte_size = target->GetMaximumSizeOfStringSummary();
720 if (!m_format_options.GetCountValue().OptionWasSet())
722 data_sp.reset (new DataBufferHeap ((item_byte_size+1) * item_count, '\0')); // account for NULLs as necessary
723 if (data_sp->GetBytes() == NULL)
725 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));
726 result.SetStatus(eReturnStatusFailed);
729 uint8_t *data_ptr = data_sp->GetBytes();
730 auto data_addr = addr;
731 auto count = item_count;
733 while (item_count < count)
736 buffer.resize(item_byte_size+1,0);
738 size_t read = target->ReadCStringFromMemory(data_addr, &buffer[0], item_byte_size+1, error);
741 result.AppendErrorWithFormat("failed to read memory from 0x%" PRIx64 ".\n", addr);
742 result.SetStatus(eReturnStatusFailed);
745 if (item_byte_size == read)
747 result.AppendWarningWithFormat("unable to find a NULL terminated string at 0x%" PRIx64 ".Consider increasing the maximum read length.\n", data_addr);
750 read+=1; // account for final NULL byte
751 memcpy(data_ptr, &buffer[0], read);
755 item_count++; // if we break early we know we only read item_count strings
757 data_sp.reset(new DataBufferHeap(data_sp->GetBytes(),bytes_read+1));
760 m_next_addr = addr + bytes_read;
761 m_prev_byte_size = bytes_read;
762 m_prev_format_options = m_format_options;
763 m_prev_memory_options = m_memory_options;
764 m_prev_outfile_options = m_outfile_options;
765 m_prev_varobj_options = m_varobj_options;
766 m_prev_clang_ast_type = clang_ast_type;
768 StreamFile outfile_stream;
769 Stream *output_stream = NULL;
770 const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue();
774 outfile_spec.GetPath (path, sizeof(path));
776 uint32_t open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate;
777 const bool append = m_outfile_options.GetAppend().GetCurrentValue();
779 open_options |= File::eOpenOptionAppend;
781 if (outfile_stream.GetFile ().Open (path, open_options).Success())
783 if (m_memory_options.m_output_as_binary)
785 const size_t bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
786 if (bytes_written > 0)
788 result.GetOutputStream().Printf ("%zi bytes %s to '%s'\n",
790 append ? "appended" : "written",
796 result.AppendErrorWithFormat("Failed to write %" PRIu64 " bytes to '%s'.\n", (uint64_t)bytes_read, path);
797 result.SetStatus(eReturnStatusFailed);
803 // We are going to write ASCII to the file just point the
804 // output_stream to our outfile_stream...
805 output_stream = &outfile_stream;
810 result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", path, append ? "append" : "write");
811 result.SetStatus(eReturnStatusFailed);
817 output_stream = &result.GetOutputStream();
821 ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope();
822 if (clang_ast_type.GetOpaqueQualType())
824 for (uint32_t i = 0; i<item_count; ++i)
826 addr_t item_addr = addr + (i * item_byte_size);
827 Address address (item_addr);
828 StreamString name_strm;
829 name_strm.Printf ("0x%" PRIx64, item_addr);
830 ValueObjectSP valobj_sp (ValueObjectMemory::Create (exe_scope,
831 name_strm.GetString().c_str(),
836 Format format = m_format_options.GetFormat();
837 if (format != eFormatDefault)
838 valobj_sp->SetFormat (format);
840 DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions(eLanguageRuntimeDescriptionDisplayVerbosityFull,format));
842 valobj_sp->Dump(*output_stream,options);
846 result.AppendErrorWithFormat ("failed to create a value object for: (%s) %s\n",
848 name_strm.GetString().c_str());
849 result.SetStatus(eReturnStatusFailed);
856 result.SetStatus(eReturnStatusSuccessFinishResult);
857 DataExtractor data (data_sp,
858 target->GetArchitecture().GetByteOrder(),
859 target->GetArchitecture().GetAddressByteSize());
861 Format format = m_format_options.GetFormat();
862 if ( ( (format == eFormatChar) || (format == eFormatCharPrintable) )
863 && (item_byte_size != 1))
865 // if a count was not passed, or it is 1
866 if (m_format_options.GetCountValue().OptionWasSet() == false || item_count == 1)
868 // this turns requests such as
869 // memory read -fc -s10 -c1 *charPtrPtr
870 // which make no sense (what is a char of size 10?)
871 // into a request for fetching 10 chars of size 1 from the same memory location
872 format = eFormatCharArray;
873 item_count = item_byte_size;
878 // here we passed a count, and it was not 1
879 // so we have a byte_size and a count
880 // we could well multiply those, but instead let's just fail
881 result.AppendErrorWithFormat("reading memory as characters of size %zu is not supported", item_byte_size);
882 result.SetStatus(eReturnStatusFailed);
887 assert (output_stream);
888 size_t bytes_dumped = data.Dump (output_stream,
898 m_next_addr = addr + bytes_dumped;
899 output_stream->EOL();
903 OptionGroupOptions m_option_group;
904 OptionGroupFormat m_format_options;
905 OptionGroupReadMemory m_memory_options;
906 OptionGroupOutputFile m_outfile_options;
907 OptionGroupValueObjectDisplay m_varobj_options;
908 lldb::addr_t m_next_addr;
909 lldb::addr_t m_prev_byte_size;
910 OptionGroupFormat m_prev_format_options;
911 OptionGroupReadMemory m_prev_memory_options;
912 OptionGroupOutputFile m_prev_outfile_options;
913 OptionGroupValueObjectDisplay m_prev_varobj_options;
914 ClangASTType m_prev_clang_ast_type;
918 g_memory_find_option_table[] =
920 { LLDB_OPT_SET_1, false, "expression", 'e', OptionParser::eRequiredArgument, NULL, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."},
921 { LLDB_OPT_SET_2, false, "string", 's', OptionParser::eRequiredArgument, NULL, 0, eArgTypeName, "Use text to find a byte pattern."},
922 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "count", 'c', OptionParser::eRequiredArgument, NULL, 0, eArgTypeCount, "How many times to perform the search."},
923 { LLDB_OPT_SET_1|LLDB_OPT_SET_2, false, "dump-offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."},
926 //----------------------------------------------------------------------
927 // Find the specified data in memory
928 //----------------------------------------------------------------------
929 class CommandObjectMemoryFind : public CommandObjectParsed
933 class OptionGroupFindMemory : public OptionGroup
936 OptionGroupFindMemory () :
944 ~OptionGroupFindMemory ()
951 return sizeof (g_memory_find_option_table) / sizeof (OptionDefinition);
954 virtual const OptionDefinition*
957 return g_memory_find_option_table;
961 SetOptionValue (CommandInterpreter &interpreter,
963 const char *option_arg)
966 const int short_option = g_memory_find_option_table[option_idx].short_option;
968 switch (short_option)
971 m_expr.SetValueFromCString(option_arg);
975 m_string.SetValueFromCString(option_arg);
979 if (m_count.SetValueFromCString(option_arg).Fail())
980 error.SetErrorString("unrecognized value for count");
984 if (m_offset.SetValueFromCString(option_arg).Fail())
985 error.SetErrorString("unrecognized value for dump-offset");
989 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
996 OptionParsingStarting (CommandInterpreter &interpreter)
1003 OptionValueString m_expr;
1004 OptionValueString m_string;
1005 OptionValueUInt64 m_count;
1006 OptionValueUInt64 m_offset;
1009 CommandObjectMemoryFind (CommandInterpreter &interpreter) :
1010 CommandObjectParsed (interpreter,
1012 "Find a value in the memory of the process being debugged.",
1014 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1015 m_option_group (interpreter),
1018 CommandArgumentEntry arg1;
1019 CommandArgumentEntry arg2;
1020 CommandArgumentData addr_arg;
1021 CommandArgumentData value_arg;
1023 // Define the first (and only) variant of this arg.
1024 addr_arg.arg_type = eArgTypeAddress;
1025 addr_arg.arg_repetition = eArgRepeatPlain;
1027 // There is only one variant this argument could be; put it into the argument entry.
1028 arg1.push_back (addr_arg);
1030 // Define the first (and only) variant of this arg.
1031 value_arg.arg_type = eArgTypeValue;
1032 value_arg.arg_repetition = eArgRepeatPlus;
1034 // There is only one variant this argument could be; put it into the argument entry.
1035 arg2.push_back (value_arg);
1037 // Push the data for the first argument into the m_arguments vector.
1038 m_arguments.push_back (arg1);
1039 m_arguments.push_back (arg2);
1041 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1042 m_option_group.Finalize();
1046 ~CommandObjectMemoryFind ()
1053 return &m_option_group;
1058 DoExecute (Args& command, CommandReturnObject &result)
1060 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1061 Process *process = m_exe_ctx.GetProcessPtr();
1063 const size_t argc = command.GetArgumentCount();
1067 result.AppendError("two addresses needed for memory find");
1072 lldb::addr_t low_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(0),LLDB_INVALID_ADDRESS,&error);
1073 if (low_addr == LLDB_INVALID_ADDRESS || error.Fail())
1075 result.AppendError("invalid low address");
1078 lldb::addr_t high_addr = Args::StringToAddress(&m_exe_ctx, command.GetArgumentAtIndex(1),LLDB_INVALID_ADDRESS,&error);
1079 if (high_addr == LLDB_INVALID_ADDRESS || error.Fail())
1081 result.AppendError("invalid low address");
1085 if (high_addr <= low_addr)
1087 result.AppendError("starting address must be smaller than ending address");
1091 lldb::addr_t found_location = LLDB_INVALID_ADDRESS;
1093 DataBufferHeap buffer;
1095 if (m_memory_options.m_string.OptionWasSet())
1096 buffer.CopyData(m_memory_options.m_string.GetStringValue(), strlen(m_memory_options.m_string.GetStringValue()));
1097 else if (m_memory_options.m_expr.OptionWasSet())
1099 StackFrame* frame = m_exe_ctx.GetFramePtr();
1100 ValueObjectSP result_sp;
1101 if (process->GetTarget().EvaluateExpression(m_memory_options.m_expr.GetStringValue(), frame, result_sp) && result_sp.get())
1103 uint64_t value = result_sp->GetValueAsUnsigned(0);
1104 switch (result_sp->GetClangType().GetByteSize())
1107 uint8_t byte = (uint8_t)value;
1108 buffer.CopyData(&byte,1);
1112 uint16_t word = (uint16_t)value;
1113 buffer.CopyData(&word,2);
1117 uint32_t lword = (uint32_t)value;
1118 buffer.CopyData(&lword,4);
1122 buffer.CopyData(&value, 8);
1129 result.AppendError("unknown type. pass a string instead");
1132 result.AppendError("do not know how to deal with larger than 8 byte result types. pass a string instead");
1138 result.AppendError("expression evaluation failed. pass a string instead?");
1144 result.AppendError("please pass either a block of text, or an expression to evaluate.");
1148 size_t count = m_memory_options.m_count.GetCurrentValue();
1149 found_location = low_addr;
1150 bool ever_found = false;
1153 found_location = Search(found_location, high_addr, buffer.GetBytes(), buffer.GetByteSize());
1154 if (found_location == LLDB_INVALID_ADDRESS)
1158 result.AppendMessage("Your data was not found within the range.\n");
1159 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult);
1162 result.AppendMessage("No more matches found within the range.\n");
1165 result.AppendMessageWithFormat("Your data was found at location: 0x%" PRIx64 "\n", found_location);
1167 DataBufferHeap dumpbuffer(32,0);
1168 process->ReadMemory(found_location+m_memory_options.m_offset.GetCurrentValue(), dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), error);
1171 DataExtractor data(dumpbuffer.GetBytes(), dumpbuffer.GetByteSize(), process->GetByteOrder(), process->GetAddressByteSize());
1172 data.Dump(&result.GetOutputStream(), 0, lldb::eFormatBytesWithASCII, 1, dumpbuffer.GetByteSize(), 16, found_location+m_memory_options.m_offset.GetCurrentValue(), 0, 0);
1173 result.GetOutputStream().EOL();
1181 result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1186 Search (lldb::addr_t low,
1191 Process *process = m_exe_ctx.GetProcessPtr();
1192 DataBufferHeap heap(buffer_size, 0);
1193 lldb::addr_t fictional_ptr = low;
1194 for (auto ptr = low;
1199 if (ptr == low || buffer_size == 1)
1200 process->ReadMemory(ptr, heap.GetBytes(), buffer_size, error);
1203 memmove(heap.GetBytes(), heap.GetBytes()+1, buffer_size-1);
1204 process->ReadMemory(ptr, heap.GetBytes()+buffer_size-1, 1, error);
1207 return LLDB_INVALID_ADDRESS;
1208 if (memcmp(heap.GetBytes(), buffer, buffer_size) == 0)
1209 return fictional_ptr;
1215 return LLDB_INVALID_ADDRESS;
1218 OptionGroupOptions m_option_group;
1219 OptionGroupFindMemory m_memory_options;
1224 g_memory_write_option_table[] =
1226 { LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, NULL, 0, eArgTypeFilename, "Write memory using the contents of a file."},
1227 { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, NULL, 0, eArgTypeOffset, "Start writng bytes from an offset within the input file."},
1230 //----------------------------------------------------------------------
1231 // Write memory to the inferior process
1232 //----------------------------------------------------------------------
1233 class CommandObjectMemoryWrite : public CommandObjectParsed
1237 class OptionGroupWriteMemory : public OptionGroup
1240 OptionGroupWriteMemory () :
1246 ~OptionGroupWriteMemory ()
1251 GetNumDefinitions ()
1253 return sizeof (g_memory_write_option_table) / sizeof (OptionDefinition);
1256 virtual const OptionDefinition*
1259 return g_memory_write_option_table;
1263 SetOptionValue (CommandInterpreter &interpreter,
1264 uint32_t option_idx,
1265 const char *option_arg)
1268 const int short_option = g_memory_write_option_table[option_idx].short_option;
1270 switch (short_option)
1273 m_infile.SetFile (option_arg, true);
1274 if (!m_infile.Exists())
1277 error.SetErrorStringWithFormat("input file does not exist: '%s'", option_arg);
1284 m_infile_offset = Args::StringToUInt64(option_arg, 0, 0, &success);
1287 error.SetErrorStringWithFormat("invalid offset string '%s'", option_arg);
1293 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option);
1300 OptionParsingStarting (CommandInterpreter &interpreter)
1303 m_infile_offset = 0;
1307 off_t m_infile_offset;
1310 CommandObjectMemoryWrite (CommandInterpreter &interpreter) :
1311 CommandObjectParsed (interpreter,
1313 "Write to the memory of the process being debugged.",
1315 eFlagRequiresProcess | eFlagProcessMustBeLaunched),
1316 m_option_group (interpreter),
1317 m_format_options (eFormatBytes, 1, UINT64_MAX),
1320 CommandArgumentEntry arg1;
1321 CommandArgumentEntry arg2;
1322 CommandArgumentData addr_arg;
1323 CommandArgumentData value_arg;
1325 // Define the first (and only) variant of this arg.
1326 addr_arg.arg_type = eArgTypeAddress;
1327 addr_arg.arg_repetition = eArgRepeatPlain;
1329 // There is only one variant this argument could be; put it into the argument entry.
1330 arg1.push_back (addr_arg);
1332 // Define the first (and only) variant of this arg.
1333 value_arg.arg_type = eArgTypeValue;
1334 value_arg.arg_repetition = eArgRepeatPlus;
1336 // There is only one variant this argument could be; put it into the argument entry.
1337 arg2.push_back (value_arg);
1339 // Push the data for the first argument into the m_arguments vector.
1340 m_arguments.push_back (arg1);
1341 m_arguments.push_back (arg2);
1343 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_FORMAT, LLDB_OPT_SET_1);
1344 m_option_group.Append (&m_format_options, OptionGroupFormat::OPTION_GROUP_SIZE , LLDB_OPT_SET_1|LLDB_OPT_SET_2);
1345 m_option_group.Append (&m_memory_options, LLDB_OPT_SET_ALL, LLDB_OPT_SET_2);
1346 m_option_group.Finalize();
1351 ~CommandObjectMemoryWrite ()
1358 return &m_option_group;
1362 UIntValueIsValidForSize (uint64_t uval64, size_t total_byte_size)
1364 if (total_byte_size > 8)
1367 if (total_byte_size == 8)
1370 const uint64_t max = ((uint64_t)1 << (uint64_t)(total_byte_size * 8)) - 1;
1371 return uval64 <= max;
1375 SIntValueIsValidForSize (int64_t sval64, size_t total_byte_size)
1377 if (total_byte_size > 8)
1380 if (total_byte_size == 8)
1383 const int64_t max = ((int64_t)1 << (uint64_t)(total_byte_size * 8 - 1)) - 1;
1384 const int64_t min = ~(max);
1385 return min <= sval64 && sval64 <= max;
1390 DoExecute (Args& command, CommandReturnObject &result)
1392 // No need to check "process" for validity as eFlagRequiresProcess ensures it is valid
1393 Process *process = m_exe_ctx.GetProcessPtr();
1395 const size_t argc = command.GetArgumentCount();
1397 if (m_memory_options.m_infile)
1401 result.AppendErrorWithFormat ("%s takes a destination address when writing file contents.\n", m_cmd_name.c_str());
1402 result.SetStatus(eReturnStatusFailed);
1408 result.AppendErrorWithFormat ("%s takes a destination address and at least one value.\n", m_cmd_name.c_str());
1409 result.SetStatus(eReturnStatusFailed);
1413 StreamString buffer (Stream::eBinary,
1414 process->GetTarget().GetArchitecture().GetAddressByteSize(),
1415 process->GetTarget().GetArchitecture().GetByteOrder());
1417 OptionValueUInt64 &byte_size_value = m_format_options.GetByteSizeValue();
1418 size_t item_byte_size = byte_size_value.GetCurrentValue();
1421 lldb::addr_t addr = Args::StringToAddress (&m_exe_ctx,
1422 command.GetArgumentAtIndex(0),
1423 LLDB_INVALID_ADDRESS,
1426 if (addr == LLDB_INVALID_ADDRESS)
1428 result.AppendError("invalid address expression\n");
1429 result.AppendError(error.AsCString());
1430 result.SetStatus(eReturnStatusFailed);
1434 if (m_memory_options.m_infile)
1436 size_t length = SIZE_MAX;
1437 if (item_byte_size > 0)
1438 length = item_byte_size;
1439 lldb::DataBufferSP data_sp (m_memory_options.m_infile.ReadFileContents (m_memory_options.m_infile_offset, length));
1442 length = data_sp->GetByteSize();
1446 size_t bytes_written = process->WriteMemory (addr, data_sp->GetBytes(), length, error);
1448 if (bytes_written == length)
1450 // All bytes written
1451 result.GetOutputStream().Printf("%" PRIu64 " bytes were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, addr);
1452 result.SetStatus(eReturnStatusSuccessFinishResult);
1454 else if (bytes_written > 0)
1456 // Some byte written
1457 result.GetOutputStream().Printf("%" PRIu64 " bytes of %" PRIu64 " requested were written to 0x%" PRIx64 "\n", (uint64_t)bytes_written, (uint64_t)length, addr);
1458 result.SetStatus(eReturnStatusSuccessFinishResult);
1462 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1463 result.SetStatus(eReturnStatusFailed);
1469 result.AppendErrorWithFormat ("Unable to read contents of file.\n");
1470 result.SetStatus(eReturnStatusFailed);
1472 return result.Succeeded();
1474 else if (item_byte_size == 0)
1476 if (m_format_options.GetFormat() == eFormatPointer)
1477 item_byte_size = buffer.GetAddressByteSize();
1482 command.Shift(); // shift off the address argument
1485 bool success = false;
1486 const size_t num_value_args = command.GetArgumentCount();
1487 for (size_t i=0; i<num_value_args; ++i)
1489 const char *value_str = command.GetArgumentAtIndex(i);
1491 switch (m_format_options.GetFormat())
1494 case eFormatFloat: // TODO: add support for floats soon
1495 case eFormatCharPrintable:
1496 case eFormatBytesWithASCII:
1497 case eFormatComplex:
1499 case eFormatUnicode16:
1500 case eFormatUnicode32:
1501 case eFormatVectorOfChar:
1502 case eFormatVectorOfSInt8:
1503 case eFormatVectorOfUInt8:
1504 case eFormatVectorOfSInt16:
1505 case eFormatVectorOfUInt16:
1506 case eFormatVectorOfSInt32:
1507 case eFormatVectorOfUInt32:
1508 case eFormatVectorOfSInt64:
1509 case eFormatVectorOfUInt64:
1510 case eFormatVectorOfFloat32:
1511 case eFormatVectorOfFloat64:
1512 case eFormatVectorOfUInt128:
1514 case eFormatComplexInteger:
1515 case eFormatAddressInfo:
1516 case eFormatHexFloat:
1517 case eFormatInstruction:
1519 result.AppendError("unsupported format for writing memory");
1520 result.SetStatus(eReturnStatusFailed);
1523 case eFormatDefault:
1526 case eFormatHexUppercase:
1527 case eFormatPointer:
1530 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 16, &success);
1533 result.AppendErrorWithFormat ("'%s' is not a valid hex string value.\n", value_str);
1534 result.SetStatus(eReturnStatusFailed);
1537 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1539 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
1540 result.SetStatus(eReturnStatusFailed);
1543 buffer.PutMaxHex64 (uval64, item_byte_size);
1546 case eFormatBoolean:
1547 uval64 = Args::StringToBoolean(value_str, false, &success);
1550 result.AppendErrorWithFormat ("'%s' is not a valid boolean string value.\n", value_str);
1551 result.SetStatus(eReturnStatusFailed);
1554 buffer.PutMaxHex64 (uval64, item_byte_size);
1558 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 2, &success);
1561 result.AppendErrorWithFormat ("'%s' is not a valid binary string value.\n", value_str);
1562 result.SetStatus(eReturnStatusFailed);
1565 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1567 result.AppendErrorWithFormat ("Value 0x%" PRIx64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
1568 result.SetStatus(eReturnStatusFailed);
1571 buffer.PutMaxHex64 (uval64, item_byte_size);
1574 case eFormatCharArray:
1576 case eFormatCString:
1579 size_t len = strlen (value_str);
1580 // Include the NULL for C strings...
1581 if (m_format_options.GetFormat() == eFormatCString)
1584 if (process->WriteMemory (addr, value_str, len, error) == len)
1590 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1591 result.SetStatus(eReturnStatusFailed);
1597 case eFormatDecimal:
1598 sval64 = Args::StringToSInt64(value_str, INT64_MAX, 0, &success);
1601 result.AppendErrorWithFormat ("'%s' is not a valid signed decimal value.\n", value_str);
1602 result.SetStatus(eReturnStatusFailed);
1605 else if (!SIntValueIsValidForSize (sval64, item_byte_size))
1607 result.AppendErrorWithFormat ("Value %" PRIi64 " is too large or small to fit in a %zu byte signed integer value.\n", sval64, item_byte_size);
1608 result.SetStatus(eReturnStatusFailed);
1611 buffer.PutMaxHex64 (sval64, item_byte_size);
1614 case eFormatUnsigned:
1615 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 0, &success);
1618 result.AppendErrorWithFormat ("'%s' is not a valid unsigned decimal string value.\n", value_str);
1619 result.SetStatus(eReturnStatusFailed);
1622 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1624 result.AppendErrorWithFormat ("Value %" PRIu64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
1625 result.SetStatus(eReturnStatusFailed);
1628 buffer.PutMaxHex64 (uval64, item_byte_size);
1632 uval64 = Args::StringToUInt64(value_str, UINT64_MAX, 8, &success);
1635 result.AppendErrorWithFormat ("'%s' is not a valid octal string value.\n", value_str);
1636 result.SetStatus(eReturnStatusFailed);
1639 else if (!UIntValueIsValidForSize (uval64, item_byte_size))
1641 result.AppendErrorWithFormat ("Value %" PRIo64 " is too large to fit in a %zu byte unsigned integer value.\n", uval64, item_byte_size);
1642 result.SetStatus(eReturnStatusFailed);
1645 buffer.PutMaxHex64 (uval64, item_byte_size);
1650 if (!buffer.GetString().empty())
1653 if (process->WriteMemory (addr, buffer.GetString().c_str(), buffer.GetString().size(), error) == buffer.GetString().size())
1657 result.AppendErrorWithFormat ("Memory write to 0x%" PRIx64 " failed: %s.\n", addr, error.AsCString());
1658 result.SetStatus(eReturnStatusFailed);
1665 OptionGroupOptions m_option_group;
1666 OptionGroupFormat m_format_options;
1667 OptionGroupWriteMemory m_memory_options;
1671 //-------------------------------------------------------------------------
1672 // CommandObjectMemory
1673 //-------------------------------------------------------------------------
1675 CommandObjectMemory::CommandObjectMemory (CommandInterpreter &interpreter) :
1676 CommandObjectMultiword (interpreter,
1678 "A set of commands for operating on memory.",
1679 "memory <subcommand> [<subcommand-options>]")
1681 LoadSubCommand ("find", CommandObjectSP (new CommandObjectMemoryFind (interpreter)));
1682 LoadSubCommand ("read", CommandObjectSP (new CommandObjectMemoryRead (interpreter)));
1683 LoadSubCommand ("write", CommandObjectSP (new CommandObjectMemoryWrite (interpreter)));
1686 CommandObjectMemory::~CommandObjectMemory ()